From 1dca5fb4b739068976bb049304fcb0e599b9cbae Mon Sep 17 00:00:00 2001 From: Nikita Levyankov Date: Thu, 18 Dec 2025 12:23:46 +0200 Subject: [PATCH] fix: lint and formatting issues in non-interactive installation PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- docs/non-interactive-installation-guide.md | 44 ++++++++++------- .../installers/lib/core/config-collector.js | 47 ++++++++++++------- tools/cli/installers/lib/core/env-resolver.js | 2 +- .../installers/lib/core/manifest-generator.js | 4 +- .../cli/installers/lib/core/options-parser.js | 20 +++----- .../installers/lib/profiles/definitions.js | 9 +--- tools/cli/installers/lib/teams/team-loader.js | 14 +++--- 7 files changed, 73 insertions(+), 67 deletions(-) diff --git a/docs/non-interactive-installation-guide.md b/docs/non-interactive-installation-guide.md index dd004702..97a27ea3 100644 --- a/docs/non-interactive-installation-guide.md +++ b/docs/non-interactive-installation-guide.md @@ -21,6 +21,7 @@ npx bmad-method@alpha install -y ``` This installs BMAD with: + - Default user name from system (USER environment variable) - Intermediate skill level - Default output folder (`_bmad-output`) @@ -49,10 +50,11 @@ cat _bmad/bmm/config.yaml ``` Example output: + ```yaml user_name: Alice user_skill_level: intermediate -output_folder: "{project-root}/_bmad-output" +output_folder: '{project-root}/_bmad-output' communication_language: English ``` @@ -169,29 +171,29 @@ npx bmad-method@alpha install -y \ ### Core Options -| Option | Description | Default | Example | -|--------|-------------|---------|---------| -| `-y, --non-interactive` | Skip all prompts | `false` | `install -y` | -| `--user-name ` | User name | System user | `--user-name=Alice` | -| `--skill-level ` | Skill level | `intermediate` | `--skill-level=advanced` | -| `--output-folder ` | Output folder | `_bmad-output` | `--output-folder=.artifacts` | -| `--communication-language ` | Communication language | `English` | `--communication-language=Spanish` | -| `--document-language ` | Document language | `English` | `--document-language=French` | +| Option | Description | Default | Example | +| --------------------------------- | ---------------------- | -------------- | ---------------------------------- | +| `-y, --non-interactive` | Skip all prompts | `false` | `install -y` | +| `--user-name ` | User name | System user | `--user-name=Alice` | +| `--skill-level ` | Skill level | `intermediate` | `--skill-level=advanced` | +| `--output-folder ` | Output folder | `_bmad-output` | `--output-folder=.artifacts` | +| `--communication-language ` | Communication language | `English` | `--communication-language=Spanish` | +| `--document-language ` | Document language | `English` | `--document-language=French` | ### Module & Selection Options -| Option | Description | Example | -|--------|-------------|---------| -| `--modules ` | Comma-separated modules | `--modules=core,bmm,bmbb` | -| `--agents ` | Comma-separated agents | `--agents=dev,architect,pm` | +| Option | Description | Example | +| -------------------- | ------------------------- | ---------------------------------- | +| `--modules ` | Comma-separated modules | `--modules=core,bmm,bmbb` | +| `--agents ` | Comma-separated agents | `--agents=dev,architect,pm` | | `--workflows ` | Comma-separated workflows | `--workflows=create-prd,dev-story` | ### Team & Profile Options -| Option | Description | Example | -|--------|-------------|---------| -| `--team ` | Install predefined team | `--team=fullstack` | -| `--profile ` | Installation profile | `--profile=minimal` | +| Option | Description | Example | +| ------------------ | ----------------------- | ------------------- | +| `--team ` | Install predefined team | `--team=fullstack` | +| `--profile ` | Installation profile | `--profile=minimal` | ## Team-Based Installation @@ -206,6 +208,7 @@ npx bmad-method@alpha install -y --team=fullstack ``` **Includes:** + - Agents: analyst, architect, pm, sm, ux-designer - Module: BMM @@ -218,6 +221,7 @@ npx bmad-method@alpha install -y --team=gamedev ``` **Includes:** + - Agents: game-designer, game-dev, game-architect, game-scrum-master - Workflows: brainstorm-game, game-brief, gdd, narrative - Module: BMGD (Game Development) @@ -252,6 +256,7 @@ npx bmad-method@alpha install -y --profile=minimal ``` **Includes:** + - Modules: core - Agents: dev - Workflows: create-tech-spec, quick-dev @@ -265,6 +270,7 @@ npx bmad-method@alpha install -y --profile=solo-dev ``` **Includes:** + - Modules: core, bmm - Agents: dev, architect, analyst, tech-writer - 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:** + - All modules - All agents - All workflows @@ -291,6 +298,7 @@ npx bmad-method@alpha install -y --profile=team ``` **Includes:** + - Modules: core, bmm - 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 @@ -437,4 +445,4 @@ fi ## Feedback Found an issue or have a suggestion? Please report it at: -https://github.com/bmad-code-org/BMAD-METHOD/issues + diff --git a/tools/cli/installers/lib/core/config-collector.js b/tools/cli/installers/lib/core/config-collector.js index 47a155bd..d7e8d3c3 100644 --- a/tools/cli/installers/lib/core/config-collector.js +++ b/tools/cli/installers/lib/core/config-collector.js @@ -885,22 +885,37 @@ class ConfigCollector { // Resolution order: CLI → ENV → existing → default → hardcoded if (moduleName === 'core') { // Core module has special mappings - if (key === 'user_name') { - value = resolveValue(cliOptions.userName, null, envDefaults.userName); - } else if (key === 'user_skill_level') { - value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate'); - } else if (key === 'communication_language') { - value = resolveValue( - cliOptions.communicationLanguage, - null, - envDefaults.communicationLanguage, - ); - } else if (key === 'document_output_language') { - value = resolveValue(cliOptions.documentLanguage, null, envDefaults.documentLanguage); - } else if (key === 'output_folder') { - value = resolveValue(cliOptions.outputFolder, null, item.default); - } else if (item.default !== undefined) { - value = item.default; + switch (key) { + case 'user_name': { + value = resolveValue(cliOptions.userName, null, envDefaults.userName); + + break; + } + case 'user_skill_level': { + value = resolveValue(cliOptions.skillLevel, null, item.default || 'intermediate'); + + break; + } + case 'communication_language': { + value = resolveValue(cliOptions.communicationLanguage, null, envDefaults.communicationLanguage); + + break; + } + 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 { // For other modules, use defaults diff --git a/tools/cli/installers/lib/core/env-resolver.js b/tools/cli/installers/lib/core/env-resolver.js index 12fce4df..8a0d5171 100644 --- a/tools/cli/installers/lib/core/env-resolver.js +++ b/tools/cli/installers/lib/core/env-resolver.js @@ -26,7 +26,7 @@ function getUserName() { if (userInfo.username) { return userInfo.username; } - } catch (error) { + } catch { // os.userInfo() can fail in some environments } diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index f01d46ca..07e521c3 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -161,7 +161,7 @@ class ManifestGenerator { // Wildcard matching: create-* matches create-prd, create-tech-spec, etc. if (pattern.includes('*')) { - const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); + const regex = new RegExp('^' + pattern.replaceAll('*', '.*') + '$'); return regex.test(workflowName); } @@ -318,7 +318,7 @@ class ManifestGenerator { // Wildcard matching: dev* matches dev, dev-story, etc. if (pattern.includes('*')) { - const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); + const regex = new RegExp('^' + pattern.replaceAll('*', '.*') + '$'); return regex.test(agentName); } diff --git a/tools/cli/installers/lib/core/options-parser.js b/tools/cli/installers/lib/core/options-parser.js index 7c159d68..660c4e6f 100644 --- a/tools/cli/installers/lib/core/options-parser.js +++ b/tools/cli/installers/lib/core/options-parser.js @@ -58,9 +58,9 @@ function separateModifiers(list) { for (const item of list) { if (item.startsWith('+')) { - result.add.push(item.substring(1)); + result.add.push(item.slice(1)); } else if (item.startsWith('-')) { - result.remove.push(item.substring(1)); + result.remove.push(item.slice(1)); } else { result.base.push(item); } @@ -118,9 +118,7 @@ function parseOptions(cliOptions) { if (normalized.profile) { const profile = getProfile(normalized.profile); if (!profile) { - throw new Error( - `Unknown profile: ${normalized.profile}. Valid profiles: minimal, full, solo-dev, team`, - ); + throw new Error(`Unknown profile: ${normalized.profile}. Valid profiles: minimal, full, solo-dev, team`); } // Profile provides defaults, but CLI options override @@ -136,9 +134,7 @@ function parseOptions(cliOptions) { normalized.agents = Array.isArray(profile.agents) ? profile.agents : profile.agents; } if (!normalized.workflows) { - normalized.workflows = Array.isArray(profile.workflows) - ? profile.workflows - : profile.workflows; + normalized.workflows = Array.isArray(profile.workflows) ? profile.workflows : profile.workflows; } } @@ -157,9 +153,7 @@ function validateOptions(options) { if (options.skillLevel) { const validLevels = ['beginner', 'intermediate', 'advanced']; if (!validLevels.includes(options.skillLevel.toLowerCase())) { - errors.push( - `Invalid skill level: ${options.skillLevel}. Valid values: beginner, intermediate, advanced`, - ); + errors.push(`Invalid skill level: ${options.skillLevel}. Valid values: beginner, intermediate, advanced`); } } @@ -167,9 +161,7 @@ function validateOptions(options) { if (options.profile) { const validProfiles = ['minimal', 'full', 'solo-dev', 'team']; if (!validProfiles.includes(options.profile.toLowerCase())) { - errors.push( - `Invalid profile: ${options.profile}. Valid values: minimal, full, solo-dev, team`, - ); + errors.push(`Invalid profile: ${options.profile}. Valid values: minimal, full, solo-dev, team`); } } diff --git a/tools/cli/installers/lib/profiles/definitions.js b/tools/cli/installers/lib/profiles/definitions.js index 0a0b0dcd..9109cd91 100644 --- a/tools/cli/installers/lib/profiles/definitions.js +++ b/tools/cli/installers/lib/profiles/definitions.js @@ -28,14 +28,7 @@ const PROFILES = { description: 'Single developer setup - dev tools and planning workflows', modules: ['core', 'bmm'], 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'], }, team: { diff --git a/tools/cli/installers/lib/teams/team-loader.js b/tools/cli/installers/lib/teams/team-loader.js index 9a2403df..0c2c032d 100644 --- a/tools/cli/installers/lib/teams/team-loader.js +++ b/tools/cli/installers/lib/teams/team-loader.js @@ -49,7 +49,7 @@ async function discoverTeams(projectRoot) { } return teams; - } catch (error) { + } catch { // If glob fails, return empty array return []; } @@ -75,9 +75,7 @@ async function loadTeam(teamName, projectRoot) { if (!team) { // Provide helpful error with suggestions const availableTeams = teams.map((t) => t.name).join(', '); - throw new Error( - `Team '${teamName}' not found. Available teams: ${availableTeams || 'none'}`, - ); + throw new Error(`Team '${teamName}' not found. Available teams: ${availableTeams || 'none'}`); } // Load full team definition @@ -130,12 +128,12 @@ function applyTeamModifiers(team, agentModifiers = [], workflowModifiers = []) { // Parse and apply agent modifiers for (const modifier of agentModifiers) { if (modifier.startsWith('+')) { - const agent = modifier.substring(1); + const agent = modifier.slice(1); if (!result.agents.includes(agent)) { result.agents.push(agent); } } else if (modifier.startsWith('-')) { - const agent = modifier.substring(1); + const agent = modifier.slice(1); result.agents = result.agents.filter((a) => a !== agent); } } @@ -143,12 +141,12 @@ function applyTeamModifiers(team, agentModifiers = [], workflowModifiers = []) { // Parse and apply workflow modifiers for (const modifier of workflowModifiers) { if (modifier.startsWith('+')) { - const workflow = modifier.substring(1); + const workflow = modifier.slice(1); if (!result.workflows.includes(workflow)) { result.workflows.push(workflow); } } else if (modifier.startsWith('-')) { - const workflow = modifier.substring(1); + const workflow = modifier.slice(1); result.workflows = result.workflows.filter((w) => w !== workflow); } }