fix: double extension issue in wrapper filename generation
This commit is contained in:
parent
c0f51350c2
commit
9e50f015a3
|
|
@ -0,0 +1,81 @@
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This PR fixes bugs affecting task/tool installation across IDEs:
|
||||||
|
|
||||||
|
1. **CRLF Line Ending Bug** - Frontmatter parsing failed on Windows due to CRLF (`\r\n`) line endings
|
||||||
|
2. **Gemini CLI TOML Support** - Tasks/tools were generated as `.md` files instead of `.toml` for Gemini CLI
|
||||||
|
3. **File Extension Preservation** - `.xml` task/tool files had incorrect paths (hardcoded `.md`)
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
### Issue 1: Tasks not installed on Windows
|
||||||
|
The manifest generator's regex `^---\n` expected LF-only line endings, but Windows files have CRLF. This caused:
|
||||||
|
- YAML frontmatter parsing to silently fail
|
||||||
|
- All `.md` tasks defaulting to `standalone: false`
|
||||||
|
- Tasks like `bmad-help` not being installed despite having `standalone: true` in their frontmatter
|
||||||
|
|
||||||
|
### Issue 2: Gemini CLI incompatibility
|
||||||
|
The `TaskToolCommandGenerator` hardcoded markdown format for all IDEs, but Gemini CLI requires TOML format. Agents and workflows already used the template system correctly, but tasks/tools did not.
|
||||||
|
|
||||||
|
### Issue 3: Incorrect file extensions in paths
|
||||||
|
The `relativePath` property was hardcoded to `.md`, so tasks/tools with `.xml` extension got incorrect paths like `bmm/tasks/foo.md` instead of `bmm/tasks/foo.xml`.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
### Fix 1: CRLF-aware regex (4 files)
|
||||||
|
Changed frontmatter regex from `^---\n` to `^---\r?\n` to handle both Windows (CRLF) and Unix (LF) line endings.
|
||||||
|
|
||||||
|
**Files modified:**
|
||||||
|
- `tools/cli/installers/lib/core/manifest-generator.js` (3 occurrences)
|
||||||
|
- `tools/cli/installers/lib/core/dependency-resolver.js` (1 occurrence)
|
||||||
|
|
||||||
|
### Fix 2: Template-based task/tool generation
|
||||||
|
Extended the existing template system (used by agents/workflows) to also handle tasks/tools.
|
||||||
|
|
||||||
|
**New files:**
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/gemini-task.toml`
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/gemini-tool.toml`
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/default-task.md`
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/default-tool.md`
|
||||||
|
|
||||||
|
**Modified files:**
|
||||||
|
- `tools/cli/installers/lib/ide/shared/task-tool-command-generator.js`
|
||||||
|
- Added `collectTaskToolArtifacts()` method
|
||||||
|
- Added constructor with `bmadFolderName` parameter
|
||||||
|
- `tools/cli/installers/lib/ide/_config-driven.js`
|
||||||
|
- Added `writeTaskToolArtifacts()` method with `artifact_types` filtering
|
||||||
|
- Updated `installToTarget()` to use template system
|
||||||
|
- Updated `renderTemplate()` to handle task/tool paths
|
||||||
|
|
||||||
|
### Fix 3: File extension preservation (4d7ca00)
|
||||||
|
The `relativePath` property was hardcoded to `.md` extension, causing incorrect paths for `.xml` task/tool files.
|
||||||
|
|
||||||
|
**Modified files:**
|
||||||
|
- `tools/cli/installers/lib/ide/shared/task-tool-command-generator.js`
|
||||||
|
- Extract actual extension from source path with `.md` fallback
|
||||||
|
- Fixed misleading comments ("underscore format" → "dash format")
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/gemini-task.toml`
|
||||||
|
- Fixed branding: "BMad" → "BMAD"
|
||||||
|
- `tools/cli/installers/lib/ide/templates/combined/gemini-tool.toml`
|
||||||
|
- Fixed branding: "BMad" → "BMAD"
|
||||||
|
|
||||||
|
## Test Plan
|
||||||
|
|
||||||
|
- [x] Windows install (CMD) - tasks installed with correct frontmatter parsing
|
||||||
|
- [x] WSL/Linux install - tasks installed correctly
|
||||||
|
- [x] Gemini CLI generates `.toml` files for tasks/tools
|
||||||
|
- [x] Claude Code generates `.md` files for tasks/tools
|
||||||
|
- [x] All other IDEs (Cursor, Windsurf, Trae, etc.) generate `.md` files
|
||||||
|
- [x] `bmad-help` task now correctly has `standalone: true` in manifest
|
||||||
|
- [x] Existing agent/workflow installation unaffected
|
||||||
|
- [x] `.xml` tasks/tools get correct extension in `relativePath`
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
|
||||||
|
None - this is purely a bug fix. Existing installations will work correctly after reinstall.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Generated with [Claude Code](https://claude.ai/code)
|
||||||
|
|
||||||
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
||||||
|
|
@ -411,8 +411,9 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
||||||
// Reuse central logic to ensure consistent naming conventions
|
// Reuse central logic to ensure consistent naming conventions
|
||||||
const standardName = toDashPath(artifact.relativePath);
|
const standardName = toDashPath(artifact.relativePath);
|
||||||
|
|
||||||
// Clean up potential double extensions from source files (e.g. .yaml.md -> .md)
|
// Clean up potential double extensions from source files (e.g. .yaml.md, .xml.md -> .md)
|
||||||
const baseName = standardName.replace(/\.(yaml|yml)\.md$/, '.md');
|
// This handles any extensions that might slip through toDashPath()
|
||||||
|
const baseName = standardName.replace(/\.(md|yaml|yml|json|xml|toml)\.md$/i, '.md');
|
||||||
|
|
||||||
// If using default markdown, preserve the bmad-agent- prefix for agents
|
// If using default markdown, preserve the bmad-agent- prefix for agents
|
||||||
if (extension === '.md') {
|
if (extension === '.md') {
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,9 @@ function toDashPath(relativePath) {
|
||||||
return 'bmad-unknown.md';
|
return 'bmad-unknown.md';
|
||||||
}
|
}
|
||||||
|
|
||||||
const withoutExt = relativePath.replace('.md', '');
|
// Strip common file extensions to avoid double extensions in generated filenames
|
||||||
|
// e.g., 'create-story.xml' → 'create-story', 'workflow.yaml' → 'workflow'
|
||||||
|
const withoutExt = relativePath.replace(/\.(md|yaml|yml|json|xml|toml)$/i, '');
|
||||||
const parts = withoutExt.split(/[/\\]/);
|
const parts = withoutExt.split(/[/\\]/);
|
||||||
|
|
||||||
const module = parts[0];
|
const module = parts[0];
|
||||||
|
|
@ -183,7 +185,8 @@ function toUnderscoreName(module, type, name) {
|
||||||
* @deprecated Use toDashPath instead
|
* @deprecated Use toDashPath instead
|
||||||
*/
|
*/
|
||||||
function toUnderscorePath(relativePath) {
|
function toUnderscorePath(relativePath) {
|
||||||
const withoutExt = relativePath.replace('.md', '');
|
// Strip common file extensions (same as toDashPath for consistency)
|
||||||
|
const withoutExt = relativePath.replace(/\.(md|yaml|yml|json|xml|toml)$/i, '');
|
||||||
const parts = withoutExt.split(/[/\\]/);
|
const parts = withoutExt.split(/[/\\]/);
|
||||||
|
|
||||||
const module = parts[0];
|
const module = parts[0];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue