From 40787c50352cdbc1733b8a2ede48192570d7d4f0 Mon Sep 17 00:00:00 2001 From: Dicky Moore Date: Sun, 8 Feb 2026 13:27:10 +0000 Subject: [PATCH] fix: restore help routing and external module install tolerance --- src/core/tasks/help.md | 15 ++++++++++- test/test-installation-components.js | 29 +++++++++++++++++++++ tools/cli/installers/lib/modules/manager.js | 4 +-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/core/tasks/help.md b/src/core/tasks/help.md index e797d4fdc..a2b414400 100644 --- a/src/core/tasks/help.md +++ b/src/core/tasks/help.md @@ -49,10 +49,23 @@ Determine what was just completed: **Required items next** — List the next required workflow For each item show: - Workflow **name** - - **Command** (use the catalog command name; present it in your platform's command format, e.g., `bmad-example-build-prototype`) + - **Command** when `command` is present + - **Agent load instruction + code** when `command` is empty - **Agent** title and display name from the CSV (e.g., "🎨 Alex (Designer)") - Brief **description** + ### Display branching rules + - When `command` has a value: + - Present the command in your platform's command format (for example: `bmad-example-build-prototype`) + - When `command` is empty: + - Do not invent a slash command + - Show how to load the agent from `agent` and then invoke using the workflow/code description + - Example: + - `Explain Concept (EC)` + - `Load: /tech-writer, then ask to "EC about [topic]"` + - `Agent: Tech Writer` + - `Description: Create clear technical explanations with examples` + ### Additional response output guidance to convey: - Run each workflow in a **fresh context window** - Load the agent using the platform's command format for `agent-command`, or run the workflow command directly diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 15fe1a087..eefa1ed4a 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -14,6 +14,7 @@ const path = require('node:path'); const os = require('node:os'); const fs = require('fs-extra'); +const csv = require('csv-parse/sync'); const yaml = require('yaml'); const { YamlXmlBuilder } = require('../tools/cli/lib/yaml-xml-builder'); const { ManifestGenerator } = require('../tools/cli/installers/lib/core/manifest-generator'); @@ -678,6 +679,34 @@ internal: true console.log(''); + // ============================================================ + // Test 17: Help Task Agent-Only Guidance Guard + // ============================================================ + console.log(`${colors.yellow}Test Suite 17: Help Task Agent-Only Guidance Guard${colors.reset}\n`); + + try { + const helpTaskPath = path.join(projectRoot, 'src', 'core', 'tasks', 'help.md'); + const moduleHelpPath = path.join(projectRoot, 'src', 'bmm', 'module-help.csv'); + + const helpTaskContent = await fs.readFile(helpTaskPath, 'utf8'); + const moduleHelpRows = csv.parse(await fs.readFile(moduleHelpPath, 'utf8'), { + columns: true, + skip_empty_lines: true, + }); + + const hasAgentOnlyRows = moduleHelpRows.some((row) => !row.command && row.agent); + assert(hasAgentOnlyRows, 'Help catalog includes agent-only rows with empty command values'); + + assert( + helpTaskContent.includes('When `command` is empty') && helpTaskContent.includes('Do not invent a slash command'), + 'Help task includes explicit guidance for agent-only rows without commands', + ); + } catch (error) { + assert(false, 'Help task agent-only guidance guard runs', error.message); + } + + console.log(''); + // ============================================================ // Summary // ============================================================ diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js index f872582b9..26f08037b 100644 --- a/tools/cli/installers/lib/modules/manager.js +++ b/tools/cli/installers/lib/modules/manager.js @@ -416,7 +416,7 @@ class ModuleManager { if (needsDependencyInstall || wasNewClone || nodeModulesMissing) { const installSpinner = ora(`Installing dependencies for ${moduleInfo.name}...`).start(); try { - execSync('npm install --production --no-audit --no-fund --prefer-offline --no-progress', { + execSync('npm install --omit=dev --no-audit --no-fund --no-progress --legacy-peer-deps', { cwd: moduleCacheDir, stdio: 'pipe', timeout: 120_000, // 2 minute timeout @@ -441,7 +441,7 @@ class ModuleManager { if (packageJsonNewer) { const installSpinner = ora(`Installing dependencies for ${moduleInfo.name}...`).start(); try { - execSync('npm install --production --no-audit --no-fund --prefer-offline --no-progress', { + execSync('npm install --omit=dev --no-audit --no-fund --no-progress --legacy-peer-deps', { cwd: moduleCacheDir, stdio: 'pipe', timeout: 120_000, // 2 minute timeout