feat: introduce GitHub Copilot Chat adapter using official BMAD prompt artifacts#2
feat: introduce GitHub Copilot Chat adapter using official BMAD prompt artifacts#2evil0119 wants to merge 16 commits intobmad-code-org:mainfrom
Conversation
Complete implementation of BMAD-METHOD Copilot Chat bridge: - @bmad chat participant with 7 slash commands - claude-code → GitHub Copilot prompt auto-mirror - Official prompt executor (no parsing/reconstruction) - 4-layer architecture: chatBridge → commandRegistry → cliBridge → promptMirror - Production-ready npm publishing pipeline - GitHub Actions CI/CD automation - MIT license Published as bmad-copilot-adapter@0.1.1 on npm registry.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a BMAD Copilot Adapter: a VS Code chat participant and extension, CLI tools and release scripts, command discovery/registry, a CLI bridge, chat-to-BMAD prompt execution (prompt-file use + runtime fallback), prompt-mirroring utilities, TypeScript sources, packaging metadata, and extensive docs and tests. Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(200,200,255,0.5)
participant User
participant CopilotChat as Copilot Chat API
participant ChatBridge
participant CommandRegistry
participant Workspace
participant BmadRuntime
participant LLM
end
User->>CopilotChat: /run <command> [input]
CopilotChat->>ChatBridge: handler(request)
ChatBridge->>CommandRegistry: resolve(command)
CommandRegistry->>Workspace: locate _bmad and prompt files
alt prompt file found
Workspace-->>ChatBridge: prompt file content
ChatBridge->>ChatBridge: strip frontmatter, append user input
else prompt file missing
ChatBridge->>BmadRuntime: buildPrompt(command, userInput)
BmadRuntime-->>ChatBridge: compiled fallback prompt
end
ChatBridge->>LLM: send prompt (stream)
LLM-->>ChatBridge: response stream
ChatBridge->>CopilotChat: stream response
CopilotChat-->>User: rendered response
sequenceDiagram
rect rgba(200,255,200,0.5)
participant VSCode
participant Extension
participant CommandRegistry
participant CliBridge
participant FileSystem
end
VSCode->>Extension: activate(context)
Extension->>CommandRegistry: scan(workspaceRoot)
CommandRegistry->>FileSystem: read CSV manifests & scan .github/prompts
FileSystem-->>CommandRegistry: manifests, promptFiles
CommandRegistry-->>Extension: RegistryState
Extension->>CliBridge: resolveCli(workspaceRoot)
CliBridge->>FileSystem: check local node_modules/.bin/bmad
alt CLI local
FileSystem-->>CliBridge: cli path
else fallback
CliBridge->>CliBridge: use npx bmad-method
end
Extension->>VSCode: register chat participant `bmad`
Extension->>Extension: setup file watchers -> rescan on changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 17
🤖 Fix all issues with AI agents
In `@bmad-copilot/.github/workflows/release.yml`:
- Around line 53-75: The workflow currently runs the ci-check and
build-and-publish jobs in parallel; update the build-and-publish job to depend
on ci-check by adding a needs: ci-check declaration so publishing waits for the
cross-platform CI matrix to succeed (refer to the job names ci-check and
build-and-publish to locate where to add the dependency).
- Around line 11-51: The workflow runs npm/npx from the repo root so steps like
"Install dependencies", "Build", "Type-check", "Publish to npm", "Publish to VS
Code Marketplace", and "Package VSIX" will fail if the extension lives in
bmad-copilot/; update the build-and-publish job to set a working-directory (e.g.
add defaults.run.working-directory: bmad-copilot or set with with run steps'
working-directory) so all npm/npx commands execute in the package folder, and
apply the same defaults.run.working-directory change to the ci-check job to keep
consistency.
In `@bmad-copilot/ARCHITECTURE.md`:
- Around line 3-6: The ARCHITECTURE.md header has stale metadata: change the
"Version: 2.0.0" entry to match package.json's version "0.1.1" (or update
package.json if the project version should be 2.0.0) and update the "Last
updated: 2025-01" timestamp to the current PR date (e.g., 2026-02) so the
"Version: 2.0.0" and "Last updated: 2025-01" lines are consistent with
package.json and the PR timing.
In `@bmad-copilot/LICENSE`:
- Line 3: Update the copyright year in the LICENSE file by replacing the string
"Copyright (c) 2024 BMAD Code Organization" with the correct year (e.g.,
"Copyright (c) 2026 BMAD Code Organization") so the license reflects the file's
2026 creation date.
In `@bmad-copilot/README.md`:
- Around line 382-390: The README's "Safety & Disclaimer" contains a
contradictory claim: the sentence "does not modify any files in `_bmad/` or
`.github/`" conflicts with the documented prompt mirror behavior that creates
`.github/prompts/` files when missing. Update the README's Safety & Disclaimer
section (the line containing that exact phrase) to accurately state that the
package does not overwrite or modify existing files in `_bmad/` or `.github/`
but will create missing `.github/prompts/` files (and never overwrite them) as
part of the prompt mirror feature; keep the rest of the bullets intact and
ensure the new wording references the prompt mirror behavior and the
non-overwrite guarantee.
In `@bmad-copilot/scripts/release.sh`:
- Around line 1-47: The release.sh script is not marked executable; set the
executable bit for release.sh so it can be run directly (e.g. add a step in CI
or run chmod +x on the script file) — locate the file named release.sh (starts
with the shebang #!/usr/bin/env bash) and ensure its filesystem permissions
include the executable flag for appropriate users (commit the permission
change).
In `@bmad-copilot/src/bmadRuntime.ts`:
- Around line 524-545: buildConfigLoadLine currently embeds the entire
config.yaml into the LLM prompt (and buildStatusPrompt embeds excerpts), which
can leak secrets; update these functions (buildConfigLoadLine and
buildStatusPrompt) to sanitize/redact sensitive keys before including config
content in prompts by parsing the YAML and replacing values for known sensitive
field names (e.g., api_key, apiKey, secret, password, token, access_token,
client_secret) with masked placeholders like "<REDACTED>"; if parsing fails,
fall back to including only the top-level keys or a truncated, non-sensitive
summary (no raw values), and add a short comment documenting that config files
must not contain secrets and that redaction is applied.
In `@bmad-copilot/src/chatBridge.ts`:
- Around line 150-175: The installation guard currently blocks all non-install
commands when registry.state is null, preventing handleStatus from running with
a null state; update the guard so that it exempts the 'status' command (keep the
existing behavior for 'install'), e.g. only show MISSING_INSTALL_MESSAGE and
return when !state AND request.command is neither 'install' nor 'status', then
let the switch call handleStatus(state, stream) which is designed to operate
with a null state.
- Around line 359-369: The JSDoc for the `/run` handler claims prompt files will
"pre-resolve all `{project-root}` file references" and inline their content, but
the buildFromPromptFile implementation currently returns the prompt body as-is;
either update the JSDoc to reflect the real behavior or change
buildFromPromptFile to perform the promised resolution and inlining (resolve
`{project-root}` tokens, read referenced files, replace tokens with file
contents, and return the compiled prompt). Locate the mismatch around the
buildFromPromptFile function used by the `/run <command-name>` handler and
ensure the chosen fix keeps JSDoc and the buildFromPromptFile behavior
consistent.
In `@bmad-copilot/src/cliBridge.ts`:
- Around line 180-195: The openTerminal implementation sends an unescaped
cmdLine via terminal.sendText which breaks when cli.command or workspace paths
contain spaces or shell metacharacters; update openTerminal (and/or add a helper
used by resolveCli) to properly escape/quote cli.command and each element of
fullArgs before joining: wrap paths containing spaces or special chars in quotes
and escape any embedded quotes/metacharacters, e.g., implement an escapeArg(arg:
string) used when building cmdLine to return a safely quoted token for
cli.command and every entry of fullArgs, then call terminal.sendText with the
sanitized cmdLine; ensure the helper is applied to both the executable
(cli.command) and args (fullArgs) to prevent splitting or injection.
In `@bmad-copilot/src/commandRegistry.ts`:
- Around line 139-168: The slashToCli function misparses core agent names
containing hyphens (e.g., bmad-agent-tech-writer) because it splits on '-' and
treats the third segment as module when parts.length >= 4; add a JSDoc comment
above the slashToCli function documenting this limitation: explain that core
agents with hyphenated names will be interpreted as module+name (producing
bmad:agent:tech:writer) due to dash-delimited parsing, note this only affects
the cliSyntax/display and not runtime behavior, and suggest the canonical
workaround (avoid hyphens in core agent names or use module form) so future
maintainers understand the ambiguity.
- Around line 293-295: The code computes workspaceDir as path.dirname(bmadDir)
but should use the provided workspaceRoot parameter; change the call that sets
workspaceDir (and the subsequent call to this.scanCopilotPromptFiles) to use
workspaceRoot directly so scanCopilotPromptFiles scans the actual workspace (use
the variable workspaceRoot instead of path.dirname(bmadDir)), updating
references around workspaceDir/bmadDir in this block and ensuring
this.scanCopilotPromptFiles(workspaceRoot, commands) is invoked.
- Around line 45-66: The parseCsv function uses headers = parseCsvLine(lines[0])
without trimming, so CRLF-produced trailing '\r' stays on header keys and breaks
lookups; update parseCsv to trim each header string (e.g., map headers through
.trim()) after calling parseCsvLine and before using headers to build records so
keys are normalized, keeping the rest of the logic in parseCsv and record
population unchanged.
- Around line 321-339: The JSDoc for search says results are "sorted by
relevance" but search(query: string, limit = 20) currently returns matches in
insertion order; update search to compute a simple relevance score per
BmadCommand (e.g., higher weight when query matches slashName vs description,
higher weight for prefix matches and earlier indexOf), sort the matched commands
by that score descending, then return the top N up to limit; operate on
this._state.commands.values() as before but collect tuples of (cmd, score), sort
by score, and map back to BmadCommand for the returned array.
In `@bmad-copilot/src/extension.ts`:
- Around line 180-227: The performScanWithMirror function ignores the
user-configured bmad.bmadDir; read the setting (e.g. const overrideBmadDir =
vscode.workspace.getConfiguration('bmad').get<string>('bmadDir')) and, when
calling registry.scan, pass that override (registry.scan(workspaceRoot,
overrideBmadDir)) so CommandRegistry.scan receives the user override; keep
existing behavior when the setting is undefined or empty. Reference symbols:
performScanWithMirror, registry.scan, and the bmad.bmadDir config key.
- Around line 229-243: The helper findBmadDir currently does runtime
require('node:fs') and require('node:path') and duplicates logic found in
CommandRegistry; replace the dynamic requires with top-level ESM imports for fs
and path (import fs from 'node:fs' and import path from 'node:path') and either
call CommandRegistry.findBmadDir(workspaceRoot) or extract the shared logic to a
new utility function (e.g., bmad/findBmadDir) and have both extension.ts and
CommandRegistry import that utility; update the findBmadDir symbol to use the
imported fs/path or delegate to the shared implementation so no runtime require
is used and logic is not duplicated.
In `@bmad-copilot/TESTING.md`:
- Line 23: The README/test instructions incorrectly reference the compiled
output as out/; update TESTING.md to state the compiled files are in dist/ (or
the actual build target) so it matches launch.json's outFiles ("dist/**/*.js")
and the build target defined in package.json (scripts.build or the
"main"/"directories" setting). Edit TESTING.md to replace "out/" with "dist/"
(or the correct directory) and ensure the wording aligns with the launch.json
outFiles and package.json build configuration.
🧹 Nitpick comments (11)
bmad-copilot/tsconfig.json (1)
1-19: Configuration looks solid overall.Standard choices for a VS Code extension targeting Node 16 / ES2022 with strict mode enabled.
One minor note:
sourceMap: false(Line 9) will make it harder to debug the extension in the VS Code Extension Host. Most VS Code extension scaffolds (yo code) default totrue. Consider enabling source maps at least for development builds if you haven't already accounted for this elsewhere.bmad-copilot/TESTING.md (1)
20-20: Add language specifiers to fenced code blocks.Several fenced code blocks (lines 20, 121, 145, 156, 206, 217) are missing language identifiers. Adding
textor an appropriate language tag improves rendering and satisfies markdownlint (MD040).Also applies to: 121-121, 145-145, 156-156, 206-206, 217-217
bmad-copilot/src/promptMirror.ts (1)
236-268: Frontmatter regex won't match files where closing---has no trailing newline.The regex on line 237 requires the closing
---to be followed by a newline (---\r?\n). Files that end with---and no body or trailing newline will skip transformation silently. This is a safe fallback (content returned as-is), but worth documenting if such files are expected from the claude-code installer./^(---\r?\n)([\s\S]*?\r?\n)(---\r?\n)([\s\S]*)$/ ^^-- requires \nbmad-copilot/src/bmadRuntime.ts (1)
554-578: Path resolution:startsWith('_bmad')could match unintended prefixes.Line 562 checks
!cleanPath.startsWith(BMAD_FOLDER_NAME)whereBMAD_FOLDER_NAMEis'_bmad'. This would also match paths like_bmad_other/..., skipping the_bmad/prefix prepend. Safer to check for_bmad/(with trailing separator).Proposed fix
- if (!cleanPath.startsWith(BMAD_FOLDER_NAME)) { + if (!cleanPath.startsWith(BMAD_FOLDER_NAME + '/') && !cleanPath.startsWith(BMAD_FOLDER_NAME + path.sep)) { cleanPath = path.join(BMAD_FOLDER_NAME, cleanPath); }bmad-copilot/src/commandRegistry.ts (3)
373-379:loadCsvis markedasyncbut performs only synchronous I/O.The method uses
fs.readFileSyncandfs.existsSync, so wrapping it inasyncand usingPromise.allinscan()(line 247) doesn't provide any actual parallelism — all reads execute sequentially on the event loop. Consider switching tofs.promises.readFilefor genuine async I/O, or dropping theasynckeyword and calling them directly to avoid misleading the reader.Option: use async I/O
- private async loadCsv<T extends { [key: string]: string }>(filePath: string): Promise<T[]> { - if (!fs.existsSync(filePath)) { - return []; - } - const content = fs.readFileSync(filePath, 'utf8'); - return parseCsv<T>(content); - } + private async loadCsv<T extends { [key: string]: string }>(filePath: string): Promise<T[]> { + try { + const { readFile } = await import('node:fs/promises'); + const content = await readFile(filePath, 'utf8'); + return parseCsv<T>(content); + } catch { + return []; + } + }
387-403:detectModulesincludes non-module directories likeide.The filter excludes
_config,_memory,docs, and dot-prefixed directories, but_bmad/ide/(used by the prompt mirror as_bmad/ide/claude-code/) would pass through and be reported as an installed module.Proposed fix — also exclude `ide`
.filter( (e) => e.isDirectory() && e.name !== '_config' && e.name !== '_memory' && e.name !== 'docs' && + e.name !== 'ide' && !e.name.startsWith('.'), )
75-104: Custom CSV parser doesn't handle newlines inside quoted fields.Since lines are pre-split on
\n(line 46), quoted fields containing embedded newlines will be broken across multiple "lines" and parsed incorrectly. If the BMAD manifest CSVs never contain such fields, this is fine — but it's worth a brief comment in the JSDoc noting this limitation.bmad-copilot/package.json (1)
62-74: Test script is a type-check alias with no actual test runner.
"test": "npm run lint"only runstsc --noEmit. This meansnpm testgives a false sense of coverage. The architecture roadmap (Section 9) acknowledges this gap. Consider adding at least a placeholder test framework (e.g., vitest or mocha) so the CI pipeline can distinguish type errors from test failures.bmad-copilot/src/chatBridge.ts (2)
113-148:activeProcessis declared but never assigned — dead code path.
activeProcess(Line 117) is initialized tonulland checked on Line 144, but no code in this class ever assigns a value to it. The entire interactive-process piping block (Lines 143-148) is unreachable dead code.Either remove the dead code or implement the assignment if interactive CLI piping is intended.
♻️ Proposed removal of dead code
- /** - * Active interactive CLI process. If set, the next user message in - * chat will be piped to this process's stdin instead of being - * treated as a new command. - */ - private activeProcess: import('node:child_process').ChildProcess | null = null;And in the handler:
try { - // --- If there's an active interactive process, pipe input --- - if (this.activeProcess?.stdin && !this.activeProcess.killed) { - this.activeProcess.stdin.write(request.prompt + '\n'); - stream.markdown(`📝 Sent: \`${request.prompt}\``); - return {}; - } - const state = this.registry.state;
625-641: Synchronous file read blocks the extension host.
fs.readFileSyncon Line 629 blocks the single-threaded extension host while reading the prompt file. For large prompt files, this could cause noticeable UI lag. Usefs.promises.readFileto keep the extension host responsive — the callers are alreadyasync.♻️ Proposed async fix
- private buildFromPromptFile( + private async buildFromPromptFile( filePath: string, userInput: string, - ): string { - const raw = fs.readFileSync(filePath, 'utf8'); + ): Promise<string> { + const raw = await fs.promises.readFile(filePath, 'utf8');And update the call site in
executeCommand(Line 601):- const compiledPrompt = this.buildFromPromptFile(promptFilePath, userInput); + const compiledPrompt = await this.buildFromPromptFile(promptFilePath, userInput);bmad-copilot/src/cliBridge.ts (1)
340-343: Biome hint is a false positive —\x1Bis intentional for ANSI stripping.The
\x1Bcontrol character in the regex is the standard ESC byte that begins ANSI escape sequences. This is the correct and conventional way to strip ANSI codes. The BiomenoControlCharactersInRegexrule doesn't account for this legitimate use case.Consider adding a suppression comment if Biome is enforced in CI:
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: Intentional ANSI escape stripping return text.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '');
Critical Fixes: - Fix CSV headers CRLF bug causing key mismatches on Windows - Fix workspace root derivation error when using overrideBmadDir - Allow /status command to run when BMAD not installed (diagnostic) - Fix command injection/space handling in terminal.sendText Major Fixes: - Implement bmad.bmadDir configuration setting consumption - Refactor findBmadDir to use top-level imports (remove require()) Security Enhancements: - Add security warnings for config.yaml exposure to LLM - Document risks in ARCHITECTURE.md with best practices section - Update risk analysis table with config file exposure Minor Fixes & Documentation: - Correct JSDoc about file inlining (passes as-is, not inlined) - Document slashToCli limitation for hyphenated agent names - Fix search() JSDoc claiming 'sorted by relevance' - Update copyright year from 2024 to 2026 - Fix TESTING.md output directory reference (out/ -> dist/) - Clarify extension file creation behavior in ARCHITECTURE.md - Add executable permissions to scripts/release.sh - Exclude .github/workflows/release.yml from git GitHub Actions Fixes: - Add working-directory for npm commands - Make build-and-publish depend on ci-check - Fix version alignment in ARCHITECTURE.md
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@bmad-copilot/ARCHITECTURE.md`:
- Around line 96-105: Update the `/run` entry in the ARCHITECTURE.md table so it
no longer claims the adapter "resolves refs" and instead reflects the actual
behavior: the chatBridge.ts Prompt Executor reads the `.prompt.md` /
`.agent.md`, strips frontmatter, and sends the raw prompt content to the LLM
without performing reference resolution; locate the `/run` description in the
Prompt Executor table and replace "resolve refs" with phrasing like "sends raw
prompt to LLM (no ref resolution)" to keep it consistent with the design
philosophy.
In `@bmad-copilot/src/chatBridge.ts`:
- Around line 117-148: The handler in ChatBridge references this.activeProcess
(checked in handler) but activeProcess is never assigned anywhere, making the
stdin-piping block dead — either remove the unreachable block or wire
activeProcess up to the CLI spawn flow; to fix, either (A) delete the
stdin-write/stream.markdown branch in ChatBridge.handler and its activeProcess
field, or (B) update CliBridge.spawnToChat (or add a new method on CliBridge) to
return or expose the spawned ChildProcess and set ChatBridge.activeProcess to
that process when starting interactive commands, and ensure you clear
activeProcess when the process exits; touch the activeProcess field,
ChatBridge.handler, and CliBridge.spawnToChat to implement the chosen approach.
- Around line 695-723: In sendToLlm, the rate-limit check uses the wrong error
code; update the LanguageModelError handling in the catch block of sendToLlm to
test err.code === 'Blocked' (instead of 'quota') and return the specific
rate-limit message when blocked; keep the existing log and fallback generic
message for other LanguageModelError codes so users see the helpful rate-limit
text on Blocked errors.
🧹 Nitpick comments (6)
bmad-copilot/src/bmadRuntime.ts (1)
563-587: Path resolution intryReadWorkflowFilecould prepend_bmad/when the path already starts with it as a prefix of a longer name.Line 571 uses
startsWith(BMAD_FOLDER_NAME)which matches_bmadbut would also match paths like_bmad_v2/.... A trailing separator check would be more precise.Suggested fix
- if (!cleanPath.startsWith(BMAD_FOLDER_NAME)) { + if (!cleanPath.startsWith(BMAD_FOLDER_NAME + '/') && !cleanPath.startsWith(BMAD_FOLDER_NAME + path.sep) && cleanPath !== BMAD_FOLDER_NAME) { cleanPath = path.join(BMAD_FOLDER_NAME, cleanPath); }Given this is a deprecated fallback and BMAD conventions use
_bmad/, the risk is very low in practice.bmad-copilot/src/commandRegistry.ts (2)
380-386:loadCsvisasyncbut only performs synchronous I/O.
readFileSyncblocks the thread, so thePromise.allwrapper at Line 253 provides no concurrency benefit. This is functionally correct but misleading. Consider either usingfs.promises.readFilefor true parallelism or dropping theasynckeyword and calling these sequentially.Option: use async I/O
- private async loadCsv<T extends { [key: string]: string }>(filePath: string): Promise<T[]> { - if (!fs.existsSync(filePath)) { - return []; - } - const content = fs.readFileSync(filePath, 'utf8'); - return parseCsv<T>(content); + private async loadCsv<T extends { [key: string]: string }>(filePath: string): Promise<T[]> { + try { + const content = await fs.promises.readFile(filePath, 'utf8'); + return parseCsv<T>(content); + } catch { + return []; + } }
567-567: Silent emptycatchblocks swallow read errors, making debugging harder.Lines 567 and 595 catch and discard all errors from
readdirSync. At minimum, consider logging a warning to the output channel, or adding a brief comment clarifying the intent (e.g., permission errors on directories the user can't read).Also applies to: 595-595
bmad-copilot/src/chatBridge.ts (1)
626-642: Frontmatter stripping regex may fail on files with a UTF-8 BOM.Line 633's regex anchors on
^---which won't match if the file starts with a BOM character (\uFEFF). This is uncommon but possible on Windows-generated files.Defensive fix
- const raw = fs.readFileSync(filePath, 'utf8'); + const raw = fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');bmad-copilot/src/extension.ts (1)
182-235:bmad.bmadDirconfig is now consumed — past issue resolved.The config override is properly read at Lines 190–192 and 215–217, and passed through to both
ensureCopilotPromptsandregistry.scan.Minor nit: the config is read twice in the same function (Lines 190–191 and 215–216). Consider reading it once at the top.
Optional: read config once
async function performScanWithMirror( registry: CommandRegistry, workspaceRoot: string, outputChannel: vscode.OutputChannel, ): Promise<number> { + const config = vscode.workspace.getConfiguration('bmad'); + const configuredBmadDir = config.get<string>('bmadDir') || undefined; + // ── Attempt prompt mirror ────────────────────────────────── try { - const config = vscode.workspace.getConfiguration('bmad'); - const configuredBmadDir = config.get<string>('bmadDir'); - const bmadDir = configuredBmadDir || findBmadDir(workspaceRoot); + const bmadDir = configuredBmadDir || findBmadDir(workspaceRoot); // ... } // ── Normal scan ────────────────────────────────── try { - const config = vscode.workspace.getConfiguration('bmad'); - const configuredBmadDir = config.get<string>('bmadDir'); - const state = await registry.scan(workspaceRoot, configuredBmadDir || undefined); + const state = await registry.scan(workspaceRoot, configuredBmadDir); // ... }bmad-copilot/src/cliBridge.ts (1)
266-277: Potential double-settle if both'error'and'close'events fire.In Node.js, a spawn
'error'event (e.g.,ENOENT) is typically followed by a'close'event. This would callreject(err)thenresolve(code). The Promise ignores the second settlement, but thecancelSub.dispose()would be called twice.A simple guard avoids the double-dispose:
Suggested fix
+ let settled = false; proc.on('close', (code) => { + if (settled) return; + settled = true; cancelSub.dispose(); this.log(`Process exited with code ${code}`); resolve(code ?? 1); }); proc.on('error', (err) => { + if (settled) return; + settled = true; cancelSub.dispose(); this.log(`Process error: ${err.message}`); reject(err); });
- chatBridge: fix rate-limit error code check (Blocked vs quota) and remove dead activeProcess code - chatBridge: handle UTF-8 BOM in frontmatter stripping - bmadRuntime: fix path prefix check to avoid false matches (_bmad_v2) - commandRegistry: convert loadCsv to truly async with fs.promises - commandRegistry: add logging to silent catch blocks for directory reads - extension: eliminate duplicate config reads in performScanWithMirror - cliBridge: add settled guard to prevent double-settle on error+close - ARCHITECTURE: clarify /run sends raw prompts without ref resolution
|
Tip For best results, initiate chat on the files or code changes.
I can help you with:
What would you like me to focus on? |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@bmad-copilot/ARCHITECTURE.md`:
- Around line 242-252: Update ARCHITECTURE.md to remove the contradiction
between the "design philosophy" claim that "the LLM can still access workspace
files through its context" (lines ~47-52) and the Risk Analysis row "LLM file
access" (the high-priority risk stating `sendRequest()` may not resolve
{project-root}); pick one approach and implement it: either (A) soften the
design-philosophy statement to indicate uncertainty/conditional behavior (e.g.,
"may be able to access workspace files depending on LLM context and adapter")
and reference fallback to BmadRuntime, or (B) if you confirm behavior, update
the Risk Analysis row to reflect that access is reliable and adjust mitigation
accordingly; edit the "design philosophy" paragraph and the "LLM file access"
risk row so they are consistent and cross-reference each other.
In `@bmad-copilot/src/commandRegistry.ts`:
- Around line 380-387: The loadCsv method returns corrupted headers when a UTF-8
BOM is present; update the loadCsv<T extends { [key: string]: string
}>(filePath: string) method to strip a leading BOM from the file content after
reading (e.g., remove /^\uFEFF/ or check startsWith('\uFEFF') and slice) before
passing the string to parseCsv<T>(content) so the first CSV header key (and
subsequent property lookups like entry.module) are correct.
🧹 Nitpick comments (10)
bmad-copilot/ARCHITECTURE.md (3)
37-37: Clarify file creation vs. modification policy.The statement "never modifies existing files in
_bmad/or overwrites files in.github/" could be misread. It's clear that_bmad/is read-only, but the.github/phrasing is ambiguous—does it mean the extension never touches.github/at all, or that it creates new files but won't overwrite existing ones?Consider rephrasing for clarity:
-**File Creation Note**: The extension **creates** prompt mirror files in `.github/prompts/` and `.github/agents/` when they don't exist, but **never modifies** existing files in `_bmad/` or overwrites files in `.github/`. +**File Creation Note**: The extension **creates** new prompt mirror files in `.github/prompts/` and `.github/agents/` when they don't exist (never overwrites existing files), and treats `_bmad/` as strictly read-only (never modifies).
146-146: Clarify "Cloud Code CLI" terminology.Line 146 mentions "Does NOT require Cloud Code CLI," but the context is about Claude Code (Anthropic's IDE). "Cloud Code" typically refers to Google's Cloud Code CLI/extension. This could confuse readers familiar with Google Cloud tooling.
Consider clarifying:
-| No CLI Required | Does NOT require Cloud Code CLI — only reads files generated by the BMAD installer | +| No CLI Required | Does NOT require Claude Code CLI — only reads files generated by the BMAD installer |
43-43: Add language specifiers to fenced code blocks.Four code blocks are missing language identifiers, which prevents syntax highlighting and reduces readability. While the content is clear, adding these would improve the documentation quality.
📝 Suggested improvements
Line 43:
-``` +```markdown Read the file at {project-root}/_bmad/bmm/config.yamlLine 58: ```diff -``` +```text ┌─────────────────────────────────────────────────┐Line 152: ```diff -``` +```text User: `@bmad` /run bmad-bmm-create-prdLine 184: ```diff -``` +```text extension.ts :: performScanWithMirror()</details> As per coding guidelines, markdownlint recommends specifying a language for all fenced code blocks (MD040). Also applies to: 58-58, 152-152, 184-184 </blockquote></details> <details> <summary>bmad-copilot/src/cliBridge.ts (2)</summary><blockquote> `266-283`: **`spawnAndCapture` lacks a settled guard, unlike `spawnToChat`.** In `spawnToChat` (Line 266), a `settled` flag correctly prevents double promise resolution when both `error` and `close` events fire. The same pattern is absent in `spawnAndCapture` (Lines 325-330). While Node.js ignores a second `resolve`/`reject` call on the same promise, adding the guard would be consistent and defensive. <details> <summary>♻️ Add settled guard for consistency</summary> ```diff let stdout = ''; let stderr = ''; proc.stdout?.on('data', (d: Buffer) => { stdout += d.toString(); }); proc.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); }); + let settled = false; + proc.on('close', (code) => { + if (settled) return; + settled = true; resolve({ exitCode: code ?? 1, stdout, stderr }); }); - proc.on('error', (err) => reject(err)); + proc.on('error', (err) => { + if (settled) return; + settled = true; + reject(err); + });
350-352: Biome false positive — control character is intentional for ANSI stripping.The
\x1B(ESC) in the regex is required to match ANSI escape sequences. The BiomenoControlCharactersInRegexrule is a known false positive for this pattern. Consider adding an inline suppression to make the intent explicit and silence CI:+ // biome-ignore lint/suspicious/noControlCharactersInRegex: Intentional — stripping ANSI escape codes return text.replace(/\x1B\[[0-9;]*[A-Za-z]/g, '');Also note the regex handles CSI sequences but misses OSC (
\x1B]...) and some less common escape forms. This is fine for typical CLI output.bmad-copilot/src/commandRegistry.ts (1)
540-604: Agent filename-to-command mapping relies on a specific naming convention.The regex on Line 588 (
/^bmad-([^-]+)-agents-(.+)$/) assumes agent filenames follow the patternbmad-<module>-agents-<name>.agent.md. If the BMAD installer changes this naming convention, prompt files won't be linked to their commands. This is worth a brief comment noting the coupling to the installer's file naming scheme.Also, this only matches module agents (with
agentsin the filename), not core agents that might use a different pattern. If core agents exist as.agent.mdfiles, they won't be linked.bmad-copilot/src/bmadRuntime.ts (1)
563-588:tryReadWorkflowFiledoes not validate resolved paths stay within the workspace.A manifest entry containing path traversal segments (e.g.,
../../etc/passwd) would be joined ontoworkspaceRootand read. While manifest files are local and trusted, a defensiverealpathcheck against the workspace root would prevent accidental reads outside the project.Given this is a deprecated fallback path with trusted local inputs, this is low risk.
bmad-copilot/src/extension.ts (2)
122-130: Debounce timer is not disposed on deactivation.If a file change fires just before deactivation, the 2-second timer will fire after the extension has been deactivated. This is safe due to the
if (root)guard on Line 128, but the dangling timer is a minor hygiene concern.♻️ Clear timer on deactivation
Store the timer reference at module scope and clear it in
deactivate:+let scanTimer: ReturnType<typeof setTimeout> | undefined; + export async function activate(context: vscode.ExtensionContext): Promise<void> { // ... - let scanTimer: ReturnType<typeof setTimeout> | undefined; const debouncedScan = () => { if (scanTimer) clearTimeout(scanTimer); scanTimer = setTimeout(async () => {export function deactivate(): void { - // All disposables are managed via context.subscriptions. + if (scanTimer) clearTimeout(scanTimer); }
238-247:findBmadDiris duplicated betweenextension.tsandCommandRegistry.This was noted in a previous review. Both implementations are identical 7-line functions. While not urgent, extracting a shared utility would prevent divergence.
bmad-copilot/src/chatBridge.ts (1)
394-504: Listing handlers duplicate formatting logic fromBmadRuntime.
handleAgents,handleWorkflows, andhandleTasksproduce Markdown tables very similar toBmadRuntime.buildAgentListingPrompt(),buildWorkflowListingPrompt(), andbuildTaskListingPrompt(). SinceBmadRuntimeis a deprecated fallback, maintaining parallel implementations is expected, but the duplication could diverge over time.
- Add CLI entry point: bootstrap, update, status commands - Remove all mirror/transform/conversion logic (pure adapter) - chatBridge: remove BmadRuntime fallback, remove hasClaudeCodeSource - commandRegistry: add invalidate()/rescan(), fix UTF-8 BOM in CSV - extension: add /update command, prompt integrity check on activation - Deprecate promptMirror.ts and bmadRuntime.ts (no active imports) - Remove GitHub Actions release workflow - Remove global install references, npx-only flow - Add troubleshooting section for 0-command scenario - Rewrite README and ARCHITECTURE.md for pure adapter model - Published to npm as bmad-copilot-adapter@0.2.0
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Fix all issues with AI agents
In `@bmad-copilot/ARCHITECTURE.md`:
- Around line 228-231: Update the architecture doc to clarify that the
CLI↔Copilot name conversion is asymmetric: the CLI→slash conversion uses a
simple replaceAll(':','-') but the reverse (slashToCli in commandRegistry.ts) is
context-sensitive and only replaces structural dashes (e.g., transforms
"bmad-bmm-create-prd" → "bmad:bmm:create-prd", not "bmad:bmm:create:prd");
reference the function name slashToCli and the CLI tokenization behavior in
commandRegistry.ts, remove the oversimplified "replace `-` with `:` for CLI"
statement, and add one short example for each direction to make the exact
behavior explicit.
In `@bmad-copilot/src/chatBridge.ts`:
- Around line 648-650: The YAML frontmatter regex in chatBridge.ts (the fmMatch
assignment using raw and producing body) wrongly requires a newline after the
closing '---'; update the pattern so the trailing `\r?\n` after the closing
delimiter is optional (allow zero or one newline) so frontmatter is stripped
even when the file ends with '---' with no newline; adjust the fmMatch regex
accordingly and keep the existing fallback assignment to body = fmMatch ?
fmMatch[2] : raw.
- Around line 637-658: The function buildFromPromptFile currently uses
synchronous fs.readFileSync which blocks the extension host; change
buildFromPromptFile to be async (e.g., async buildFromPromptFile) and replace
fs.readFileSync with await fs.promises.readFile(filePath, 'utf8'), preserve the
BOM stripping and frontmatter parsing logic, and update any callers such as
executeCommand to await the new async buildFromPromptFile signature so the file
I/O is non-blocking.
In `@bmad-copilot/src/cli/bootstrap.ts`:
- Around line 82-84: The bootstrap function destructures BootstrapOptions.yes
but never uses it; either implement skip-confirmation behavior using the yes
flag inside bootstrap (e.g., pass it to any prompt/confirm routines or
conditionally bypass interactive prompts) or remove the yes parameter from
BootstrapOptions and from bootstrap's signature and call sites to avoid
misleading callers—locate the bootstrap function and any prompt/confirmation
logic it invokes and wire the yes boolean through those code paths (or eliminate
the unused destructuring) so the parameter is no longer unused.
- Around line 143-160: The code currently determines VS Code availability by
reading results[results.length - 1].ok which is fragile; change the flow to
capture the VS Code detection outcome in a named variable (e.g., vsCodeDetected
or detectVsCodeResult) at the point where the CLI detection step runs, then use
that variable in the VS Code extension install block instead of positional
access; keep calling installExtension(), pushing the install result into
results, and invoking stepOk/stepSkip/stepFail as before, but base the if-check
on the new named variable rather than results[results.length - 1].ok to avoid
breakage if steps are reordered.
In `@bmad-copilot/src/cli/update.ts`:
- Around line 115-121: The code currently creates a sentinel at
path.join(bmadDir, '.copilot-update') via sentinelPath and fs.writeFileSync
which contradicts the README claim that the package "does not modify any files
in _bmad/"; either update the README to document the sentinel file or change the
sentinel location to outside bmadDir (for example write to path.join('.github',
'.copilot-update') or the repo root) and update the sentinelPath usage
accordingly so there is no write into _bmad/; adjust the console messages if you
change location and ensure the try/catch around fs.writeFileSync remains to
handle non-critical failures.
- Around line 166-183: The exclusion lists are inconsistent: align the logic by
extracting the ignored-directory names into a single shared constant (e.g.,
IGNORED_MODULE_DIRS or IGNORED_DIRS) and use it in the detectModules function in
update.ts and status.ts and in the module-filtering logic in commandRegistry.ts
(the registry filter that currently omits _config/_memory/docs but not ide);
ensure the shared list contains '_config', '_memory', 'docs', 'ide', and any
dot-prefixed entries handling, then replace the per-file hardcoded arrays with
references to that constant so all three implementations behave identically.
In `@bmad-copilot/src/cliBridge.ts`:
- Around line 299-331: spawnAndCapture currently passes a timeout option to
cp.spawn which is ignored, so getVersion can hang; fix by adding a manual timer
in spawnAndCapture: after spawning proc (variable proc) start a NodeJS timeout
that, when fired, kills the child (proc.kill()), stops listening, and rejects or
resolves with a non-zero exit (or a clear timeout error), and ensure the timer
is cleared on proc.on('close') and proc.on('error'); keep existing stdout/stderr
aggregation and ensure the promise is settled exactly once.
In `@bmad-copilot/src/commandRegistry.ts`:
- Around line 76-105: Add a JSDoc comment above parseCsvLine (and the
higher-level parseCsv if present) stating that the current CSV parsing
implementation does not support newlines inside quoted fields because parseCsv
splits on '\n' prior to calling parseCsvLine; explicitly note the limitation,
the rationale (BMAD manifests are machine-generated with short values), and warn
that multi-line quoted fields will produce corrupt records so future maintainers
know the constraint and where to improve the parser if needed.
In `@bmad-copilot/src/extension.ts`:
- Around line 87-110: The code wrongly uses dynamic require('node:path') to
build promptsDir and bmadDirLocal even though a top-level path import exists;
update the references in the workspaceRoot block to use the imported path module
(replace require('node:path').join(...) with path.join(...)) for promptsDir and
bmadDirLocal, leaving the rest of the logic around hasBmadDir, hasPrompts, log,
and vscode.window.showWarningMessage intact so behavior is unchanged.
🧹 Nitpick comments (7)
bmad-copilot/README.md (1)
34-37: Fenced code blocks missing language identifiers.Several fenced code blocks (Lines 34, 95, 159, 170, 250, 259, 331, 358) use plain triple-backticks for ASCII diagrams and example text. Consider adding
textorplaintextas the language identifier to satisfy markdownlint MD040.Also applies to: 250-264, 331-354, 358-377
bmad-copilot/src/cli/update.ts (1)
33-40:FMTobject and helpers are duplicated across all three CLI modules.The
FMTformatting object is identical inupdate.ts,bootstrap.ts, andstatus.ts. Similarly,countCsvRowsanddetectModulesare duplicated betweenupdate.tsandstatus.ts. Consider extracting these into a sharedcli/utils.tsmodule.bmad-copilot/src/cli/bootstrap.ts (1)
364-394: Four near-identical file helper functions could be parameterized.
hasBmadFiles,hasBmadAgentFiles,countBmadFiles, andcountBmadAgentFilesdiffer only by suffix. A single parameterized helper would reduce duplication.Proposed refactor
-function hasBmadFiles(dir: string): boolean { - try { - return fs.readdirSync(dir).some((f) => f.startsWith('bmad') && f.endsWith('.prompt.md')); - } catch { - return false; - } -} - -function hasBmadAgentFiles(dir: string): boolean { - try { - return fs.readdirSync(dir).some((f) => f.startsWith('bmad') && f.endsWith('.agent.md')); - } catch { - return false; - } -} - -function countBmadFiles(dir: string): number { - try { - return fs.readdirSync(dir).filter((f) => f.startsWith('bmad') && f.endsWith('.prompt.md')).length; - } catch { - return 0; - } -} - -function countBmadAgentFiles(dir: string): number { - try { - return fs.readdirSync(dir).filter((f) => f.startsWith('bmad') && f.endsWith('.agent.md')).length; - } catch { - return 0; - } -} +function listBmadFiles(dir: string, suffix: string): string[] { + try { + return fs.readdirSync(dir).filter((f) => f.startsWith('bmad') && f.endsWith(suffix)); + } catch { + return []; + } +}Then use
listBmadFiles(dir, '.prompt.md').length > 0andlistBmadFiles(dir, '.prompt.md').lengthas needed.bmad-copilot/src/cliBridge.ts (1)
180-199: Quoting improvement addresses spaces but not shell metacharacters.The current quoting logic (Lines 185–187) handles paths with spaces but doesn't escape
",$, backticks,|,&, or other shell metacharacters within args. SincesendTextsends raw text to the shell, a workspace path like/foo/$bar/projectwould still be misinterpreted. For the current use case (installer invocation), this is low-risk but worth noting.bmad-copilot/src/commandRegistry.ts (1)
285-304: State is published beforescanCopilotPromptFilescompletes — safe but fragile.
this._stateis assigned at line 285 withpromptFiles: new Map()andhasCopilotFiles: false, thenscanCopilotPromptFilesmutates it at line 302. This works becausescanCopilotPromptFilesis synchronous and JS is single-threaded, but if anyone ever makes it async (or reads state between the assignment and the call), they'll see an incomplete snapshot.Consider moving the assignment after the scan, or building the prompt file data first and including it in the state assignment.
♻️ Suggested restructure
+ const promptFiles = new Map<string, string>(); + const hasCopilotFiles = this.scanCopilotPromptFiles(workspaceRoot, commands, promptFiles); + this._state = { bmadDir, commands, helpEntries, agents, workflows, tasks, tools, modules, - promptFiles: new Map(), - hasCopilotFiles: false, + promptFiles, + hasCopilotFiles, lastScan: new Date().toISOString(), }; - // --- Scan .github/prompts/ and .github/agents/ --- - this.scanCopilotPromptFiles(workspaceRoot, commands); - return this._state;This would require refactoring
scanCopilotPromptFilesto accept and populate aMaprather than mutatingthis._state.bmad-copilot/ARCHITECTURE.md (1)
44-46: Fenced code blocks missing language identifiers.Lines 44, 65, 178, and 210 open fenced code blocks without a language tag. Adding
textorplaintextwould satisfy markdownlint MD040 and provide consistent formatting.Also applies to: 65-65, 178-178, 210-210
bmad-copilot/src/chatBridge.ts (1)
203-223:handleUpdateshows success before the async command completes.
vscode.commands.executeCommand('bmad-copilot.update')is fire-and-forget via.then(). The "✅ Update triggered" message at line 218 renders before the rescan finishes. This is acceptable since the VS Code command handler inextension.tsshows its own notification on completion, but it's worth being aware that if the update fails, the user still sees the success checkmark in the chat.Consider
await-ing the command and conditionally showing the success message:- vscode.commands.executeCommand('bmad-copilot.update').then( - () => { /* Command executed — UI notification handled by the command */ }, - (err) => { this.log(`Update command error: ${err}`); }, - ); - - stream.markdown( - '✅ Update triggered. The command registry will be refreshed momentarily.\n\n' + - '> Use `@bmad /status` to verify the updated state.', - ); + try { + await vscode.commands.executeCommand('bmad-copilot.update'); + stream.markdown( + '✅ Update complete. Use `@bmad /status` to verify the updated state.', + ); + } catch (err) { + this.log(`Update command error: ${err}`); + stream.markdown('⚠️ Update failed. Check the BMAD Copilot output panel for details.'); + }
- Critical: fix agent file pattern matching across all modules commandRegistry.ts now scans bmad-agent-*.md (not *.agent.md) extension.ts integrity check includes .github/agents/ chatBridge.ts error messages reference both directories CLI bootstrap/update/status all use correct pattern - Publisher changed to evil9369 - DEP0190 deprecation warning fixed on Windows - README/ARCHITECTURE/CHANGELOG updated for BMAD v6 structure - Published to npm as bmad-copilot-adapter@0.2.4
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@bmad-copilot/ARCHITECTURE.md`:
- Around line 337-340: The ARCHITECTURE.md contains a stale claim that "Status
commands include 500-char excerpts from each module config" which is inaccurate
given the current implementation; update the document to reflect the real
behavior in chatBridge.ts (the handleStatus function) by removing or replacing
that sentence with a statement that status commands only report module names and
counts (no config excerpts are sent to the LLM), and ensure the "Config file
scope" section explicitly matches handleStatus's output semantics so readers are
not misled about what data is exposed.
In `@bmad-copilot/package.json`:
- Around line 136-144: The settings bmad.autoScan and bmad.verbose are declared
but not used; update extension.ts to read the 'bmad' configuration (via
vscode.workspace.getConfiguration('bmad')) and conditionally call
performScan(...) only when config.get<boolean>('autoScan', true) is true, and
update the log(...) function (or wherever outputChannel.appendLine is called) to
respect config.get<boolean>('verbose', false) before writing; also ensure the
BmadConfig interface reflects the same keys and remove unused defaults if you
choose to delete the settings instead.
In `@bmad-copilot/README.md`:
- Line 6: Update all repository references from pi-docket to bmad-code-org: in
README.md replace the badge URL text
"https://github.com/pi-docket/bmad-method-vscode" (the BMAD-METHOD badge on line
~6) and the clone URL in the Development section (around lines ~283–284) to
"https://github.com/bmad-code-org/bmad-method-vscode", and in package.json
update the homepage, bugs.url, and repository.url fields to use
"https://github.com/bmad-code-org/bmad-method-vscode" (and ensure
repository.type/name fields reflect bmad-code-org if present) so all metadata
point to the bmad-code-org organization.
In `@bmad-copilot/src/chatBridge.ts`:
- Around line 46-48: The README's prerequisites line uses "Node.js **v20+**"
which conflicts with package.json's "node": ">=18.0.0" and the CLI bootstrap
checks; update the README text that currently says "Node.js **v20+**" to match
the project's supported range (e.g., "Node.js ≥ 18.0.0" or ">=18.0.0") and
verify the wording is consistent with the "node" field in package.json and any
bootstrap/CLI version check logic (search for the literal "Node.js **v20+**" in
the README and the "node" field in package.json to align them).
In `@bmad-copilot/src/extension.ts`:
- Around line 259-271: Remove the unused standalone function findBmadDir from
extension.ts: delete the function declaration (the top-level function named
findBmadDir that returns string|null) since the only actual usage is the
CommandRegistry.prototype.findBmadDir instance method; ensure no other
references to the top-level symbol remain and run a quick TypeScript build to
verify no unresolved references.
🧹 Nitpick comments (4)
bmad-copilot/src/commandRegistry.ts (1)
573-631: Prompt file scanning uses synchronous I/O inside an async workflow.
scanCopilotPromptFilesusesfs.existsSyncandfs.readdirSyncbut is called from the asyncscan()method. For a small number of files this is acceptable, but consider migrating tofs.promises.readdirfor consistency with the asyncloadCsvhelper, especially if the.github/directories grow over time.bmad-copilot/src/chatBridge.ts (1)
203-223:handleUpdatesends "complete" message before the update actually finishes.
vscode.commands.executeCommand('bmad-copilot.update')is fired but not awaited. The "✅ Update triggered" message at Line 218 is sent immediately, regardless of whether the update succeeded. Consider awaiting the command and reporting the actual outcome.📝 Proposed fix
- private handleUpdate( + private async handleUpdate( stream: vscode.ChatResponseStream, - ): vscode.ChatResult { + ): Promise<vscode.ChatResult> { stream.markdown( '🔄 **Updating BMAD command registry…**\n\n' + 'Invalidating cache and triggering full rescan.\n\n', ); - // Fire the VS Code command which performs invalidate + mirror + rescan - vscode.commands.executeCommand('bmad-copilot.update').then( - () => { /* Command executed — UI notification handled by the command */ }, - (err) => { this.log(`Update command error: ${err}`); }, - ); + try { + await vscode.commands.executeCommand('bmad-copilot.update'); + } catch (err) { + this.log(`Update command error: ${err}`); + stream.markdown('⚠️ Update command failed. Check the BMAD Copilot output panel for details.\n\n'); + return {}; + } stream.markdown( '✅ Update triggered. The command registry will be refreshed momentarily.\n\n' + '> Use `@bmad /status` to verify the updated state.', ); return {}; }bmad-copilot/src/cli/bootstrap.ts (2)
162-171: Step 5 duplicates the filesystem checks from Step 2.
validateCopilotRegistrationre-reads the same directories and applies the samehasBmadFiles/hasBmadAgentFileschecks already performed in Step 2 (Lines 106–130). Consider passing the Step 2 results forward instead of hitting the filesystem again.
358-388:has*andcount*helpers duplicate the same filtering logic.Each
has/countpair reads the directory and applies the identical filter —hasreturns.some(…)andcountreturns.filter(…).length. A single helper returning the count would serve both purposes (count > 0replaceshas).Proposed consolidation
-function hasBmadFiles(dir: string): boolean { - try { - return fs.readdirSync(dir).some((f) => f.startsWith('bmad') && f.endsWith('.prompt.md')); - } catch { - return false; - } -} - -function hasBmadAgentFiles(dir: string): boolean { - try { - return fs.readdirSync(dir).some((f) => f.startsWith('bmad-agent') && f.endsWith('.md')); - } catch { - return false; - } -} - -function countBmadFiles(dir: string): number { - try { - return fs.readdirSync(dir).filter((f) => f.startsWith('bmad') && f.endsWith('.prompt.md')).length; - } catch { - return 0; - } -} - -function countBmadAgentFiles(dir: string): number { - try { - return fs.readdirSync(dir).filter((f) => f.startsWith('bmad-agent') && f.endsWith('.md')).length; - } catch { - return 0; - } -} +function countBmadFiles(dir: string): number { + try { + return fs.readdirSync(dir).filter((f) => f.startsWith('bmad') && f.endsWith('.prompt.md')).length; + } catch { + return 0; + } +} + +function countBmadAgentFiles(dir: string): number { + try { + return fs.readdirSync(dir).filter((f) => f.startsWith('bmad-agent') && f.endsWith('.md')).length; + } catch { + return 0; + } +}Then replace
hasBmadFiles(dir)→countBmadFiles(dir) > 0andhasBmadAgentFiles(dir)→countBmadAgentFiles(dir) > 0at call sites.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
- Add comprehensive JSDoc comments to extension.ts helper functions - Add JSDoc comments to chatBridge.ts constructor and private methods - Add JSDoc comments to all CLI utility functions (bootstrap, index, status, update) - Ensure all public and private methods have proper parameter and return type documentation - Improve code maintainability and self-documentation This commit addresses the docstring coverage requirement, raising it from 63.64% to meet the 90% threshold.
|
@coderabbitai resume |
✅ Actions performedReviews resumed. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@bmad-copilot/src/cli/bootstrap.ts`:
- Around line 343-372: The function validateCopilotRegistration currently treats
the presence of only the _bmad directory as a success; update the hasBmadDir
branch inside validateCopilotRegistration so that when no BMAD prompt/agent
files exist but _bmad/ is present it returns ok: false and skipped: true
(preserving a helpful message that instructs the user to run the installer),
rather than ok: true; change the return object in the hasBmadDir block
(referencing hasBmadDir, promptsDir, agentsDir, countBmadFiles and
countBmadAgentFiles) so the check does not inflate success counts in the overall
summary.
In `@bmad-copilot/src/extension.ts`:
- Around line 93-96: Wrap the directory read checks for promptsDir and agentsDir
in try/catch so unreadable directories won't throw during activation: inside the
logic that computes hasPrompts and hasAgents (references: hasPrompts, hasAgents,
promptsDir, agentsDir and fs.readdirSync), attempt fs.readdirSync(...) in a try
block and on error fall back to treating the directory as
non-existent/unreadable (return false for each check) and optionally log the
error; ensure the fs.existsSync() condition is preserved so only existing paths
are attempted to be read.
🧹 Nitpick comments (4)
bmad-copilot/README.md (1)
96-98: Consider adding language identifiers to code fences.Code blocks at lines 96-98, 161-165, and similar locations would benefit from language identifiers for better syntax highlighting. For example:
- Line 96: Add
```textinstead of```- Line 161: Add
```textfor plain command examplesThis improves readability and accessibility, though it's a minor enhancement.
Also applies to: 161-165
bmad-copilot/src/cli/status.ts (2)
31-38: Extensive code duplication across CLI modules — extract shared utilities.The
FMTobject,detectModules,countCsvRows,listBmadFiles/listBmadAgentFiles, and VS Code detection logic are duplicated nearly verbatim acrossstatus.ts,update.ts, andbootstrap.ts. This violates DRY and makes it easy for the exclusion lists or formatting to drift between modules.Consider extracting these into a shared
src/cli/helpers.tsmodule:Suggested module structure
// src/cli/helpers.ts export const FMT = { /* ... */ }; export function detectModules(bmadDir: string): string[] { /* ... */ } export function countCsvRows(filePath: string): number { /* ... */ } export function listBmadFiles(dir: string, suffix: string): string[] { /* ... */ } export function listBmadAgentFiles(dir: string): string[] { /* ... */ } export function detectVsCode(): { available: boolean; version: string | null } { /* ... */ } export function checkExtensionInstalled(): boolean { /* ... */ } export function printCheck(label: string, value: string, ok: boolean, isOptional?: boolean): void { /* ... */ }
232-250:detectVsCodespawns a blocking subprocess — acceptable for CLI but worth noting.
spawnSyncwith a 10-second timeout is fine for a CLI diagnostic tool. However, if this code were ever invoked from the extension context (e.g., imported byextension.ts), it would block the extension host. The module boundary currently prevents this, but a brief JSDoc note would help.bmad-copilot/src/cli/index.ts (1)
134-134: Add.catch()to the top-levelmain()call for safety.If an unexpected error escapes the
try/catchinmain()(e.g., during argument parsing), it would produce an unhandled promise rejection. Node.js ≥15 terminates the process on unhandled rejections by default, but the exit code and message would be less controlled than your explicit handler.Suggested fix
-main(); +main().catch((err) => { + console.error(`\x1b[31m✖ ${err instanceof Error ? err.message : String(err)}\x1b[0m`); + process.exit(1); +});
|
bmad-copilot-adapter-0.2.4.zip At this stage, the extension is not published to the VS Code Marketplace. Since this PR is intended to be merged upstream rather than maintained as a separate fork, I am not registering or publishing it independently. For review and testing purposes, I have attached the packaged Reviewers can install it locally using: code --install-extension .vsix This allows full testing of the Copilot integration without requiring Marketplace publication. If the PR is accepted, the publishing strategy can be aligned with the official release process. |
WhatThis PR completes the implementation and stabilization of the BMAD Copilot Chat Adapter integration. All previously identified issues have been addressed to the best of my knowledge.
A packaged WhyBMAD officially supports installer-generated prompt artifacts for IDE integrations. This PR provides that adapter while strictly respecting upstream architectural boundaries. The goal is not to introduce a parallel execution engine, but to enable Copilot usage based solely on official artifacts. Scope of Changes
No changes were made to BMAD core behavior. TestingManual validation performed:
The attached Notes on DistributionThis extension has not been published to the VS Code Marketplace. Since this PR is intended for upstream integration rather than independent maintenance, I am not registering or releasing it separately. The If accepted, publishing strategy can follow the official release process. Merge ReadinessTo the best of my knowledge, the reported issues have been resolved. If any additional problems remain, I am happy to address them promptly. I believe this implementation is ready for review and potential merge to enable official Copilot Chat support within BMAD. |
- Fix validateCopilotRegistration to return ok: false when only _bmad/ exists without prompt files - Add try/catch error handling for directory read operations in extension activation - Prevent unreadable directories from throwing errors during startup - Improve bootstrap validation to not inflate success counts
- Change from Marketplace install to source code build workflow - Add prominent warning that extension is not published - Update installation steps to require git clone and build - Add 'Building from Source' section with detailed steps - Update bootstrap command description (verify vs install) - Update Publishing & Versioning section - Remove references to auto-install extension - Clarify that VSIX is not available on Marketplace
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@bmad-copilot/CHANGELOG.md`:
- Line 3: Check and correct the release dates for the two CHANGELOG headings "##
[0.2.4] — 2026-02-11" and "## [0.2.0] — 2026-02-11": verify source/release tags
or git history to determine the true publish dates, update the incorrect date(s)
in CHANGELOG.md accordingly, and if both dates are intentionally identical, add
a brief note under the 0.2.4 entry explaining that it was a hotfix released the
same day (e.g., "hotfix for agent detection released same day as 0.2.0") so
readers understand the reason for the duplicate date.
In `@bmad-copilot/README.md`:
- Line 48: Several fenced code blocks use bare backticks ("```") without
language identifiers causing markdownlint MD040 failures; update each
triple-backtick block (the occurrences currently shown as "```") to include an
appropriate language tag (for example "```bash" for shell commands, "```text"
for plain output, or "```yaml"/"```json" where applicable) so the fenced blocks
at the noted locations include explicit language identifiers.
| @@ -0,0 +1,77 @@ | |||
| # Changelog | |||
|
|
|||
| ## [0.2.4] — 2026-02-11 | |||
There was a problem hiding this comment.
Verify the release dates for versions 0.2.4 and 0.2.0.
Both versions are dated 2026-02-11. Releasing a minor version (0.2.0) and a patch version (0.2.4) on the same day is unusual. This could indicate:
- A rapid hotfix was needed immediately after the 0.2.0 release
- A date entry error (copy-paste)
- Pre-staging multiple versions
If this was intentional (e.g., a critical fix for agent detection in 0.2.4 after 0.2.0 shipped), consider adding a note explaining the rapid iteration. Otherwise, verify the dates are correct.
Also applies to: 22-22
🤖 Prompt for AI Agents
In `@bmad-copilot/CHANGELOG.md` at line 3, Check and correct the release dates for
the two CHANGELOG headings "## [0.2.4] — 2026-02-11" and "## [0.2.0] —
2026-02-11": verify source/release tags or git history to determine the true
publish dates, update the incorrect date(s) in CHANGELOG.md accordingly, and if
both dates are intentionally identical, add a brief note under the 0.2.4 entry
explaining that it was a hotfix released the same day (e.g., "hotfix for agent
detection released same day as 0.2.0") so readers understand the reason for the
duplicate date.
|
|
||
| **bmad-copilot-adapter** is a VS Code extension that bridges the [BMAD-METHOD](https://github.com/pi-docket/bmad-method-vscode) command system into GitHub Copilot Chat. It reads the official `.prompt.md` and agent `.md` files generated by the BMAD installer and passes them **directly** to the Copilot LLM — no workflow parsing, no prompt reconstruction, no token management. | ||
|
|
||
| ``` |
There was a problem hiding this comment.
Add language identifiers to fenced code blocks.
markdownlint flags missing languages on multiple fenced blocks; add identifiers (e.g., bash, text) to satisfy MD040.
Also applies to: 111-111, 189-189, 200-200, 281-281, 290-290, 372-372, 399-399
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)
[warning] 48-48: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In `@bmad-copilot/README.md` at line 48, Several fenced code blocks use bare
backticks ("```") without language identifiers causing markdownlint MD040
failures; update each triple-backtick block (the occurrences currently shown as
"```") to include an appropriate language tag (for example "```bash" for shell
commands, "```text" for plain output, or "```yaml"/"```json" where applicable)
so the fenced blocks at the noted locations include explicit language
identifiers.
- Remove auto-install attempt (extension not on Marketplace) - Check if extension already installed - Show build instructions with npm package link if not installed - Update function comments to reflect new behavior - Display clear steps: git clone, npm install, build VSIX, install - Reference: https://www.npmjs.com/package/bmad-copilot-adapter
- Update package.json and package-lock.json - Published to npm: https://www.npmjs.com/package/bmad-copilot-adapter - Generated VSIX: releases/bmad-copilot-adapter-0.2.6.vsix - Installed extension successfully
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@bmad-copilot/package.json`:
- Around line 11-18: The package.json fields "homepage" and the "repository.url"
currently reference the wrong org (pi-docket); update the values so they point
to the canonical repository under bmad-code-org/bmad-method-vscode (replace
"https://github.com/pi-docket/bmad-method-vscode#readme" and
"git+https://github.com/pi-docket/bmad-method-vscode.git" with the corresponding
URLs using bmad-code-org), ensuring the "homepage" and "repository.url" keys
reflect the correct org.
In `@bmad-copilot/src/cli/bootstrap.ts`:
- Line 185: The console.log that prints the VSIX install instruction uses a
hardcoded version string ("console.log(FMT.dim(' code --install-extension
releases/bmad-copilot-adapter-0.2.5.vsix'))") which will become stale; change it
to dynamically read the package version (e.g., require('./package.json').version
or import package.json) and interpolate that version into the string, or emit a
glob/wildcard hint like "releases/bmad-copilot-adapter-*.vsix" so the
instruction always matches the current build; update the code that prints this
message (the console.log call) to use the chosen approach and ensure
tests/consumers still see the correct message.
🧹 Nitpick comments (6)
bmad-copilot/src/cli/bootstrap.ts (3)
298-298:installExtensionisasyncbut contains noawait.All operations inside are synchronous (
spawnSync). Dropasyncand returnStepResultdirectly, or convert to the asynchronous spawn API if non-blocking behavior is intended.
378-425: Four near-identical helpers with redundant directory reads.
hasBmadFiles+countBmadFiles(and the agent equivalents) each callreaddirSyncindependently, meaning Step 2 reads each directory twice. Consider a single parameterized helper:♻️ Suggested consolidation
-function hasBmadFiles(dir: string): boolean { ... } -function hasBmadAgentFiles(dir: string): boolean { ... } -function countBmadFiles(dir: string): number { ... } -function countBmadAgentFiles(dir: string): number { ... } +function countMatchingFiles( + dir: string, + predicate: (name: string) => boolean, +): number { + try { + return fs.readdirSync(dir).filter(predicate).length; + } catch { + return 0; + } +} + +const isBmadPrompt = (f: string) => f.startsWith('bmad') && f.endsWith('.prompt.md'); +const isBmadAgent = (f: string) => f.startsWith('bmad-agent') && f.endsWith('.md');Callers become
countMatchingFiles(dir, isBmadPrompt), and> 0replaces thehas*variants.
129-153: Step 2 and Step 5 duplicate the same prompts/agents detection logic.Lines 130-133 and 337-341 perform identical filesystem checks. Consider computing the prompt/agent counts once at the top of
bootstrapand passing them into the individual step functions to avoid the duplication and redundant I/O.bmad-copilot/package.json (3)
63-64:testscript only runs type-checking — no runtime tests.
"test": "npm run lint"aliases totsc --noEmit, which validates types but won't catch logic bugs. Consider adding at least unit tests for the command registry and prompt-file discovery logic, even if VS Code integration tests are deferred.
45-52: Consider adding an upper bound to thebmad-methodpeer dependency.
">=6.0.0-Beta.1"has no ceiling, so a future v7 breaking change would still satisfy the range. A semver-compatible bound like"^6.0.0-Beta.1"or">=6.0.0-Beta.1 <7.0.0"would be safer.
42-44: Thebinentry is intentional for npm CLI distribution; add.vscodeignoreto exclude it from VSIX if not needed.The
binfield is legitimate—bin/bmad-copilot-adapter.jsexists and provides a CLI interface (npx bmad-copilot-adapter bootstrap|update|status) for npm package distribution. However, without a.vscodeignorefile, thebin/directory will be included in the VSIX package by default. Since the package description states the VSIX is built separately ("not available on Marketplace"), consider adding.vscodeignoreto excludebin/and reduce VSIX size, unless there's a reason to keep it bundled.
| "homepage": "https://github.com/pi-docket/bmad-method-vscode#readme", | ||
| "bugs": { | ||
| "url": "https://github.com/pi-docket/bmad-method-vscode/issues" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/pi-docket/bmad-method-vscode.git" | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git remote -vRepository: bmad-code-org/bmad-method-vscode
Length of output: 228
Update repository URLs to reference the canonical repository.
homepage and repository.url incorrectly reference pi-docket/bmad-method-vscode, but the canonical repository is bmad-code-org/bmad-method-vscode (confirmed by git remote). Update both URLs to point to the correct org so users file issues and find documentation in the right place.
Affected lines
"homepage": "https://github.com/pi-docket/bmad-method-vscode#readme",
...
"repository": {
"type": "git",
"url": "git+https://github.com/pi-docket/bmad-method-vscode.git"
},
Should reference bmad-code-org/bmad-method-vscode instead.
🤖 Prompt for AI Agents
In `@bmad-copilot/package.json` around lines 11 - 18, The package.json fields
"homepage" and the "repository.url" currently reference the wrong org
(pi-docket); update the values so they point to the canonical repository under
bmad-code-org/bmad-method-vscode (replace
"https://github.com/pi-docket/bmad-method-vscode#readme" and
"git+https://github.com/pi-docket/bmad-method-vscode.git" with the corresponding
URLs using bmad-code-org), ensuring the "homepage" and "repository.url" keys
reflect the correct org.
| console.log(FMT.dim(' cd bmad-method-vscode/bmad-copilot')); | ||
| console.log(FMT.dim(' npm install')); | ||
| console.log(FMT.dim(' npm run vsce:package')); | ||
| console.log(FMT.dim(' code --install-extension releases/bmad-copilot-adapter-0.2.5.vsix')); |
There was a problem hiding this comment.
Hardcoded version 0.2.5 in the VSIX install instruction will go stale.
The commit messages mention a bump to 0.2.6, yet this line still references 0.2.5. Either derive the version at runtime (e.g., read from package.json) or use a wildcard/glob hint so users don't install an outdated artifact.
- console.log(FMT.dim(' code --install-extension releases/bmad-copilot-adapter-0.2.5.vsix'));
+ console.log(FMT.dim(' code --install-extension releases/bmad-copilot-adapter-<version>.vsix'));🤖 Prompt for AI Agents
In `@bmad-copilot/src/cli/bootstrap.ts` at line 185, The console.log that prints
the VSIX install instruction uses a hardcoded version string
("console.log(FMT.dim(' code --install-extension
releases/bmad-copilot-adapter-0.2.5.vsix'))") which will become stale; change it
to dynamically read the package version (e.g., require('./package.json').version
or import package.json) and interpolate that version into the string, or emit a
glob/wildcard hint like "releases/bmad-copilot-adapter-*.vsix" so the
instruction always matches the current build; update the code that prints this
message (the console.log call) to use the chosen approach and ensure
tests/consumers still see the correct message.
|
I wanted to try this out but I am stuck. Can you please update the testing instructions in the PR description? I can do step 1 (install bmm using the bmad installer and choose GitHub Copilot) but after that there is no When I do step 1 I get... I have also started a thread in the help forum because I can't even figure out how to use these agents that were installed: https://discord.com/channels/1377115244018532404/1472225071350415422/1472225071350415422 |
|
see attached PDF for use of BMAD agents in Github Copiot
|
Thanks for sharing the PDF — it matches Copilot Chat’s expected behavior (the old “GitHub Copilot” extension is deprecated and replaced by GitHub Copilot Chat). Why you don’t see /status after Step 1 What you did in Step 1 (npx bmad-method install → select GitHub Copilot) is working as intended: it only generates the repo-side Copilot artifacts under .github/agents and .github/prompts. /status (and the “adapter command surface” like /install, /run …, etc.) comes from the bmad-copilot-adapter VS Code extension, because Copilot Chat needs an extension to register and expose these custom commands inside the chat UI. In other words: .github/agents / .github/prompts = content artifacts Copilot can use VS Code extension (adapter) = the thing that provides /status and bridges execution/diagnostics in Copilot Chat Important: not published on VS Code Marketplace yet Right now the extension is not published to the VS Code Marketplace, so you won’t be able to “just install it from the Extensions panel”. You must build a .vsix and install it manually. Updated testing instructions (what I’ll add to the PR) Step 1 — Build and install the VS Code extension (VSIX) git clone https://github.com/pi-docket/bmad-method-vscode.git Notes / sanity checks Make sure GitHub Copilot Chat is installed/enabled in VS Code (the legacy Copilot extension is deprecated). After installing the VSIX, run “Developer: Reload Window” once. Step 2 — Install BMAD-METHOD artifacts into your project cd /path/to/your-project After Step 1 + Step 2, /status should be available in Copilot Chat. How to use the installed BMAD agents in Copilot Chat (from the PDF) If your goal is simply “how do I invoke the agents I see in .github/agents”, you do it via the Copilot Chat UI:
Slash commands tip (also from the PDF) Copilot Chat often needs to cache slash commands too: Use a slash command at least once to cache it After cached, typing /hel should highlight /bmad-help To select a highlighted slash command, press Enter twice Quick troubleshooting (if /status still doesn’t show) Confirm the VSIX is installed: Extensions panel → look for the adapter extension (and ensure it’s enabled). Reload VS Code window once after installing. Make sure you’re typing /status in Copilot Chat, not in the terminal. Confirm you’re using GitHub Copilot Chat (not the deprecated Copilot extension). Reference README for the exact steps above: |
|
I tried both by adding a remote with your fork and switching to your branch, and by cloning your repo and switching to your branch with I think the instructions are missing a compile step, unless it's supposed to be happening automatically. It didn't for me. Claude changed package.json like so and then it worked, but this may not be correct. |
|
Is there a reason it is in a subdirectory? Will it be easy to eventually release to the marketplaces from there? I think we are only going to have one Official VS Code Extension. It can have other features, (I originally wanted to visualize the epics and tech specs files) and they should probably all be configurable or gracefully detect incompatibility -- not everyone uses GitHub Copilot. |
|
thanks — you’re exactly right. The packaging instructions are missing an explicit compile step (or an automatic “prepackage” hook), which is why vsce package can’t find extension/dist/extension.js. What happened npm run vsce:package currently runs npx @vscode/vsce package ... directly, but the extension entrypoint is expected at: extension/dist/extension.js If the TypeScript build hasn’t been run yet, that file doesn’t exist, so vsce fails with:
Correct fix We should ensure the build runs automatically before packaging. Your instinct (adding a build hook) is correct. vsce will run pre for npm scripts, so the most direct fix is to add: "scripts": { (Using prevsce only works if the script is literally named vsce, which it isn’t here — so prevsce:package is the right hook for vsce:package.) Workaround (until I push the fix) You can also run the build manually: npm install I’ll update the PR description/testing instructions and adjust the package scripts so npm run vsce:package is self-contained and works from a clean checkout. |
|
@wsmoak thanks again — and sorry for the churn here. While looking into the packaging/build issue you hit, I also realized a couple of problems in the current user interaction/command surface that I’d like to fix properly rather than patching around. That will require some larger changes (I want to make the onboarding + Could you give me a bit of time to rework this? I’ll push an update that:
In the meantime, your workaround ( |
I completely agree with your direction here, and yes — this is one of the reasons I have not tried to publish anything to the VS Code Marketplace yet. I do not want to create a situation where we end up with multiple “official-ish” extensions, or where users install something that only works in a narrow Copilot-specific setup and then get stuck. If the goal is one Official VS Code Extension, then we should treat Copilot (and any other chat provider) as an optional integration that the extension can detect and enable when available. I support the approach you described:
Concretely, I think the extension should be structured as:
This also ties into the documentation problem we are seeing in this PR thread: users can generate My plan for the next update to this PR is to align with that “single extension, optional integrations” model:
Once those changes are in place, the project will be in a much better state to consider Marketplace publishing, without confusing users or locking the “official” direction into an early, Copilot-only shape. |
|
Sounds good! Same, I made that original VS Code extension on a whim (be like Kiro!) and knew I should not publish it due to trademarks/naming/potential confusion. If you have not wandered over to Discord yet and you have time, posting some screenshots of this in the Showcase would be good. Link here in the Community section of the README |
What
Introduce a GitHub Copilot Chat adapter that enables BMAD workflows to be executed inside VS Code using the officially generated
.github/promptsand.github/agentsartifacts.This implementation strictly relies on installer-generated prompt files and does not re-implement or reinterpret workflow logic.
Why
BMAD users increasingly operate within VS Code with GitHub Copilot Chat. While BMAD provides installer support for Copilot tool artifacts, missing prompt files can lead to confusion and inconsistent execution paths.
This PR ensures:
The adapter acts purely as a transport layer between BMAD’s official prompt artifacts and Copilot Chat.
How
/run <command>to installer-generated prompt files./statusdiagnostics for missing.github/prompts./installterminal bridge.Testing
Manual verification on Windows:
/statusto confirm_bmad/detection..github/promptsdiscovery./run <command>workflows end-to-end.✅ EXTENDED DESIGN NOTES (For Maintainers)
Below this section in your PR, add:
Design Philosophy
This adapter intentionally avoids:
_bmadresourcesInstead, it executes only officially generated prompt files.
The goal is long-term maintainability and upstream alignment.
Any future changes to prompt structure will propagate automatically through installer artifacts without requiring adapter updates.
Alignment with Upstream Installer Behavior
During testing, it was observed that in certain update scenarios:
In these cases,
.github/promptsmay not be regenerated.Rather than implementing speculative prompt generation, this adapter:
This preserves official ownership of artifact generation.
Why Not Auto-Generate Prompts from Manifests?
Although technically possible, generating Copilot prompts from manifest CSV files would:
This PR deliberately avoids that approach.
All execution relies on installer-produced artifacts.
Execution Model
The adapter:
.github/prompts/*.prompt.md_bmadresourcesThis mirrors the official Copilot tool integration model.
Windows Support
All examples and diagnostics include PowerShell-compatible commands:
No Cloud Code CLI dependency is required.
Only installer-generated artifacts are used.
Backward Compatibility
This PR:
_bmad/It adds an execution surface only.
Future Maintenance
Because execution relies exclusively on official prompt files:
This minimizes long-term maintenance burden.
Summary
This PR enables BMAD workflows to be executed within GitHub Copilot Chat using official installer artifacts while preserving strict alignment with upstream design principles.
✅ Tone Analysis (Why Maintainers Will Like This)
This PR description:
Maintainers care about:
Your description proactively addresses all of those.
Summary by CodeRabbit
New Features
Documentation
Chores