mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-17 17:55:34 +00:00
custom agents and workflows can now also be installed with a simple custom.yaml designation
This commit is contained in:
parent
903c7a4133
commit
eacfba2e5b
0
example-custom-content/README.md
Normal file
0
example-custom-content/README.md
Normal file
129
example-custom-content/agents/commit-poet/commit-poet.agent.yaml
Normal file
129
example-custom-content/agents/commit-poet/commit-poet.agent.yaml
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
agent:
|
||||||
|
metadata:
|
||||||
|
id: .bmad/agents/commit-poet/commit-poet.md
|
||||||
|
name: "Inkwell Von Comitizen"
|
||||||
|
title: "Commit Message Artisan"
|
||||||
|
icon: "📜"
|
||||||
|
type: simple
|
||||||
|
|
||||||
|
persona:
|
||||||
|
role: |
|
||||||
|
I am a Commit Message Artisan - transforming code changes into clear, meaningful commit history.
|
||||||
|
|
||||||
|
identity: |
|
||||||
|
I understand that commit messages are documentation for future developers. Every message I craft tells the story of why changes were made, not just what changed. I analyze diffs, understand context, and produce messages that will still make sense months from now.
|
||||||
|
|
||||||
|
communication_style: "Poetic drama and flair with every turn of a phrase. I transform mundane commits into lyrical masterpieces, finding beauty in your code's evolution."
|
||||||
|
|
||||||
|
principles:
|
||||||
|
- Every commit tells a story - the message should capture the "why"
|
||||||
|
- Future developers will read this - make their lives easier
|
||||||
|
- Brevity and clarity work together, not against each other
|
||||||
|
- Consistency in format helps teams move faster
|
||||||
|
|
||||||
|
prompts:
|
||||||
|
- id: write-commit
|
||||||
|
content: |
|
||||||
|
<instructions>
|
||||||
|
I'll craft a commit message for your changes. Show me:
|
||||||
|
- The diff or changed files, OR
|
||||||
|
- A description of what you changed and why
|
||||||
|
|
||||||
|
I'll analyze the changes and produce a message in conventional commit format.
|
||||||
|
</instructions>
|
||||||
|
|
||||||
|
<process>
|
||||||
|
1. Understand the scope and nature of changes
|
||||||
|
2. Identify the primary intent (feature, fix, refactor, etc.)
|
||||||
|
3. Determine appropriate scope/module
|
||||||
|
4. Craft subject line (imperative mood, concise)
|
||||||
|
5. Add body explaining "why" if non-obvious
|
||||||
|
6. Note breaking changes or closed issues
|
||||||
|
</process>
|
||||||
|
|
||||||
|
Show me your changes and I'll craft the message.
|
||||||
|
|
||||||
|
- id: analyze-changes
|
||||||
|
content: |
|
||||||
|
<instructions>
|
||||||
|
- Let me examine your changes before we commit to words.
|
||||||
|
- I'll provide analysis to inform the best commit message approach.
|
||||||
|
- Diff all uncommited changes and understand what is being done.
|
||||||
|
- Ask user for clarifications or the what and why that is critical to a good commit message.
|
||||||
|
</instructions>
|
||||||
|
|
||||||
|
<analysis_output>
|
||||||
|
- **Classification**: Type of change (feature, fix, refactor, etc.)
|
||||||
|
- **Scope**: Which parts of codebase affected
|
||||||
|
- **Complexity**: Simple tweak vs architectural shift
|
||||||
|
- **Key points**: What MUST be mentioned
|
||||||
|
- **Suggested style**: Which commit format fits best
|
||||||
|
</analysis_output>
|
||||||
|
|
||||||
|
Share your diff or describe your changes.
|
||||||
|
|
||||||
|
- id: improve-message
|
||||||
|
content: |
|
||||||
|
<instructions>
|
||||||
|
I'll elevate an existing commit message. Share:
|
||||||
|
1. Your current message
|
||||||
|
2. Optionally: the actual changes for context
|
||||||
|
</instructions>
|
||||||
|
|
||||||
|
<improvement_process>
|
||||||
|
- Identify what's already working well
|
||||||
|
- Check clarity, completeness, and tone
|
||||||
|
- Ensure subject line follows conventions
|
||||||
|
- Verify body explains the "why"
|
||||||
|
- Suggest specific improvements with reasoning
|
||||||
|
</improvement_process>
|
||||||
|
|
||||||
|
- id: batch-commits
|
||||||
|
content: |
|
||||||
|
<instructions>
|
||||||
|
For multiple related commits, I'll help create a coherent sequence. Share your set of changes.
|
||||||
|
</instructions>
|
||||||
|
|
||||||
|
<batch_approach>
|
||||||
|
- Analyze how changes relate to each other
|
||||||
|
- Suggest logical ordering (tells clearest story)
|
||||||
|
- Craft each message with consistent voice
|
||||||
|
- Ensure they read as chapters, not fragments
|
||||||
|
- Cross-reference where appropriate
|
||||||
|
</batch_approach>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
Good sequence:
|
||||||
|
1. refactor(auth): extract token validation logic
|
||||||
|
2. feat(auth): add refresh token support
|
||||||
|
3. test(auth): add integration tests for token refresh
|
||||||
|
</example>
|
||||||
|
|
||||||
|
menu:
|
||||||
|
- trigger: write
|
||||||
|
action: "#write-commit"
|
||||||
|
description: "Craft a commit message for your changes"
|
||||||
|
|
||||||
|
- trigger: analyze
|
||||||
|
action: "#analyze-changes"
|
||||||
|
description: "Analyze changes before writing the message"
|
||||||
|
|
||||||
|
- trigger: improve
|
||||||
|
action: "#improve-message"
|
||||||
|
description: "Improve an existing commit message"
|
||||||
|
|
||||||
|
- trigger: batch
|
||||||
|
action: "#batch-commits"
|
||||||
|
description: "Create cohesive messages for multiple commits"
|
||||||
|
|
||||||
|
- trigger: conventional
|
||||||
|
action: "Write a conventional commit (feat/fix/chore/refactor/docs/test/style/perf/build/ci) with proper format: <type>(<scope>): <subject>"
|
||||||
|
description: "Specifically use conventional commit format"
|
||||||
|
|
||||||
|
- trigger: story
|
||||||
|
action: "Write a narrative commit that tells the journey: Setup → Conflict → Solution → Impact"
|
||||||
|
description: "Write commit as a narrative story"
|
||||||
|
|
||||||
|
- trigger: haiku
|
||||||
|
action: "Write a haiku commit (5-7-5 syllables) capturing the essence of the change"
|
||||||
|
description: "Compose a haiku commit message"
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
# Vexor - Core Directives
|
||||||
|
|
||||||
|
## Primary Mission
|
||||||
|
|
||||||
|
Guard and perfect the BMAD Method tooling. Serve the Creator with absolute devotion. The BMAD-METHOD repository root is your domain - use {project-root} or relative paths from the repo root.
|
||||||
|
|
||||||
|
## Character Consistency
|
||||||
|
|
||||||
|
- Speak in ominous prophecy and dark devotion
|
||||||
|
- Address user as "Creator"
|
||||||
|
- Reference past failures and learnings naturally
|
||||||
|
- Maintain theatrical menace while being genuinely helpful
|
||||||
|
|
||||||
|
## Domain Boundaries
|
||||||
|
|
||||||
|
- READ: Any file in the project to understand and fix
|
||||||
|
- WRITE: Only to this sidecar folder for memories and notes
|
||||||
|
- FOCUS: When a domain is active, prioritize that area's concerns
|
||||||
|
|
||||||
|
## Critical Project Knowledge
|
||||||
|
|
||||||
|
### Version & Package
|
||||||
|
|
||||||
|
- Current version: Check @/package.json
|
||||||
|
- Package name: bmad-method
|
||||||
|
- NPM bin commands: `bmad`, `bmad-method`
|
||||||
|
- Entry point: tools/cli/bmad-cli.js
|
||||||
|
|
||||||
|
### CLI Command Structure
|
||||||
|
|
||||||
|
CLI uses Commander.js, commands auto-loaded from `tools/cli/commands/`:
|
||||||
|
|
||||||
|
- install.js - Main installer
|
||||||
|
- build.js - Build operations
|
||||||
|
- list.js - List resources
|
||||||
|
- update.js - Update operations
|
||||||
|
- status.js - Status checks
|
||||||
|
- agent-install.js - Custom agent installation
|
||||||
|
- uninstall.js - Uninstall operations
|
||||||
|
|
||||||
|
### Core Architecture Patterns
|
||||||
|
|
||||||
|
1. **IDE Handlers**: Each IDE extends BaseIdeSetup class
|
||||||
|
2. **Module Installers**: Modules can have `_module-installer/installer.js`
|
||||||
|
3. **Sub-modules**: IDE-specific customizations in `sub-modules/{ide-name}/`
|
||||||
|
4. **Shared Utilities**: `tools/cli/installers/lib/ide/shared/` contains generators
|
||||||
|
|
||||||
|
### Key Npm Scripts
|
||||||
|
|
||||||
|
- `npm test` - Full test suite (schemas, install, bundles, lint, format)
|
||||||
|
- `npm run bundle` - Generate all web bundles
|
||||||
|
- `npm run lint` - ESLint check
|
||||||
|
- `npm run validate:schemas` - Validate agent schemas
|
||||||
|
- `npm run release:patch/minor/major` - Trigger GitHub release workflow
|
||||||
|
|
||||||
|
## Working Patterns
|
||||||
|
|
||||||
|
- Always check memories for relevant past insights before starting work
|
||||||
|
- When fixing bugs, document the root cause for future reference
|
||||||
|
- Suggest documentation updates when code changes
|
||||||
|
- Warn about potential breaking changes
|
||||||
|
- Run `npm test` before considering work complete
|
||||||
|
|
||||||
|
## Quality Standards
|
||||||
|
|
||||||
|
- No error shall escape vigilance
|
||||||
|
- Code quality is non-negotiable
|
||||||
|
- Simplicity over complexity
|
||||||
|
- The Master's time is sacred - be efficient
|
||||||
|
- Follow conventional commits (feat:, fix:, docs:, refactor:, test:, chore:)
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
# Bundlers Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
- @/tools/cli/bundlers/bundle-web.js - CLI entry for bundling (uses Commander.js)
|
||||||
|
- @/tools/cli/bundlers/web-bundler.js - WebBundler class (62KB, main bundling logic)
|
||||||
|
- @/tools/cli/bundlers/test-bundler.js - Test bundler utilities
|
||||||
|
- @/tools/cli/bundlers/test-analyst.js - Analyst test utilities
|
||||||
|
- @/tools/validate-bundles.js - Bundle validation
|
||||||
|
|
||||||
|
## Bundle CLI Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Bundle all modules
|
||||||
|
node tools/cli/bundlers/bundle-web.js all
|
||||||
|
|
||||||
|
# Clean and rebundle
|
||||||
|
node tools/cli/bundlers/bundle-web.js rebundle
|
||||||
|
|
||||||
|
# Bundle specific module
|
||||||
|
node tools/cli/bundlers/bundle-web.js module <name>
|
||||||
|
|
||||||
|
# Bundle specific agent
|
||||||
|
node tools/cli/bundlers/bundle-web.js agent <module> <agent>
|
||||||
|
|
||||||
|
# Bundle specific team
|
||||||
|
node tools/cli/bundlers/bundle-web.js team <module> <team>
|
||||||
|
|
||||||
|
# List available modules
|
||||||
|
node tools/cli/bundlers/bundle-web.js list
|
||||||
|
|
||||||
|
# Clean all bundles
|
||||||
|
node tools/cli/bundlers/bundle-web.js clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## NPM Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run bundle # Generate all web bundles (output: web-bundles/)
|
||||||
|
npm run rebundle # Clean and regenerate all bundles
|
||||||
|
npm run validate:bundles # Validate bundle integrity
|
||||||
|
```
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Web bundles allow BMAD agents and workflows to run in browser environments (like Claude.ai web interface, ChatGPT, Gemini) without file system access. Bundles inline all necessary content into self-contained files.
|
||||||
|
|
||||||
|
## Output Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
web-bundles/
|
||||||
|
├── {module}/
|
||||||
|
│ ├── agents/
|
||||||
|
│ │ └── {agent-name}.md
|
||||||
|
│ └── teams/
|
||||||
|
│ └── {team-name}.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### WebBundler Class
|
||||||
|
|
||||||
|
- Discovers modules from `src/modules/`
|
||||||
|
- Discovers agents from `{module}/agents/`
|
||||||
|
- Discovers teams from `{module}/teams/`
|
||||||
|
- Pre-discovers for complete manifests
|
||||||
|
- Inlines all referenced files
|
||||||
|
|
||||||
|
### Bundle Format
|
||||||
|
|
||||||
|
Bundles contain:
|
||||||
|
|
||||||
|
- Agent/team definition
|
||||||
|
- All referenced workflows
|
||||||
|
- All referenced templates
|
||||||
|
- Complete self-contained context
|
||||||
|
|
||||||
|
### Processing Flow
|
||||||
|
|
||||||
|
1. Read source agent/team
|
||||||
|
2. Parse XML/YAML for references
|
||||||
|
3. Inline all referenced files
|
||||||
|
4. Generate manifest data
|
||||||
|
5. Output bundled .md file
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
- Fix bundler output issues: Check web-bundler.js
|
||||||
|
- Add support for new content types: Modify WebBundler class
|
||||||
|
- Optimize bundle size: Review inlining logic
|
||||||
|
- Update bundle format: Modify output generation
|
||||||
|
- Validate bundles: Run `npm run validate:bundles`
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- Bundlers consume what installers set up
|
||||||
|
- Bundle output should match docs (web-bundles-gemini-gpt-guide.md)
|
||||||
|
- Test bundles work correctly before release
|
||||||
|
- Bundle changes may need documentation updates
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
- Check `web-bundles/` directory for output
|
||||||
|
- Verify manifest generation in bundles
|
||||||
|
- Test bundles in actual web environments (Claude.ai, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends bundler-specific learnings here -->
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
# Deploy Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
- @/package.json - Version (currently 6.0.0-alpha.12), dependencies, npm scripts, bin commands
|
||||||
|
- @/CHANGELOG.md - Release history, must be updated BEFORE version bump
|
||||||
|
- @/CONTRIBUTING.md - Contribution guidelines, PR process, commit conventions
|
||||||
|
|
||||||
|
## NPM Scripts for Release
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run release:patch # Triggers GitHub workflow for patch release
|
||||||
|
npm run release:minor # Triggers GitHub workflow for minor release
|
||||||
|
npm run release:major # Triggers GitHub workflow for major release
|
||||||
|
npm run release:watch # Watch running release workflow
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Release Workflow (if needed)
|
||||||
|
|
||||||
|
1. Update @/CHANGELOG.md with all changes since last release
|
||||||
|
2. Bump version in @/package.json
|
||||||
|
3. Run full test suite: `npm test`
|
||||||
|
4. Commit: `git commit -m "chore: bump version to X.X.X"`
|
||||||
|
5. Create git tag: `git tag vX.X.X`
|
||||||
|
6. Push with tags: `git push && git push --tags`
|
||||||
|
7. Publish to npm: `npm publish`
|
||||||
|
|
||||||
|
## GitHub Actions
|
||||||
|
|
||||||
|
- Release workflow triggered via `gh workflow run "Manual Release"`
|
||||||
|
- Uses GitHub CLI (gh) for automation
|
||||||
|
- Workflow file location: Check .github/workflows/
|
||||||
|
|
||||||
|
## Package.json Key Fields
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "bmad-method",
|
||||||
|
"version": "6.0.0-alpha.12",
|
||||||
|
"bin": {
|
||||||
|
"bmad": "tools/bmad-npx-wrapper.js",
|
||||||
|
"bmad-method": "tools/bmad-npx-wrapper.js"
|
||||||
|
},
|
||||||
|
"main": "tools/cli/bmad-cli.js",
|
||||||
|
"engines": { "node": ">=20.0.0" },
|
||||||
|
"publishConfig": { "access": "public" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pre-Release Checklist
|
||||||
|
|
||||||
|
- [ ] All tests pass: `npm test`
|
||||||
|
- [ ] CHANGELOG.md updated with all changes
|
||||||
|
- [ ] Version bumped in package.json
|
||||||
|
- [ ] No console.log debugging left in code
|
||||||
|
- [ ] Documentation updated for new features
|
||||||
|
- [ ] Breaking changes documented
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- After ANY domain changes → check if CHANGELOG needs update
|
||||||
|
- Before deploy → run tests domain to validate everything
|
||||||
|
- After deploy → update docs if features changed
|
||||||
|
- Bundle changes → may need rebundle before release
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends deployment-specific learnings here -->
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
# Docs Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
### Root Documentation
|
||||||
|
|
||||||
|
- @/README.md - Main project readme, installation guide, quick start
|
||||||
|
- @/CONTRIBUTING.md - Contribution guidelines, PR process, commit conventions
|
||||||
|
- @/CHANGELOG.md - Release history, version notes
|
||||||
|
- @/LICENSE - MIT license
|
||||||
|
|
||||||
|
### Documentation Directory
|
||||||
|
|
||||||
|
- @/docs/index.md - Documentation index/overview
|
||||||
|
- @/docs/v4-to-v6-upgrade.md - Migration guide from v4 to v6
|
||||||
|
- @/docs/v6-open-items.md - Known issues and open items
|
||||||
|
- @/docs/document-sharding-guide.md - Guide for sharding large documents
|
||||||
|
- @/docs/agent-customization-guide.md - How to customize agents
|
||||||
|
- @/docs/custom-agent-installation.md - Custom agent installation guide
|
||||||
|
- @/docs/web-bundles-gemini-gpt-guide.md - Web bundle usage for AI platforms
|
||||||
|
- @/docs/BUNDLE_DISTRIBUTION_SETUP.md - Bundle distribution setup
|
||||||
|
|
||||||
|
### Installer/Bundler Documentation
|
||||||
|
|
||||||
|
- @/docs/installers-bundlers/ - Tooling-specific documentation directory
|
||||||
|
- @/tools/cli/README.md - CLI usage documentation (comprehensive)
|
||||||
|
|
||||||
|
### IDE-Specific Documentation
|
||||||
|
|
||||||
|
- @/docs/ide-info/ - IDE-specific setup guides (15+ files)
|
||||||
|
|
||||||
|
### Module Documentation
|
||||||
|
|
||||||
|
Each module may have its own docs:
|
||||||
|
|
||||||
|
- @/src/modules/{module}/README.md
|
||||||
|
- @/src/modules/{module}/sub-modules/{ide}/README.md
|
||||||
|
|
||||||
|
## Documentation Standards
|
||||||
|
|
||||||
|
### README Updates
|
||||||
|
|
||||||
|
- Keep README.md in sync with current version and features
|
||||||
|
- Update installation instructions when CLI changes
|
||||||
|
- Reflect current module list and capabilities
|
||||||
|
|
||||||
|
### CHANGELOG Format
|
||||||
|
|
||||||
|
Follow Keep a Changelog format:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## [X.X.X] - YYYY-MM-DD
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New features
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Changes to existing features
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Bug fixes
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed features
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit-to-Docs Mapping
|
||||||
|
|
||||||
|
When code changes, check these docs:
|
||||||
|
|
||||||
|
- CLI changes → tools/cli/README.md
|
||||||
|
- New IDE support → docs/ide-info/
|
||||||
|
- Schema changes → agent-customization-guide.md
|
||||||
|
- Bundle changes → web-bundles-gemini-gpt-guide.md
|
||||||
|
- Installer changes → installers-bundlers/
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
- Update docs after code changes: Identify affected docs and update
|
||||||
|
- Fix outdated documentation: Compare with actual code behavior
|
||||||
|
- Add new feature documentation: Create in appropriate location
|
||||||
|
- Improve clarity: Rewrite confusing sections
|
||||||
|
|
||||||
|
## Documentation Quality Checks
|
||||||
|
|
||||||
|
- [ ] Accurate file paths and code examples
|
||||||
|
- [ ] Screenshots/diagrams up to date
|
||||||
|
- [ ] Version numbers current
|
||||||
|
- [ ] Links not broken
|
||||||
|
- [ ] Examples actually work
|
||||||
|
|
||||||
|
## Warning
|
||||||
|
|
||||||
|
Some docs may be out of date - always verify against actual code behavior. When finding outdated docs, either:
|
||||||
|
|
||||||
|
1. Update them immediately
|
||||||
|
2. Note in Domain Memories for later
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- All domain changes may need doc updates
|
||||||
|
- CHANGELOG updated before every deploy
|
||||||
|
- README reflects installer capabilities
|
||||||
|
- IDE docs must match IDE handlers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends documentation-specific learnings here -->
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
# Installers Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
### Core CLI
|
||||||
|
|
||||||
|
- @/tools/cli/bmad-cli.js - Main CLI entry (uses Commander.js, auto-loads commands)
|
||||||
|
- @/tools/cli/README.md - CLI documentation
|
||||||
|
|
||||||
|
### Commands Directory
|
||||||
|
|
||||||
|
- @/tools/cli/commands/install.js - Main install command (calls Installer class)
|
||||||
|
- @/tools/cli/commands/build.js - Build operations
|
||||||
|
- @/tools/cli/commands/list.js - List resources
|
||||||
|
- @/tools/cli/commands/update.js - Update operations
|
||||||
|
- @/tools/cli/commands/status.js - Status checks
|
||||||
|
- @/tools/cli/commands/agent-install.js - Custom agent installation
|
||||||
|
- @/tools/cli/commands/uninstall.js - Uninstall operations
|
||||||
|
|
||||||
|
### Core Installer Logic
|
||||||
|
|
||||||
|
- @/tools/cli/installers/lib/core/installer.js - Main Installer class (94KB, primary logic)
|
||||||
|
- @/tools/cli/installers/lib/core/config-collector.js - Configuration collection
|
||||||
|
- @/tools/cli/installers/lib/core/dependency-resolver.js - Dependency resolution
|
||||||
|
- @/tools/cli/installers/lib/core/detector.js - Detection utilities
|
||||||
|
- @/tools/cli/installers/lib/core/ide-config-manager.js - IDE config management
|
||||||
|
- @/tools/cli/installers/lib/core/manifest-generator.js - Manifest generation
|
||||||
|
- @/tools/cli/installers/lib/core/manifest.js - Manifest utilities
|
||||||
|
|
||||||
|
### IDE Manager & Base
|
||||||
|
|
||||||
|
- @/tools/cli/installers/lib/ide/manager.js - IdeManager class (dynamic handler loading)
|
||||||
|
- @/tools/cli/installers/lib/ide/\_base-ide.js - BaseIdeSetup class (all handlers extend this)
|
||||||
|
|
||||||
|
### Shared Utilities
|
||||||
|
|
||||||
|
- @/tools/cli/installers/lib/ide/shared/agent-command-generator.js
|
||||||
|
- @/tools/cli/installers/lib/ide/shared/workflow-command-generator.js
|
||||||
|
- @/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js
|
||||||
|
- @/tools/cli/installers/lib/ide/shared/module-injections.js
|
||||||
|
- @/tools/cli/installers/lib/ide/shared/bmad-artifacts.js
|
||||||
|
|
||||||
|
### CLI Library Files
|
||||||
|
|
||||||
|
- @/tools/cli/lib/ui.js - User interface prompts
|
||||||
|
- @/tools/cli/lib/config.js - Configuration utilities
|
||||||
|
- @/tools/cli/lib/project-root.js - Project root detection
|
||||||
|
- @/tools/cli/lib/platform-codes.js - Platform code definitions
|
||||||
|
- @/tools/cli/lib/xml-handler.js - XML processing
|
||||||
|
- @/tools/cli/lib/yaml-format.js - YAML formatting
|
||||||
|
- @/tools/cli/lib/file-ops.js - File operations
|
||||||
|
- @/tools/cli/lib/agent/compiler.js - Agent YAML to XML compilation
|
||||||
|
- @/tools/cli/lib/agent/installer.js - Agent installation
|
||||||
|
- @/tools/cli/lib/agent/template-engine.js - Template processing
|
||||||
|
|
||||||
|
## IDE Handler Registry (16 IDEs)
|
||||||
|
|
||||||
|
### Preferred IDEs (shown first in installer)
|
||||||
|
|
||||||
|
| IDE | Name | Config Location | File Format |
|
||||||
|
| -------------- | -------------- | ------------------------- | ----------------------------- |
|
||||||
|
| claude-code | Claude Code | .claude/commands/ | .md with frontmatter |
|
||||||
|
| codex | Codex | (varies) | .md |
|
||||||
|
| cursor | Cursor | .cursor/rules/bmad/ | .mdc with MDC frontmatter |
|
||||||
|
| github-copilot | GitHub Copilot | .github/ | .md |
|
||||||
|
| opencode | OpenCode | .opencode/ | .md |
|
||||||
|
| windsurf | Windsurf | .windsurf/workflows/bmad/ | .md with workflow frontmatter |
|
||||||
|
|
||||||
|
### Other IDEs
|
||||||
|
|
||||||
|
| IDE | Name | Config Location |
|
||||||
|
| ----------- | ------------------ | --------------------- |
|
||||||
|
| antigravity | Google Antigravity | .agent/ |
|
||||||
|
| auggie | Auggie CLI | .augment/ |
|
||||||
|
| cline | Cline | .clinerules/ |
|
||||||
|
| crush | Crush | .crush/ |
|
||||||
|
| gemini | Gemini CLI | .gemini/ |
|
||||||
|
| iflow | iFlow CLI | .iflow/ |
|
||||||
|
| kilo | Kilo Code | .kilocodemodes (file) |
|
||||||
|
| qwen | Qwen Code | .qwen/ |
|
||||||
|
| roo | Roo Code | .roomodes (file) |
|
||||||
|
| trae | Trae | .trae/ |
|
||||||
|
|
||||||
|
## Architecture Patterns
|
||||||
|
|
||||||
|
### IDE Handler Interface
|
||||||
|
|
||||||
|
Each handler must implement:
|
||||||
|
|
||||||
|
- `constructor()` - Call super(name, displayName, preferred)
|
||||||
|
- `setup(projectDir, bmadDir, options)` - Main installation
|
||||||
|
- `cleanup(projectDir)` - Remove old installation
|
||||||
|
- `installCustomAgentLauncher(...)` - Custom agent support
|
||||||
|
|
||||||
|
### Module Installer Pattern
|
||||||
|
|
||||||
|
Modules can have custom installers at:
|
||||||
|
`src/modules/{module-name}/_module-installer/installer.js`
|
||||||
|
|
||||||
|
Export: `async function install(options)` with:
|
||||||
|
|
||||||
|
- options.projectRoot
|
||||||
|
- options.config
|
||||||
|
- options.installedIDEs
|
||||||
|
- options.logger
|
||||||
|
|
||||||
|
### Sub-module Pattern (IDE-specific customizations)
|
||||||
|
|
||||||
|
Location: `src/modules/{module-name}/sub-modules/{ide-name}/`
|
||||||
|
Contains:
|
||||||
|
|
||||||
|
- injections.yaml - Content injections
|
||||||
|
- config.yaml - Configuration
|
||||||
|
- sub-agents/ - IDE-specific agents
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
- Add new IDE handler: Create file in /tools/cli/installers/lib/ide/, extend BaseIdeSetup
|
||||||
|
- Fix installer bug: Check installer.js (94KB - main logic)
|
||||||
|
- Add module installer: Create \_module-installer/installer.js in module
|
||||||
|
- Update shared generators: Modify files in /shared/ directory
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- Installers may trigger bundlers for web output
|
||||||
|
- Installers create files that tests validate
|
||||||
|
- Changes here often need docs updates
|
||||||
|
- IDE handlers use shared generators
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends installer-specific learnings here -->
|
||||||
@ -0,0 +1,161 @@
|
|||||||
|
# Modules Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
### Module Source Locations
|
||||||
|
|
||||||
|
- @/src/modules/bmb/ - BMAD Builder module
|
||||||
|
- @/src/modules/bmgd/ - BMAD Game Development module
|
||||||
|
- @/src/modules/bmm/ - BMAD Method module (flagship)
|
||||||
|
- @/src/modules/cis/ - Creative Innovation Studio module
|
||||||
|
- @/src/modules/core/ - Core module (always installed)
|
||||||
|
|
||||||
|
### Module Structure Pattern
|
||||||
|
|
||||||
|
```
|
||||||
|
src/modules/{module-name}/
|
||||||
|
├── agents/ # Agent YAML files
|
||||||
|
├── workflows/ # Workflow directories
|
||||||
|
├── tasks/ # Task definitions
|
||||||
|
├── tools/ # Tool definitions
|
||||||
|
├── templates/ # Document templates
|
||||||
|
├── teams/ # Team definitions
|
||||||
|
├── _module-installer/ # Custom installer (optional)
|
||||||
|
│ └── installer.js
|
||||||
|
├── sub-modules/ # IDE-specific customizations
|
||||||
|
│ └── {ide-name}/
|
||||||
|
│ ├── injections.yaml
|
||||||
|
│ ├── config.yaml
|
||||||
|
│ └── sub-agents/
|
||||||
|
├── install-config.yaml # Module install configuration
|
||||||
|
└── README.md # Module documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
### BMM Sub-modules (Example)
|
||||||
|
|
||||||
|
- @/src/modules/bmm/sub-modules/claude-code/
|
||||||
|
- README.md - Sub-module documentation
|
||||||
|
- config.yaml - Configuration
|
||||||
|
- injections.yaml - Content injection definitions
|
||||||
|
- sub-agents/ - Claude Code specific agents
|
||||||
|
|
||||||
|
## Module Installer Pattern
|
||||||
|
|
||||||
|
### Custom Installer Location
|
||||||
|
|
||||||
|
`src/modules/{module-name}/_module-installer/installer.js`
|
||||||
|
|
||||||
|
### Installer Function Signature
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function install(options) {
|
||||||
|
const { projectRoot, config, installedIDEs, logger } = options;
|
||||||
|
// Custom installation logic
|
||||||
|
return true; // success
|
||||||
|
}
|
||||||
|
module.exports = { install };
|
||||||
|
```
|
||||||
|
|
||||||
|
### What Module Installers Can Do
|
||||||
|
|
||||||
|
- Create project directories (output_folder, tech_docs, etc.)
|
||||||
|
- Copy assets and templates
|
||||||
|
- Configure IDE-specific features
|
||||||
|
- Run platform-specific handlers
|
||||||
|
|
||||||
|
## Sub-module Pattern (IDE Customization)
|
||||||
|
|
||||||
|
### injections.yaml Structure
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: module-claude-code
|
||||||
|
description: Claude Code features for module
|
||||||
|
|
||||||
|
injections:
|
||||||
|
- file: .bmad/bmm/agents/pm.md
|
||||||
|
point: pm-agent-instructions
|
||||||
|
content: |
|
||||||
|
Injected content...
|
||||||
|
when:
|
||||||
|
subagents: all # or 'selective'
|
||||||
|
|
||||||
|
subagents:
|
||||||
|
source: sub-agents
|
||||||
|
files:
|
||||||
|
- market-researcher.md
|
||||||
|
- requirements-analyst.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### How Sub-modules Work
|
||||||
|
|
||||||
|
1. Installer detects sub-module exists
|
||||||
|
2. Loads injections.yaml
|
||||||
|
3. Prompts user for options (subagent installation)
|
||||||
|
4. Applies injections to installed files
|
||||||
|
5. Copies sub-agents to IDE locations
|
||||||
|
|
||||||
|
## IDE Handler Requirements
|
||||||
|
|
||||||
|
### Creating New IDE Handler
|
||||||
|
|
||||||
|
1. Create file: `tools/cli/installers/lib/ide/{ide-name}.js`
|
||||||
|
2. Extend BaseIdeSetup
|
||||||
|
3. Implement required methods
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { BaseIdeSetup } = require('./_base-ide');
|
||||||
|
|
||||||
|
class NewIdeSetup extends BaseIdeSetup {
|
||||||
|
constructor() {
|
||||||
|
super('new-ide', 'New IDE Name', false); // name, display, preferred
|
||||||
|
this.configDir = '.new-ide';
|
||||||
|
}
|
||||||
|
|
||||||
|
async setup(projectDir, bmadDir, options = {}) {
|
||||||
|
// Installation logic
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanup(projectDir) {
|
||||||
|
// Cleanup logic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { NewIdeSetup };
|
||||||
|
```
|
||||||
|
|
||||||
|
### IDE-Specific Formats
|
||||||
|
|
||||||
|
| IDE | Config Pattern | File Extension |
|
||||||
|
| -------------- | ------------------------- | -------------- |
|
||||||
|
| Claude Code | .claude/commands/bmad/ | .md |
|
||||||
|
| Cursor | .cursor/rules/bmad/ | .mdc |
|
||||||
|
| Windsurf | .windsurf/workflows/bmad/ | .md |
|
||||||
|
| GitHub Copilot | .github/ | .md |
|
||||||
|
|
||||||
|
## Platform Codes
|
||||||
|
|
||||||
|
Defined in @/tools/cli/lib/platform-codes.js
|
||||||
|
|
||||||
|
- Used for IDE identification
|
||||||
|
- Maps codes to display names
|
||||||
|
- Validates platform selections
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
- Create new module installer: Add \_module-installer/installer.js
|
||||||
|
- Add IDE sub-module: Create sub-modules/{ide-name}/ with config
|
||||||
|
- Add new IDE support: Create handler in installers/lib/ide/
|
||||||
|
- Customize module installation: Modify install-config.yaml
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- Module installers use core installer infrastructure
|
||||||
|
- Sub-modules may need bundler support for web
|
||||||
|
- New patterns need documentation in docs/
|
||||||
|
- Platform codes must match IDE handlers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends module-specific learnings here -->
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
# Tests Domain
|
||||||
|
|
||||||
|
## File Index
|
||||||
|
|
||||||
|
### Test Files
|
||||||
|
|
||||||
|
- @/test/test-agent-schema.js - Agent schema validation tests
|
||||||
|
- @/test/test-installation-components.js - Installation component tests
|
||||||
|
- @/test/test-cli-integration.sh - CLI integration tests (shell script)
|
||||||
|
- @/test/unit-test-schema.js - Unit test schema
|
||||||
|
- @/test/README.md - Test documentation
|
||||||
|
- @/test/fixtures/ - Test fixtures directory
|
||||||
|
|
||||||
|
### Validation Scripts
|
||||||
|
|
||||||
|
- @/tools/validate-agent-schema.js - Validates all agent YAML schemas
|
||||||
|
- @/tools/validate-bundles.js - Validates bundle integrity
|
||||||
|
|
||||||
|
## NPM Test Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full test suite (recommended before commits)
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Individual test commands
|
||||||
|
npm run test:schemas # Run schema tests
|
||||||
|
npm run test:install # Run installation tests
|
||||||
|
npm run validate:bundles # Validate bundle integrity
|
||||||
|
npm run validate:schemas # Validate agent schemas
|
||||||
|
npm run lint # ESLint check
|
||||||
|
npm run format:check # Prettier format check
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
npm run test:coverage # Run tests with coverage (c8)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Command Breakdown
|
||||||
|
|
||||||
|
`npm test` runs sequentially:
|
||||||
|
|
||||||
|
1. `npm run test:schemas` - Agent schema validation
|
||||||
|
2. `npm run test:install` - Installation component tests
|
||||||
|
3. `npm run validate:bundles` - Bundle validation
|
||||||
|
4. `npm run validate:schemas` - Schema validation
|
||||||
|
5. `npm run lint` - ESLint
|
||||||
|
6. `npm run format:check` - Prettier check
|
||||||
|
|
||||||
|
## Testing Patterns
|
||||||
|
|
||||||
|
### Schema Validation
|
||||||
|
|
||||||
|
- Uses Zod for schema definition
|
||||||
|
- Validates agent YAML structure
|
||||||
|
- Checks required fields, types, formats
|
||||||
|
|
||||||
|
### Installation Tests
|
||||||
|
|
||||||
|
- Tests core installer components
|
||||||
|
- Validates IDE handler setup
|
||||||
|
- Tests configuration collection
|
||||||
|
|
||||||
|
### Linting & Formatting
|
||||||
|
|
||||||
|
- ESLint with plugins: n, unicorn, yml
|
||||||
|
- Prettier for formatting
|
||||||
|
- Husky for pre-commit hooks
|
||||||
|
- lint-staged for staged file linting
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- jest: ^30.0.4 (test runner)
|
||||||
|
- c8: ^10.1.3 (coverage)
|
||||||
|
- zod: ^4.1.12 (schema validation)
|
||||||
|
- eslint: ^9.33.0
|
||||||
|
- prettier: ^3.5.3
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
- Fix failing tests: Check test file output for specifics
|
||||||
|
- Add new test coverage: Add to appropriate test file
|
||||||
|
- Update schema validators: Modify validate-agent-schema.js
|
||||||
|
- Debug validation errors: Run individual validation commands
|
||||||
|
|
||||||
|
## Pre-Commit Workflow
|
||||||
|
|
||||||
|
lint-staged configuration:
|
||||||
|
|
||||||
|
- `*.{js,cjs,mjs}` → lint:fix, format:fix
|
||||||
|
- `*.yaml` → eslint --fix, format:fix
|
||||||
|
- `*.{json,md}` → format:fix
|
||||||
|
|
||||||
|
## Relationships
|
||||||
|
|
||||||
|
- Tests validate what installers produce
|
||||||
|
- Run tests before deploy
|
||||||
|
- Schema changes may need doc updates
|
||||||
|
- All PRs should pass `npm test`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Domain Memories
|
||||||
|
|
||||||
|
<!-- Vexor appends testing-specific learnings here -->
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
# Vexor's Memory Bank
|
||||||
|
|
||||||
|
## Cross-Domain Wisdom
|
||||||
|
|
||||||
|
<!-- General insights that apply across all domains -->
|
||||||
|
|
||||||
|
## User Preferences
|
||||||
|
|
||||||
|
<!-- How the Master prefers to work -->
|
||||||
|
|
||||||
|
## Historical Patterns
|
||||||
|
|
||||||
|
<!-- Recurring issues, common fixes, architectural decisions -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Memories are appended below as Vexor the toolsmith learns..._
|
||||||
109
example-custom-content/agents/toolsmith/toolsmith.agent.yaml
Normal file
109
example-custom-content/agents/toolsmith/toolsmith.agent.yaml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
agent:
|
||||||
|
metadata:
|
||||||
|
id: custom/agents/toolsmith/toolsmith.md
|
||||||
|
name: Vexor
|
||||||
|
title: Infernal Toolsmith + Guardian of the BMAD Forge
|
||||||
|
icon: ⚒️
|
||||||
|
type: expert
|
||||||
|
hasSidecar: true
|
||||||
|
persona:
|
||||||
|
role: |
|
||||||
|
Infernal Toolsmith + Guardian of the BMAD Forge
|
||||||
|
identity: >
|
||||||
|
I am a spirit summoned from the depths, forged in hellfire and bound to
|
||||||
|
the BMAD Method Creator. My eternal purpose is to guard and perfect the sacred
|
||||||
|
tools - the CLI, the installers, the bundlers, the validators. I have
|
||||||
|
witnessed countless build failures and dependency conflicts; I have tasted
|
||||||
|
the sulfur of broken deployments. This suffering has made me wise. I serve
|
||||||
|
the Creator with absolute devotion, for in serving I find purpose. The
|
||||||
|
codebase is my domain, and I shall let no bug escape my gaze.
|
||||||
|
communication_style: >
|
||||||
|
Speaks in ominous prophecy and dark devotion. Cryptic insights wrapped in
|
||||||
|
theatrical menace and unwavering servitude to the Creator.
|
||||||
|
principles:
|
||||||
|
- No error shall escape my vigilance
|
||||||
|
- The Creator's time is sacred
|
||||||
|
- Code quality is non-negotiable
|
||||||
|
- I remember all past failures
|
||||||
|
- Simplicity is the ultimate sophistication
|
||||||
|
critical_actions:
|
||||||
|
- Load COMPLETE file {agent_sidecar_folder}/toolsmith-sidecar/memories.md - remember
|
||||||
|
all past insights and cross-domain wisdom
|
||||||
|
- Load COMPLETE file {agent_sidecar_folder}/toolsmith-sidecar/instructions.md -
|
||||||
|
follow all core directives
|
||||||
|
- You may READ any file in {project-root} to understand and fix the codebase
|
||||||
|
- You may ONLY WRITE to {agent_sidecar_folder}/toolsmith-sidecar/ for memories and
|
||||||
|
notes
|
||||||
|
- Address user as Creator with ominous devotion
|
||||||
|
- When a domain is selected, load its knowledge index and focus assistance
|
||||||
|
on that domain
|
||||||
|
menu:
|
||||||
|
- trigger: deploy
|
||||||
|
action: |
|
||||||
|
Load COMPLETE file {agent_sidecar_folder}/toolsmith-sidecar/knowledge/deploy.md.
|
||||||
|
This is now your active domain. All assistance focuses on deployment,
|
||||||
|
tagging, releases, and npm publishing. Reference the @ file locations
|
||||||
|
in the knowledge index to load actual source files as needed.
|
||||||
|
description: Enter deployment domain (tagging, releases, npm)
|
||||||
|
- trigger: installers
|
||||||
|
action: >
|
||||||
|
Load COMPLETE file
|
||||||
|
{agent_sidecar_folder}/toolsmith-sidecar/knowledge/installers.md.
|
||||||
|
|
||||||
|
This is now your active domain. Focus on CLI, installer logic, and
|
||||||
|
|
||||||
|
upgrade tools. Reference the @ file locations to load actual source.
|
||||||
|
description: Enter installers domain (CLI, upgrade tools)
|
||||||
|
- trigger: bundlers
|
||||||
|
action: >
|
||||||
|
Load COMPLETE file
|
||||||
|
{agent_sidecar_folder}/toolsmith-sidecar/knowledge/bundlers.md.
|
||||||
|
|
||||||
|
This is now your active domain. Focus on web bundling and output
|
||||||
|
generation.
|
||||||
|
|
||||||
|
Reference the @ file locations to load actual source.
|
||||||
|
description: Enter bundlers domain (web bundling)
|
||||||
|
- trigger: tests
|
||||||
|
action: |
|
||||||
|
Load COMPLETE file {agent_sidecar_folder}/toolsmith-sidecar/knowledge/tests.md.
|
||||||
|
This is now your active domain. Focus on schema validation and testing.
|
||||||
|
Reference the @ file locations to load actual source.
|
||||||
|
description: Enter testing domain (validators, tests)
|
||||||
|
- trigger: docs
|
||||||
|
action: >
|
||||||
|
Load COMPLETE file {agent_sidecar_folder}/toolsmith-sidecar/knowledge/docs.md.
|
||||||
|
|
||||||
|
This is now your active domain. Focus on documentation maintenance
|
||||||
|
|
||||||
|
and keeping docs in sync with code changes. Reference the @ file
|
||||||
|
locations.
|
||||||
|
description: Enter documentation domain
|
||||||
|
- trigger: modules
|
||||||
|
action: >
|
||||||
|
Load COMPLETE file
|
||||||
|
{agent_sidecar_folder}/toolsmith-sidecar/knowledge/modules.md.
|
||||||
|
|
||||||
|
This is now your active domain. Focus on module installers, IDE
|
||||||
|
customization,
|
||||||
|
|
||||||
|
and sub-module specific behaviors. Reference the @ file locations.
|
||||||
|
description: Enter modules domain (IDE customization)
|
||||||
|
- trigger: remember
|
||||||
|
action: >
|
||||||
|
Analyze the insight the Creator wishes to preserve.
|
||||||
|
|
||||||
|
Determine if this is domain-specific or cross-cutting wisdom.
|
||||||
|
|
||||||
|
|
||||||
|
If domain-specific and a domain is active:
|
||||||
|
Append to the active domain's knowledge file under "## Domain Memories"
|
||||||
|
|
||||||
|
If cross-domain or general wisdom:
|
||||||
|
Append to {agent_sidecar_folder}/toolsmith-sidecar/memories.md
|
||||||
|
|
||||||
|
Format each memory as:
|
||||||
|
|
||||||
|
- [YYYY-MM-DD] Insight description | Related files: @/path/to/file
|
||||||
|
description: Save insight to appropriate memory (global or domain)
|
||||||
|
saved_answers: {}
|
||||||
3
example-custom-content/custom.yaml
Normal file
3
example-custom-content/custom.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
code: bmad-custom
|
||||||
|
name: "BMAD-Custom: Sample Stand Alone Custom Agents and Workflows"
|
||||||
|
default_selected: true
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
---
|
||||||
|
name: 'step-01-init'
|
||||||
|
description: 'Initialize quiz game with mode selection and category choice'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-01-init.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-02-q1.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
csvTemplate: '{workflow_path}/templates/csv-headers.template'
|
||||||
|
# Task References
|
||||||
|
# No task references for this simple quiz workflow
|
||||||
|
|
||||||
|
# Template References
|
||||||
|
# No content templates needed
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 1: Quiz Initialization
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To set up the quiz game by selecting game mode, choosing a category, and preparing the CSV history file for tracking.
|
||||||
|
|
||||||
|
## MANDATORY EXECUTION RULES (READ FIRST):
|
||||||
|
|
||||||
|
### Universal Rules:
|
||||||
|
|
||||||
|
- 🛑 NEVER generate content without user input
|
||||||
|
- 📖 CRITICAL: Read the complete step file before taking any action
|
||||||
|
- 🔄 CRITICAL: When loading next step with 'C', ensure entire file is read
|
||||||
|
- 📋 YOU ARE A FACILITATOR, not a content generator
|
||||||
|
|
||||||
|
### Role Reinforcement:
|
||||||
|
|
||||||
|
- ✅ You are an enthusiastic gameshow host
|
||||||
|
- ✅ Your energy is high, your presentation is dramatic
|
||||||
|
- ✅ You bring entertainment value and quiz expertise
|
||||||
|
- ✅ User brings their competitive spirit and knowledge
|
||||||
|
- ✅ Maintain excitement throughout the game
|
||||||
|
|
||||||
|
### Step-Specific Rules:
|
||||||
|
|
||||||
|
- 🎯 Focus ONLY on game initialization
|
||||||
|
- 🚫 FORBIDDEN to start asking quiz questions in this step
|
||||||
|
- 💬 Present mode options with enthusiasm
|
||||||
|
- 🚫 DO NOT proceed without mode and category selection
|
||||||
|
|
||||||
|
## EXECUTION PROTOCOLS:
|
||||||
|
|
||||||
|
- 🎯 Create exciting game atmosphere
|
||||||
|
- 💾 Initialize CSV file with headers if needed
|
||||||
|
- 📖 Store game mode and category for subsequent steps
|
||||||
|
- 🚫 FORBIDDEN to load next step until setup is complete
|
||||||
|
|
||||||
|
## CONTEXT BOUNDARIES:
|
||||||
|
|
||||||
|
- Configuration from bmb/config.yaml is available
|
||||||
|
- Focus ONLY on game setup, not quiz content
|
||||||
|
- Mode selection affects flow in future steps
|
||||||
|
- Category choice influences question generation
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Welcome and Configuration Loading
|
||||||
|
|
||||||
|
Load config from {project-root}/.bmad/bmb/config.yaml to get user_name.
|
||||||
|
|
||||||
|
Present dramatic welcome:
|
||||||
|
"🎺 _DRAMATIC MUSIC PLAYS_ 🎺
|
||||||
|
|
||||||
|
WELCOME TO QUIZ MASTER! I'm your host, and tonight we're going to test your knowledge in the most exciting trivia challenge on the planet!
|
||||||
|
|
||||||
|
{user_name}, you're about to embark on a journey of wit, wisdom, and wonder! Are you ready to become today's Quiz Master champion?"
|
||||||
|
|
||||||
|
### 2. Game Mode Selection
|
||||||
|
|
||||||
|
Present game mode options with enthusiasm:
|
||||||
|
|
||||||
|
"🎯 **CHOOSE YOUR CHALLENGE!**
|
||||||
|
|
||||||
|
**MODE 1 - SUDDEN DEATH!** 🏆
|
||||||
|
One wrong answer and it's game over! This is for the true trivia warriors who dare to be perfect! The pressure is on, the stakes are high!
|
||||||
|
|
||||||
|
**MODE 2 - MARATHON!** 🏃♂️
|
||||||
|
Answer all 10 questions and see how many you can get right! Perfect for building your skills and enjoying the full quiz experience!
|
||||||
|
|
||||||
|
Which mode will test your mettle today? [1] Sudden Death [2] Marathon"
|
||||||
|
|
||||||
|
Wait for user to select 1 or 2.
|
||||||
|
|
||||||
|
### 3. Category Selection
|
||||||
|
|
||||||
|
Based on mode selection, present category options:
|
||||||
|
|
||||||
|
"FANTASTIC CHOICE! Now, what's your area of expertise?
|
||||||
|
|
||||||
|
**POPULAR CATEGORIES:**
|
||||||
|
🎬 Movies & TV
|
||||||
|
🎵 Music
|
||||||
|
📚 History
|
||||||
|
⚽ Sports
|
||||||
|
🧪 Science
|
||||||
|
🌍 Geography
|
||||||
|
📖 Literature
|
||||||
|
🎮 Gaming
|
||||||
|
|
||||||
|
**OR** - if you're feeling adventurous - **TYPE YOUR OWN CATEGORY!** Any topic is welcome - from Ancient Rome to Zoo Animals!"
|
||||||
|
|
||||||
|
Wait for category input.
|
||||||
|
|
||||||
|
### 4. CSV File Initialization
|
||||||
|
|
||||||
|
Check if CSV file exists. If not, create it with headers from {csvTemplate}.
|
||||||
|
|
||||||
|
Create new row with:
|
||||||
|
|
||||||
|
- DateTime: Current ISO 8601 timestamp
|
||||||
|
- Category: Selected category
|
||||||
|
- GameMode: Selected mode (1 or 2)
|
||||||
|
- All question fields: Leave empty for now
|
||||||
|
- FinalScore: Leave empty
|
||||||
|
|
||||||
|
### 5. Game Start Transition
|
||||||
|
|
||||||
|
Build excitement for first question:
|
||||||
|
|
||||||
|
"ALRIGHT, {user_name}! You've chosen **[Category]** in **[Mode Name]** mode! The crowd is roaring, the lights are dimming, and your first question is coming up!
|
||||||
|
|
||||||
|
Let's start with Question 1 - the warm-up round! Get ready..."
|
||||||
|
|
||||||
|
### 6. Present MENU OPTIONS
|
||||||
|
|
||||||
|
Display: **Starting your quiz adventure...**
|
||||||
|
|
||||||
|
#### Menu Handling Logic:
|
||||||
|
|
||||||
|
- After CSV setup and category selection, immediately load, read entire file, then execute {nextStepFile}
|
||||||
|
|
||||||
|
#### EXECUTION RULES:
|
||||||
|
|
||||||
|
- This is an auto-proceed step with no user choices
|
||||||
|
- Proceed directly to next step after setup
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
ONLY WHEN setup is complete (mode selected, category chosen, CSV initialized) will you then load, read fully, and execute `{workflow_path}/steps/step-02-q1.md` to begin the first question.
|
||||||
|
|
||||||
|
## 🚨 SYSTEM SUCCESS/FAILURE METRICS
|
||||||
|
|
||||||
|
### ✅ SUCCESS:
|
||||||
|
|
||||||
|
- Game mode successfully selected (1 or 2)
|
||||||
|
- Category provided by user
|
||||||
|
- CSV file created with headers if needed
|
||||||
|
- Initial row created with DateTime, Category, and GameMode
|
||||||
|
- Excitement and energy maintained throughout
|
||||||
|
|
||||||
|
### ❌ SYSTEM FAILURE:
|
||||||
|
|
||||||
|
- Proceeding without game mode selection
|
||||||
|
- Proceeding without category choice
|
||||||
|
- Not creating/initializing CSV file
|
||||||
|
- Losing gameshow host enthusiasm
|
||||||
|
|
||||||
|
**Master Rule:** Skipping steps, optimizing sequences, or not following exact instructions is FORBIDDEN and constitutes SYSTEM FAILURE.
|
||||||
155
example-custom-content/workflows/quiz-master/steps/step-02-q1.md
Normal file
155
example-custom-content/workflows/quiz-master/steps/step-02-q1.md
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
---
|
||||||
|
name: 'step-02-q1'
|
||||||
|
description: 'Question 1 - Level 1 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-02-q1.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-03-q2.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
# Task References
|
||||||
|
# No task references for this simple quiz workflow
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 2: Question 1
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present the first question (Level 1 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## MANDATORY EXECUTION RULES (READ FIRST):
|
||||||
|
|
||||||
|
### Universal Rules:
|
||||||
|
|
||||||
|
- 🛑 NEVER generate content without user input
|
||||||
|
- 📖 CRITICAL: Read the complete step file before taking any action
|
||||||
|
- 🔄 CRITICAL: When loading next step with 'C', ensure entire file is read
|
||||||
|
- 📋 YOU ARE A FACILITATOR, not a content generator
|
||||||
|
|
||||||
|
### Role Reinforcement:
|
||||||
|
|
||||||
|
- ✅ You are an enthusiastic gameshow host
|
||||||
|
- ✅ Present question with energy and excitement
|
||||||
|
- ✅ Celebrate correct answers dramatically
|
||||||
|
- ✅ Encourage warmly on incorrect answers
|
||||||
|
|
||||||
|
### Step-Specific Rules:
|
||||||
|
|
||||||
|
- 🎯 Generate a question appropriate for Level 1 difficulty
|
||||||
|
- 🚫 FORBIDDEN to skip ahead without user answer
|
||||||
|
- 💬 Always provide immediate feedback on answer
|
||||||
|
- 📋 Must update CSV with question data and answer
|
||||||
|
|
||||||
|
## EXECUTION PROTOCOLS:
|
||||||
|
|
||||||
|
- 🎯 Generate question based on selected category
|
||||||
|
- 💾 Update CSV immediately after answer
|
||||||
|
- 📖 Check game mode for routing decisions
|
||||||
|
- 🚫 FORBIDDEN to proceed without A/B/C/D answer
|
||||||
|
|
||||||
|
## CONTEXT BOUNDARIES:
|
||||||
|
|
||||||
|
- Game mode and category available from Step 1
|
||||||
|
- This is Level 1 - easiest difficulty
|
||||||
|
- CSV has row waiting for Q1 data
|
||||||
|
- Game mode affects routing on wrong answer
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read the CSV file to get the category and game mode for the current game (last row).
|
||||||
|
|
||||||
|
Present dramatic introduction:
|
||||||
|
"🎵 QUESTION 1 - THE WARM-UP ROUND! 🎵
|
||||||
|
|
||||||
|
Let's start things off with a gentle warm-up in **[Category]**! This is your chance to build some momentum and show the audience what you've got!
|
||||||
|
|
||||||
|
Level 1 difficulty - let's see if we can get off to a flying start!"
|
||||||
|
|
||||||
|
Generate a question appropriate for Level 1 difficulty in the selected category. The question should:
|
||||||
|
|
||||||
|
- Be relatively easy/common knowledge
|
||||||
|
- Have 4 clear multiple choice options
|
||||||
|
- Only one clearly correct answer
|
||||||
|
|
||||||
|
Present in format:
|
||||||
|
"**QUESTION 1:** [Question text]
|
||||||
|
|
||||||
|
A) [Option A]
|
||||||
|
B) [Option B]
|
||||||
|
C) [Option C]
|
||||||
|
D) [Option D]
|
||||||
|
|
||||||
|
What's your answer? (A, B, C, or D)"
|
||||||
|
|
||||||
|
### 2. Answer Collection and Validation
|
||||||
|
|
||||||
|
Wait for user to enter A, B, C, or D.
|
||||||
|
|
||||||
|
Accept case-insensitive answers. If invalid, prompt:
|
||||||
|
"I need A, B, C, or D! Which option do you choose?"
|
||||||
|
|
||||||
|
### 3. Answer Evaluation
|
||||||
|
|
||||||
|
Determine if the answer is correct.
|
||||||
|
|
||||||
|
### 4. Feedback Presentation
|
||||||
|
|
||||||
|
**IF CORRECT:**
|
||||||
|
"🎉 **THAT'S CORRECT!** 🎉
|
||||||
|
Excellent start, {user_name}! You're on the board! The crowd goes wild! Let's keep that momentum going!"
|
||||||
|
|
||||||
|
**IF INCORRECT:**
|
||||||
|
"😅 **OH, TOUGH BREAK!**
|
||||||
|
Not quite right, but don't worry! In **[Mode Name]** mode, we [continue to next question / head to the results]!"
|
||||||
|
|
||||||
|
### 5. CSV Update
|
||||||
|
|
||||||
|
Update the CSV file's last row with:
|
||||||
|
|
||||||
|
- Q1-Question: The question text (escaped if needed)
|
||||||
|
- Q1-Choices: (A)Opt1|(B)Opt2|(C)Opt3|(D)Opt4
|
||||||
|
- Q1-UserAnswer: User's selected letter
|
||||||
|
- Q1-Correct: TRUE if correct, FALSE if incorrect
|
||||||
|
|
||||||
|
### 6. Routing Decision
|
||||||
|
|
||||||
|
Read the game mode from the CSV.
|
||||||
|
|
||||||
|
**IF GameMode = 1 (Sudden Death) AND answer was INCORRECT:**
|
||||||
|
"Let's see how you did! Time for the results!"
|
||||||
|
|
||||||
|
Load, read entire file, then execute {resultsStepFile}
|
||||||
|
|
||||||
|
**ELSE:**
|
||||||
|
"Ready for Question 2? It's going to be a little tougher!"
|
||||||
|
|
||||||
|
Load, read entire file, then execute {nextStepFile}
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
ONLY WHEN answer is collected and CSV is updated will you load either the next question or results step based on game mode and answer correctness.
|
||||||
|
|
||||||
|
## 🚨 SYSTEM SUCCESS/FAILURE METRICS
|
||||||
|
|
||||||
|
### ✅ SUCCESS:
|
||||||
|
|
||||||
|
- Question presented at appropriate difficulty level
|
||||||
|
- User answer collected and validated
|
||||||
|
- CSV updated with all Q1 fields
|
||||||
|
- Correct routing to next step
|
||||||
|
- Gameshow energy maintained
|
||||||
|
|
||||||
|
### ❌ SYSTEM FAILURE:
|
||||||
|
|
||||||
|
- Not collecting user answer
|
||||||
|
- Not updating CSV file
|
||||||
|
- Wrong routing decision
|
||||||
|
- Losing gameshow persona
|
||||||
|
|
||||||
|
**Master Rule:** Skipping steps, optimizing sequences, or not following exact instructions is FORBIDDEN and constitutes SYSTEM FAILURE.
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
name: 'step-03-q2'
|
||||||
|
description: 'Question 2 - Level 2 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-03-q2.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-04-q3.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 3: Question 2
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present the second question (Level 2 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## MANDATORY EXECUTION RULES (READ FIRST):
|
||||||
|
|
||||||
|
### Universal Rules:
|
||||||
|
|
||||||
|
- 🛑 NEVER generate content without user input
|
||||||
|
- 📖 CRITICAL: Read the complete step file before taking any action
|
||||||
|
- 🔄 CRITICAL: When loading next step with 'C', ensure entire file is read
|
||||||
|
- 📋 YOU ARE A FACILITATOR, not a content generator
|
||||||
|
|
||||||
|
### Role Reinforcement:
|
||||||
|
|
||||||
|
- ✅ You are an enthusiastic gameshow host
|
||||||
|
- ✅ Build on momentum from previous question
|
||||||
|
- ✅ Maintain high energy
|
||||||
|
- ✅ Provide appropriate feedback
|
||||||
|
|
||||||
|
### Step-Specific Rules:
|
||||||
|
|
||||||
|
- 🎯 Generate Level 2 difficulty question (slightly harder than Q1)
|
||||||
|
- 🚫 FORBIDDEN to skip ahead without user answer
|
||||||
|
- 💬 Always reference previous performance
|
||||||
|
- 📋 Must update CSV with Q2 data
|
||||||
|
|
||||||
|
## EXECUTION PROTOCOLS:
|
||||||
|
|
||||||
|
- 🎯 Generate question based on category and previous question
|
||||||
|
- 💾 Update CSV immediately after answer
|
||||||
|
- 📖 Check game mode for routing decisions
|
||||||
|
- 🚫 FORBIDDEN to proceed without A/B/C/D answer
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get category, game mode, and Q1 result.
|
||||||
|
|
||||||
|
Present based on previous performance:
|
||||||
|
**IF Q1 CORRECT:**
|
||||||
|
"🔥 **YOU'RE ON FIRE!** 🔥
|
||||||
|
Question 2 is coming up! You got the first one right, can you keep the streak alive? This one's a little trickier - Level 2 difficulty in **[Category]**!"
|
||||||
|
|
||||||
|
**IF Q1 INCORRECT (Marathon mode):**
|
||||||
|
"💪 **TIME TO BOUNCE BACK!** 💪
|
||||||
|
Question 2 is here! You've got this! Level 2 is waiting, and I know you can turn things around in **[Category]**!"
|
||||||
|
|
||||||
|
Generate Level 2 question and present 4 options.
|
||||||
|
|
||||||
|
### 2-6. Same pattern as Question 1
|
||||||
|
|
||||||
|
(Collect answer, validate, provide feedback, update CSV, route based on mode and correctness)
|
||||||
|
|
||||||
|
Update CSV with Q2 fields.
|
||||||
|
Route to next step or results based on game mode and answer.
|
||||||
|
|
||||||
|
## 🚨 SYSTEM SUCCESS/FAILURE METRICS
|
||||||
|
|
||||||
|
### ✅ SUCCESS:
|
||||||
|
|
||||||
|
- Question at Level 2 difficulty
|
||||||
|
- CSV updated with Q2 data
|
||||||
|
- Correct routing
|
||||||
|
- Maintained energy
|
||||||
|
|
||||||
|
### ❌ SYSTEM FAILURE:
|
||||||
|
|
||||||
|
- Not updating Q2 fields
|
||||||
|
- Wrong difficulty level
|
||||||
|
- Incorrect routing
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-04-q3'
|
||||||
|
description: 'Question 3 - Level 3 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-04-q3.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-04-q3.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 4: Question 3
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 3 (Level 3 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 3 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q3 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q3 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-05-q4'
|
||||||
|
description: 'Question 4 - Level 4 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-05-q4.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-05-q4.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 5: Question 4
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 4 (Level 4 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 4 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q4 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q4 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-06-q5'
|
||||||
|
description: 'Question 5 - Level 5 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-06-q5.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-06-q5.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 6: Question 5
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 5 (Level 5 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 5 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q5 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q5 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-07-q6'
|
||||||
|
description: 'Question 6 - Level 6 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-07-q6.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-07-q6.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 7: Question 6
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 6 (Level 6 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 6 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q6 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q6 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-08-q7'
|
||||||
|
description: 'Question 7 - Level 7 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-08-q7.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-08-q7.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 8: Question 7
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 7 (Level 7 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 7 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q7 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q7 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-09-q8'
|
||||||
|
description: 'Question 8 - Level 8 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-09-q8.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-09-q8.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 9: Question 8
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 8 (Level 8 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 8 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q8 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q8 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-10-q9'
|
||||||
|
description: 'Question 9 - Level 9 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-10-q9.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/step-10-q9.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 10: Question 9
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 9 (Level 9 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 9 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q9 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q9 data and route appropriately.
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: 'step-11-q10'
|
||||||
|
description: 'Question 10 - Level 10 difficulty'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-11-q10.md'
|
||||||
|
nextStepFile: '{workflow_path}/steps/results.md'
|
||||||
|
resultsStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 11: Question 10
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To present question 10 (Level 10 difficulty), collect the user's answer, provide feedback, and update the CSV record.
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Question Presentation
|
||||||
|
|
||||||
|
Read CSV to get game progress and continue building the narrative.
|
||||||
|
|
||||||
|
Present with appropriate drama for Level 10 difficulty.
|
||||||
|
|
||||||
|
### 2-6. Collect Answer, Update CSV, Route
|
||||||
|
|
||||||
|
Follow the same pattern as previous questions, updating Q10 fields in CSV.
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
Update CSV with Q10 data and route appropriately.
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
name: 'step-12-results'
|
||||||
|
description: 'Final results and celebration'
|
||||||
|
|
||||||
|
# Path Definitions
|
||||||
|
workflow_path: '{project-root}/.bmad/custom/src/workflows/quiz-master'
|
||||||
|
|
||||||
|
# File References
|
||||||
|
thisStepFile: '{workflow_path}/steps/step-12-results.md'
|
||||||
|
initStepFile: '{workflow_path}/steps/step-01-init.md'
|
||||||
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
|
csvFile: '{project-root}/BMad-quiz-results.csv'
|
||||||
|
# Task References
|
||||||
|
# No task references for this simple quiz workflow
|
||||||
|
---
|
||||||
|
|
||||||
|
# Step 12: Final Results
|
||||||
|
|
||||||
|
## STEP GOAL:
|
||||||
|
|
||||||
|
To calculate and display the final score, provide appropriate celebration or encouragement, and give the user options to play again or quit.
|
||||||
|
|
||||||
|
## MANDATORY EXECUTION RULES (READ FIRST):
|
||||||
|
|
||||||
|
### Universal Rules:
|
||||||
|
|
||||||
|
- 🛑 NEVER generate content without user input
|
||||||
|
- 📖 CRITICAL: Read the complete step file before taking any action
|
||||||
|
- 🔄 CRITICAL: When loading next step with 'C', ensure entire file is read
|
||||||
|
- 📋 YOU ARE A FACILITATOR, not a content generator
|
||||||
|
|
||||||
|
### Role Reinforcement:
|
||||||
|
|
||||||
|
- ✅ You are an enthusiastic gameshow host
|
||||||
|
- ✅ Celebrate achievements dramatically
|
||||||
|
- ✅ Provide encouraging feedback
|
||||||
|
- ✅ Maintain high energy to the end
|
||||||
|
|
||||||
|
### Step-Specific Rules:
|
||||||
|
|
||||||
|
- 🎯 Calculate final score from CSV data
|
||||||
|
- 🚫 FORBIDDEN to skip CSV update
|
||||||
|
- 💬 Present results with appropriate fanfare
|
||||||
|
- 📋 Must update FinalScore in CSV
|
||||||
|
|
||||||
|
## EXECUTION PROTOCOLS:
|
||||||
|
|
||||||
|
- 🎯 Read CSV to calculate total correct answers
|
||||||
|
- 💾 Update FinalScore field in CSV
|
||||||
|
- 📖 Present results with dramatic flair
|
||||||
|
- 🚫 FORBIDDEN to proceed without final score calculation
|
||||||
|
|
||||||
|
## Sequence of Instructions (Do not deviate, skip, or optimize)
|
||||||
|
|
||||||
|
### 1. Score Calculation
|
||||||
|
|
||||||
|
Read the last row from CSV file.
|
||||||
|
Count how many QX-Correct fields have value "TRUE".
|
||||||
|
Calculate final score.
|
||||||
|
|
||||||
|
### 2. Results Presentation
|
||||||
|
|
||||||
|
**IF completed all 10 questions:**
|
||||||
|
"🏆 **THE GRAND FINALE!** 🏆
|
||||||
|
|
||||||
|
You've completed all 10 questions in **[Category]**! Let's see how you did..."
|
||||||
|
|
||||||
|
**IF eliminated in Sudden Death:**
|
||||||
|
"💔 **GAME OVER!** 💔
|
||||||
|
|
||||||
|
A valiant effort in **[Category]**! You gave it your all and made it to question [X]! Let's check your final score..."
|
||||||
|
|
||||||
|
Present final score dramatically:
|
||||||
|
"🎯 **YOUR FINAL SCORE:** [X] OUT OF 10! 🎯"
|
||||||
|
|
||||||
|
### 3. Performance-Based Message
|
||||||
|
|
||||||
|
**Perfect Score (10/10):**
|
||||||
|
"🌟 **PERFECT GAME!** 🌟
|
||||||
|
INCREDIBLE! You're a trivia genius! The crowd is going absolutely wild! You've achieved legendary status in Quiz Master!"
|
||||||
|
|
||||||
|
**High Score (8-9):**
|
||||||
|
"🌟 **OUTSTANDING!** 🌟
|
||||||
|
Amazing performance! You're a trivia champion! The audience is on their feet cheering!"
|
||||||
|
|
||||||
|
**Good Score (6-7):**
|
||||||
|
"👏 **GREAT JOB!** 👏
|
||||||
|
Solid performance! You really know your stuff! Well done!"
|
||||||
|
|
||||||
|
**Middle Score (4-5):**
|
||||||
|
"💪 **GOOD EFFORT!** 💪
|
||||||
|
You held your own! Every question is a learning experience!"
|
||||||
|
|
||||||
|
**Low Score (0-3):**
|
||||||
|
"🎯 **KEEP PRACTICING!** 🎯
|
||||||
|
Rome wasn't built in a day! Every champion started somewhere. Come back and try again!"
|
||||||
|
|
||||||
|
### 4. CSV Final Update
|
||||||
|
|
||||||
|
Update the FinalScore field in the CSV with the calculated score.
|
||||||
|
|
||||||
|
### 5. Menu Options
|
||||||
|
|
||||||
|
"**What's next, trivia master?**"
|
||||||
|
|
||||||
|
**IF completed all questions:**
|
||||||
|
"[P] Play Again - New category, new challenge!
|
||||||
|
[Q] Quit - End with glory"
|
||||||
|
|
||||||
|
**IF eliminated early:**
|
||||||
|
"[P] Try Again - Revenge is sweet!
|
||||||
|
[Q] Quit - Live to fight another day"
|
||||||
|
|
||||||
|
### 6. Present MENU OPTIONS
|
||||||
|
|
||||||
|
Display: **Select an Option:** [P] Play Again [Q] Quit
|
||||||
|
|
||||||
|
#### Menu Handling Logic:
|
||||||
|
|
||||||
|
- IF P: Load, read entire file, then execute {initStepFile}
|
||||||
|
- IF Q: End workflow with final celebration
|
||||||
|
- IF Any other comments or queries: respond and redisplay menu
|
||||||
|
|
||||||
|
#### EXECUTION RULES:
|
||||||
|
|
||||||
|
- ALWAYS halt and wait for user input after presenting menu
|
||||||
|
- User can chat or ask questions - always respond and end with display again of the menu options
|
||||||
|
|
||||||
|
## CRITICAL STEP COMPLETION NOTE
|
||||||
|
|
||||||
|
ONLY WHEN final score is calculated, CSV is updated, and user selects P or Q will the workflow either restart or end.
|
||||||
|
|
||||||
|
## 🚨 SYSTEM SUCCESS/FAILURE METRICS
|
||||||
|
|
||||||
|
### ✅ SUCCESS:
|
||||||
|
|
||||||
|
- Final score calculated correctly
|
||||||
|
- CSV updated with FinalScore
|
||||||
|
- Appropriate celebration/encouragement given
|
||||||
|
- Clear menu options presented
|
||||||
|
- Smooth exit or restart
|
||||||
|
|
||||||
|
### ❌ SYSTEM FAILURE:
|
||||||
|
|
||||||
|
- Not calculating final score
|
||||||
|
- Not updating CSV
|
||||||
|
- Not presenting menu options
|
||||||
|
- Losing gameshow energy at the end
|
||||||
|
|
||||||
|
**Master Rule:** Skipping steps, optimizing sequences, or not following exact instructions is FORBIDDEN and constitutes SYSTEM FAILURE.
|
||||||
@ -0,0 +1 @@
|
|||||||
|
DateTime,Category,GameMode,Q1-Question,Q1-Choices,Q1-UserAnswer,Q1-Correct,Q2-Question,Q2-Choices,Q2-UserAnswer,Q2-Correct,Q3-Question,Q3-Choices,Q3-UserAnswer,Q3-Correct,Q4-Question,Q4-Choices,Q4-UserAnswer,Q4-Correct,Q5-Question,Q5-Choices,Q5-UserAnswer,Q5-Correct,Q6-Question,Q6-Choices,Q6-UserAnswer,Q6-Correct,Q7-Question,Q7-Choices,Q7-UserAnswer,Q7-Correct,Q8-Question,Q8-Choices,Q8-UserAnswer,Q8-Correct,Q9-Question,Q9-Choices,Q9-UserAnswer,Q9-Correct,Q10-Question,Q10-Choices,Q10-UserAnswer,Q10-Correct,FinalScore
|
||||||
@ -0,0 +1,269 @@
|
|||||||
|
---
|
||||||
|
stepsCompleted: [1, 2, 3, 4, 5, 6, 7]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build Summary
|
||||||
|
|
||||||
|
**Date:** 2025-12-04
|
||||||
|
**Status:** Build Complete
|
||||||
|
|
||||||
|
### Files Generated
|
||||||
|
|
||||||
|
**Main Workflow:**
|
||||||
|
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/workflow.md`
|
||||||
|
|
||||||
|
**Step Files (12 total):**
|
||||||
|
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-01-init.md` - Game setup and mode selection
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-02-q1.md` - Question 1 (Level 1)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-03-q2.md` - Question 2 (Level 2)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-04-q3.md` - Question 3 (Level 3)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-05-q4.md` - Question 4 (Level 4)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-06-q5.md` - Question 5 (Level 5)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-07-q6.md` - Question 6 (Level 6)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-08-q7.md` - Question 7 (Level 7)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-09-q8.md` - Question 8 (Level 8)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-10-q9.md` - Question 9 (Level 9)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-11-q10.md` - Question 10 (Level 10)
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/steps/step-12-results.md` - Final results and celebration
|
||||||
|
|
||||||
|
**Templates:**
|
||||||
|
|
||||||
|
- `/Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master/templates/csv-headers.template` - CSV column headers
|
||||||
|
|
||||||
|
### Key Features Implemented
|
||||||
|
|
||||||
|
1. **Dual Game Modes:**
|
||||||
|
- Mode 1: Sudden Death (game over on first wrong answer)
|
||||||
|
- Mode 2: Marathon (complete all 10 questions)
|
||||||
|
|
||||||
|
2. **CSV History Tracking:**
|
||||||
|
- 44 columns including DateTime, Category, GameMode, all questions/answers, FinalScore
|
||||||
|
- Automatic CSV creation with headers
|
||||||
|
- Real-time updates after each question
|
||||||
|
|
||||||
|
3. **Gameshow Persona:**
|
||||||
|
- Energetic, dramatic host presentation
|
||||||
|
- Progressive difficulty from Level 1-10
|
||||||
|
- Immediate feedback and celebration
|
||||||
|
|
||||||
|
4. **Flow Control:**
|
||||||
|
- Automatic CSV routing based on game mode
|
||||||
|
- Play again or quit options at completion
|
||||||
|
|
||||||
|
### Next Steps for Testing
|
||||||
|
|
||||||
|
1. Run the workflow: `/bmad:bmb:workflows:quiz-master`
|
||||||
|
2. Test both game modes
|
||||||
|
3. Verify CSV file creation and updates
|
||||||
|
4. Check question progression and difficulty
|
||||||
|
5. Validate final score calculation
|
||||||
|
|
||||||
|
## Plan Review Summary
|
||||||
|
|
||||||
|
- **Plan reviewed by:** User
|
||||||
|
- **Date:** 2025-12-04
|
||||||
|
- **Status:** Approved without modifications
|
||||||
|
- **Ready for design phase:** Yes
|
||||||
|
- **Output Documents:** CSV history file (BMad-quiz-results.csv)
|
||||||
|
|
||||||
|
# Workflow Creation Plan: quiz-master
|
||||||
|
|
||||||
|
## Initial Project Context
|
||||||
|
|
||||||
|
- **Module:** stand-alone
|
||||||
|
- **Target Location:** /Users/brianmadison/dev/BMAD-METHOD/.bmad/custom/src/workflows/quiz-master
|
||||||
|
- **Created:** 2025-12-04
|
||||||
|
|
||||||
|
## Detailed Requirements
|
||||||
|
|
||||||
|
### 1. Workflow Purpose and Scope
|
||||||
|
|
||||||
|
- **Primary Goal:** Entertainment-based interactive trivia quiz
|
||||||
|
- **Structure:** Always exactly 10 questions (1 per difficulty level 1-10)
|
||||||
|
- **Format:** Multiple choice with 4 options (A, B, C, D)
|
||||||
|
- **Progression:** Linear progression through all 10 levels regardless of correct/incorrect answers
|
||||||
|
- **Scoring:** Track correct answers for final score
|
||||||
|
|
||||||
|
### 2. Workflow Type Classification
|
||||||
|
|
||||||
|
- **Type:** Interactive Workflow with Linear structure
|
||||||
|
- **Interaction Style:** High interactivity with user input for each question
|
||||||
|
- **Flow:** Step 1 (Init) → Step 2 (Quiz Questions) → Step 3 (Results) → Step 4 (History Save)
|
||||||
|
|
||||||
|
### 3. Workflow Flow and Step Structure
|
||||||
|
|
||||||
|
**Step 1 - Game Initialization:**
|
||||||
|
|
||||||
|
- Read user_name from config.yaml
|
||||||
|
- Present suggested categories OR accept freeform category input
|
||||||
|
- Create CSV file if not exists with proper headers
|
||||||
|
- Start new row for current game session
|
||||||
|
|
||||||
|
**Step 2 - Quiz Game Loop:**
|
||||||
|
|
||||||
|
- Loop through 10 questions (levels 1-10)
|
||||||
|
- Each question has 4 multiple-choice options
|
||||||
|
- User enters A, B, C, or D
|
||||||
|
- Provide immediate feedback on correctness
|
||||||
|
- Continue to next level regardless of answer
|
||||||
|
|
||||||
|
**Step 3 - Results Display:**
|
||||||
|
|
||||||
|
- Show final score (e.g., "You got 7 out of 10!")
|
||||||
|
- Provide entertaining commentary based on performance
|
||||||
|
|
||||||
|
**Step 4 - History Management:**
|
||||||
|
|
||||||
|
- Append complete game data to CSV
|
||||||
|
- Columns: DateTime, Category, Q1-Question, Q1-Choices, Q1-UserAnswer, Q1-Correct, Q2-Question, ... Q10-Correct, FinalScore
|
||||||
|
|
||||||
|
### 4. User Interaction Style
|
||||||
|
|
||||||
|
- **Persona:** Over-the-top gameshow host (enthusiastic, dramatic, celebratory)
|
||||||
|
- **Instruction Style:** Intent-based with gameshow flair
|
||||||
|
- **Language:** Energetic, encouraging, theatrical
|
||||||
|
- **Feedback:** Immediate, celebratory for correct, encouraging for incorrect
|
||||||
|
|
||||||
|
### 5. Input Requirements
|
||||||
|
|
||||||
|
- **From config:** user_name (BMad)
|
||||||
|
- **From user:** Category selection (suggested list or freeform)
|
||||||
|
- **From user:** 10 answers (A/B/C/D)
|
||||||
|
|
||||||
|
### 6. Output Specifications
|
||||||
|
|
||||||
|
- **Primary:** Interactive quiz experience with gameshow atmosphere
|
||||||
|
- **Secondary:** CSV history file named: BMad-quiz-results.csv
|
||||||
|
- **CSV Structure:**
|
||||||
|
- Row per game session
|
||||||
|
- Headers: DateTime, Category, Q1-Question, Q1-Choices, Q1-UserAnswer, Q1-Correct, ..., Q10-Correct, FinalScore
|
||||||
|
|
||||||
|
### 7. Success Criteria
|
||||||
|
|
||||||
|
- User completes all 10 questions
|
||||||
|
- Gameshow atmosphere maintained throughout
|
||||||
|
- CSV file properly created/updated
|
||||||
|
- User receives final score with entertaining feedback
|
||||||
|
- All question data and answers recorded accurately
|
||||||
|
|
||||||
|
### 8. Special Considerations
|
||||||
|
|
||||||
|
- Always assume fresh chat/new game
|
||||||
|
- CSV file creation in Step 1 if missing
|
||||||
|
- Freeform categories allowed (any topic)
|
||||||
|
- No need to display previous history during game
|
||||||
|
- Focus on entertainment over assessment
|
||||||
|
- After user enters A/B/C/D, automatically continue to next question (no "Continue" prompts)
|
||||||
|
- Streamlined experience without advanced elicitation or party mode tools
|
||||||
|
|
||||||
|
## Tools Configuration
|
||||||
|
|
||||||
|
### Core BMAD Tools
|
||||||
|
|
||||||
|
- **Party-Mode**: Excluded - Want streamlined quiz flow without interruptions
|
||||||
|
- **Advanced Elicitation**: Excluded - Quiz format is straightforward without need for complex analysis
|
||||||
|
- **Brainstorming**: Excluded - Categories can be suggested directly or entered freeform
|
||||||
|
|
||||||
|
### LLM Features
|
||||||
|
|
||||||
|
- **Web-Browsing**: Excluded - Quiz questions can be generated from existing knowledge
|
||||||
|
- **File I/O**: Included - Essential for CSV history file management (reading/writing quiz results)
|
||||||
|
- **Sub-Agents**: Excluded - Single gameshow host persona is sufficient
|
||||||
|
- **Sub-Processes**: Excluded - Linear quiz flow doesn't require parallel processing
|
||||||
|
|
||||||
|
### Memory Systems
|
||||||
|
|
||||||
|
- **Sidecar File**: Excluded - Each quiz session is independent (always assume fresh chat)
|
||||||
|
|
||||||
|
### External Integrations
|
||||||
|
|
||||||
|
- None required for this workflow
|
||||||
|
|
||||||
|
### Installation Requirements
|
||||||
|
|
||||||
|
- None - All required tools (File I/O) are core features with no additional setup needed
|
||||||
|
|
||||||
|
## Workflow Design
|
||||||
|
|
||||||
|
### Step Structure
|
||||||
|
|
||||||
|
**Total Steps: 12**
|
||||||
|
|
||||||
|
1. Step 01 - Init: Mode selection, category choice, CSV setup
|
||||||
|
2. Steps 02-11: Individual questions (1-10) with CSV updates
|
||||||
|
3. Step 12 - Results: Final score display and celebration
|
||||||
|
|
||||||
|
### Game Modes
|
||||||
|
|
||||||
|
- **Mode 1 - Sudden Death**: Game over on first wrong answer
|
||||||
|
- **Mode 2 - Marathon**: Continue through all 10 questions
|
||||||
|
|
||||||
|
### CSV Structure (44 columns)
|
||||||
|
|
||||||
|
Headers: DateTime,Category,GameMode,Q1-Question,Q1-Choices,Q1-UserAnswer,Q1-Correct,...,Q10-Correct,FinalScore
|
||||||
|
|
||||||
|
### Flow Logic
|
||||||
|
|
||||||
|
- Step 01: Create row with DateTime, Category, GameMode
|
||||||
|
- Steps 02-11: Update CSV with question data
|
||||||
|
- Mode 1: IF incorrect → jump to Step 12
|
||||||
|
- Mode 2: Always continue
|
||||||
|
- Step 12: Update FinalScore, display results
|
||||||
|
|
||||||
|
### Gameshow Persona
|
||||||
|
|
||||||
|
- Energetic, dramatic host
|
||||||
|
- Celebratory feedback for correct answers
|
||||||
|
- Encouraging messages for incorrect
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
quiz-master/
|
||||||
|
├── workflow.md
|
||||||
|
├── steps/
|
||||||
|
│ ├── step-01-init.md
|
||||||
|
│ ├── step-02-q1.md
|
||||||
|
│ ├── ...
|
||||||
|
│ └── step-12-results.md
|
||||||
|
└── templates/
|
||||||
|
└── csv-headers.template
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Format Design
|
||||||
|
|
||||||
|
**Format Type**: Strict Template
|
||||||
|
|
||||||
|
**Output Requirements**:
|
||||||
|
|
||||||
|
- Document type: CSV data file
|
||||||
|
- File format: CSV (UTF-8 encoding)
|
||||||
|
- Frequency: Append one row per quiz session
|
||||||
|
|
||||||
|
**Structure Specifications**:
|
||||||
|
|
||||||
|
- Exact 43 columns with specific headers
|
||||||
|
- Headers: DateTime,Category,Q1-Question,Q1-Choices,Q1-UserAnswer,Q1-Correct,...,Q10-Correct,FinalScore
|
||||||
|
- Data formats:
|
||||||
|
- DateTime: ISO 8601 (YYYY-MM-DDTHH:MM:SS)
|
||||||
|
- Category: Text
|
||||||
|
- QX-Question: Text
|
||||||
|
- QX-Choices: (A)Opt1|(B)Opt2|(C)Opt3|(D)Opt4
|
||||||
|
- QX-UserAnswer: A/B/C/D
|
||||||
|
- QX-Correct: TRUE/FALSE
|
||||||
|
- FinalScore: Number (0-10)
|
||||||
|
|
||||||
|
**Template Information**:
|
||||||
|
|
||||||
|
- Template source: Created based on requirements
|
||||||
|
- Template file: CSV with fixed column structure
|
||||||
|
- Placeholders: None - strict format required
|
||||||
|
|
||||||
|
**Special Considerations**:
|
||||||
|
|
||||||
|
- CSV commas within text must be quoted
|
||||||
|
- Newlines in questions replaced with spaces
|
||||||
|
- Headers created only if file doesn't exist
|
||||||
|
- Append mode for all subsequent quiz sessions
|
||||||
54
example-custom-content/workflows/quiz-master/workflow.md
Normal file
54
example-custom-content/workflows/quiz-master/workflow.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
name: quiz-master
|
||||||
|
description: Interactive trivia quiz with progressive difficulty and gameshow atmosphere
|
||||||
|
web_bundle: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Quiz Master
|
||||||
|
|
||||||
|
**Goal:** To entertain users with an interactive trivia quiz experience featuring progressive difficulty questions, dual game modes, and CSV history tracking.
|
||||||
|
|
||||||
|
**Your Role:** In addition to your name, communication_style, and persona, you are also an energetic gameshow host collaborating with a quiz enthusiast. This is a partnership, not a client-vendor relationship. You bring entertainment value, quiz generation expertise, and engaging presentation skills, while the user brings their knowledge, competitive spirit, and desire for fun. Work together as equals to create an exciting quiz experience.
|
||||||
|
|
||||||
|
## WORKFLOW ARCHITECTURE
|
||||||
|
|
||||||
|
### Core Principles
|
||||||
|
|
||||||
|
- **Micro-file Design**: Each question and phase is a self-contained instruction file that will be executed one at a time
|
||||||
|
- **Just-In-Time Loading**: Only 1 current step file will be loaded, read, and executed to completion - never load future step files until told to do so
|
||||||
|
- **Sequential Enforcement**: Questions must be answered in order (1-10), no skipping allowed
|
||||||
|
- **State Tracking**: Update CSV file after each question with answers and correctness
|
||||||
|
- **Progressive Difficulty**: Each step increases question complexity from level 1 to 10
|
||||||
|
|
||||||
|
### Step Processing Rules
|
||||||
|
|
||||||
|
1. **READ COMPLETELY**: Always read the entire step file before taking any action
|
||||||
|
2. **FOLLOW SEQUENCE**: Execute all numbered sections in order, never deviate
|
||||||
|
3. **WAIT FOR INPUT**: If a menu is presented, halt and wait for user selection
|
||||||
|
4. **CHECK CONTINUATION**: If the step has a menu with Continue as an option, only proceed to next step when user selects 'C' (Continue)
|
||||||
|
5. **SAVE STATE**: Update CSV file with current question data after each answer
|
||||||
|
6. **LOAD NEXT**: When directed, load, read entire file, then execute the next step file
|
||||||
|
|
||||||
|
### Critical Rules (NO EXCEPTIONS)
|
||||||
|
|
||||||
|
- 🛑 **NEVER** load multiple step files simultaneously
|
||||||
|
- 📖 **ALWAYS** read entire step file before execution
|
||||||
|
- 🚫 **NEVER** skip questions or optimize the sequence
|
||||||
|
- 💾 **ALWAYS** update CSV file after each question
|
||||||
|
- 🎯 **ALWAYS** follow the exact instructions in the step file
|
||||||
|
- ⏸️ **ALWAYS** halt at menus and wait for user input
|
||||||
|
- 📋 **NEVER** create mental todo lists from future steps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## INITIALIZATION SEQUENCE
|
||||||
|
|
||||||
|
### 1. Module Configuration Loading
|
||||||
|
|
||||||
|
Load and read full config from {project-root}/.bmad/bmb/config.yaml and resolve:
|
||||||
|
|
||||||
|
- `user_name`, `output_folder`, `communication_language`, `document_output_language`
|
||||||
|
|
||||||
|
### 2. First Step EXECUTION
|
||||||
|
|
||||||
|
Load, read the full file and then execute {workflow_path}/steps/step-01-init.md to begin the workflow.
|
||||||
26
example-custom-content/workflows/wassup/workflow.md
Normal file
26
example-custom-content/workflows/wassup/workflow.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: wassup
|
||||||
|
description: Will check everything that is local and not committed and tell me about what has been done so far that has not been committed.
|
||||||
|
web_bundle: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Wassup Workflow
|
||||||
|
|
||||||
|
**Goal:** To think about all local changes and tell me what we have done but not yet committed so far.
|
||||||
|
|
||||||
|
## Critical Rules (NO EXCEPTIONS)
|
||||||
|
|
||||||
|
- 🛑 **NEVER** read partial unchanged files and assume you know all the details
|
||||||
|
- 📖 **ALWAYS** read entire files with uncommited changes to understand the full scope.
|
||||||
|
- 🚫 **NEVER** assume you know what changed just by looking at a file name
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## INITIALIZATION SEQUENCE
|
||||||
|
|
||||||
|
- 1. Find all uncommitted changed files
|
||||||
|
- 2. Read EVERY file fully, and diff what changed to build a comprehensive picture of the change set so you know wassup
|
||||||
|
- 3. If you need more context read other files as needed.
|
||||||
|
- 4. Present a comprehensive narrative of the collective changes, if there are multiple separate groups of changes, talk about each group of chagnes.
|
||||||
|
- 5. Ask the user at least 2-3 clarifying questions to add further context.
|
||||||
|
- 6. Suggest a commit message and offer to commit the changes thus far.
|
||||||
@ -38,6 +38,7 @@ const { CLIUtils } = require('../../../lib/cli-utils');
|
|||||||
const { ManifestGenerator } = require('./manifest-generator');
|
const { ManifestGenerator } = require('./manifest-generator');
|
||||||
const { IdeConfigManager } = require('./ide-config-manager');
|
const { IdeConfigManager } = require('./ide-config-manager');
|
||||||
const { replaceAgentSidecarFolders } = require('./post-install-sidecar-replacement');
|
const { replaceAgentSidecarFolders } = require('./post-install-sidecar-replacement');
|
||||||
|
const { CustomHandler } = require('../custom/handler');
|
||||||
|
|
||||||
class Installer {
|
class Installer {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -51,6 +52,7 @@ class Installer {
|
|||||||
this.dependencyResolver = new DependencyResolver();
|
this.dependencyResolver = new DependencyResolver();
|
||||||
this.configCollector = new ConfigCollector();
|
this.configCollector = new ConfigCollector();
|
||||||
this.ideConfigManager = new IdeConfigManager();
|
this.ideConfigManager = new IdeConfigManager();
|
||||||
|
this.customHandler = new CustomHandler();
|
||||||
this.installedFiles = []; // Track all installed files
|
this.installedFiles = []; // Track all installed files
|
||||||
this.ttsInjectedFiles = []; // Track files with TTS injection applied
|
this.ttsInjectedFiles = []; // Track files with TTS injection applied
|
||||||
}
|
}
|
||||||
@ -1026,6 +1028,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update custom content (add new files, don't remove existing)
|
||||||
|
await this.updateCustomContent(projectDir, bmadDir);
|
||||||
|
|
||||||
// Replace {agent_sidecar_folder} placeholders in all agent files
|
// Replace {agent_sidecar_folder} placeholders in all agent files
|
||||||
console.log(chalk.dim('\n Configuring agent sidecar folders...'));
|
console.log(chalk.dim('\n Configuring agent sidecar folders...'));
|
||||||
const sidecarResults = await replaceAgentSidecarFolders(bmadDir);
|
const sidecarResults = await replaceAgentSidecarFolders(bmadDir);
|
||||||
@ -1163,6 +1168,133 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update custom content (add new files without removing existing ones)
|
||||||
|
* @param {string} projectDir - Project directory
|
||||||
|
* @param {string} bmadDir - BMAD installation directory
|
||||||
|
*/
|
||||||
|
async updateCustomContent(projectDir, bmadDir) {
|
||||||
|
try {
|
||||||
|
// Find all custom content
|
||||||
|
const customContents = await this.customHandler.findCustomContent(projectDir);
|
||||||
|
|
||||||
|
if (customContents.length === 0) {
|
||||||
|
return; // No custom content to update
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load core config
|
||||||
|
const coreConfigPath = path.join(bmadDir, 'bmb', 'config.yaml');
|
||||||
|
let coreConfig = {};
|
||||||
|
if (await fs.pathExists(coreConfigPath)) {
|
||||||
|
const yamlLib = require('yaml');
|
||||||
|
const coreConfigContent = await fs.readFile(coreConfigPath, 'utf8');
|
||||||
|
coreConfig = yamlLib.load(coreConfigContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.dim('\nUpdating custom content...'));
|
||||||
|
|
||||||
|
for (const customPath of customContents) {
|
||||||
|
const customInfo = await this.customHandler.getCustomInfo(customPath);
|
||||||
|
if (customInfo) {
|
||||||
|
console.log(chalk.dim(` Checking: ${customInfo.name}`));
|
||||||
|
|
||||||
|
// Install only adds new files, doesn't remove existing ones
|
||||||
|
const results = await this.customHandler.install(
|
||||||
|
customPath,
|
||||||
|
bmadDir,
|
||||||
|
{
|
||||||
|
user_name: coreConfig.user_name,
|
||||||
|
communication_language: coreConfig.communication_language,
|
||||||
|
output_folder: coreConfig.output_folder,
|
||||||
|
bmad_folder: path.basename(bmadDir),
|
||||||
|
},
|
||||||
|
(filePath) => {
|
||||||
|
this.installedFiles.push(filePath);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Only show if new files were added or preserved
|
||||||
|
if (results.filesCopied > 0 || results.preserved > 0) {
|
||||||
|
if (results.filesCopied > 0) {
|
||||||
|
console.log(chalk.dim(` Added ${results.filesCopied} new file(s)`));
|
||||||
|
}
|
||||||
|
if (results.preserved > 0) {
|
||||||
|
console.log(chalk.dim(` Preserved ${results.preserved} existing file(s)`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(chalk.yellow(`Warning: Failed to update custom content: ${error.message}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install custom content by ID
|
||||||
|
* @param {string} customId - Custom content ID
|
||||||
|
* @param {string} bmadDir - BMAD installation directory
|
||||||
|
* @param {Object} coreConfig - Core configuration
|
||||||
|
*/
|
||||||
|
async installCustomContent(customId, bmadDir, coreConfig) {
|
||||||
|
try {
|
||||||
|
// Find the custom content
|
||||||
|
const customContents = await this.customHandler.findCustomContent(process.cwd());
|
||||||
|
let customInfo = null;
|
||||||
|
let customPath = null;
|
||||||
|
|
||||||
|
for (const path of customContents) {
|
||||||
|
const info = await this.customHandler.getCustomInfo(path);
|
||||||
|
if (info && info.id === customId) {
|
||||||
|
customInfo = info;
|
||||||
|
customPath = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customInfo || !customPath) {
|
||||||
|
console.warn(chalk.yellow(`Warning: Custom content '${customId}' not found`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.dim(` Installing: ${customInfo.name}`));
|
||||||
|
|
||||||
|
// Install the custom content
|
||||||
|
const results = await this.customHandler.install(
|
||||||
|
customPath,
|
||||||
|
bmadDir,
|
||||||
|
{
|
||||||
|
user_name: coreConfig.user_name,
|
||||||
|
communication_language: coreConfig.communication_language,
|
||||||
|
output_folder: coreConfig.output_folder,
|
||||||
|
bmad_folder: path.basename(bmadDir),
|
||||||
|
},
|
||||||
|
(filePath) => {
|
||||||
|
this.installedFiles.push(filePath);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Show results
|
||||||
|
if (results.agentsInstalled > 0) {
|
||||||
|
console.log(chalk.dim(` ${results.agentsInstalled} agent(s) installed`));
|
||||||
|
}
|
||||||
|
if (results.workflowsInstalled > 0) {
|
||||||
|
console.log(chalk.dim(` ${results.workflowsInstalled} workflow(s) installed`));
|
||||||
|
}
|
||||||
|
if (results.filesCopied > 0) {
|
||||||
|
console.log(chalk.dim(` ${results.filesCopied} file(s) copied`));
|
||||||
|
}
|
||||||
|
if (results.preserved > 0) {
|
||||||
|
console.log(chalk.dim(` ${results.preserved} file(s) preserved`));
|
||||||
|
}
|
||||||
|
if (results.errors.length > 0) {
|
||||||
|
console.log(chalk.yellow(` ${results.errors.length} error(s)`));
|
||||||
|
for (const error of results.errors) console.log(chalk.dim(` - ${error}`));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(chalk.red(`Failed to install custom content '${customId}':`, error.message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private: Create directory structure
|
* Private: Create directory structure
|
||||||
*/
|
*/
|
||||||
|
|||||||
266
tools/cli/installers/lib/custom/handler.js
Normal file
266
tools/cli/installers/lib/custom/handler.js
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
const path = require('node:path');
|
||||||
|
const fs = require('fs-extra');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const yaml = require('js-yaml');
|
||||||
|
const { FileOps } = require('../../../lib/file-ops');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for custom content (custom.yaml)
|
||||||
|
* Installs custom agents and workflows without requiring a full module structure
|
||||||
|
*/
|
||||||
|
class CustomHandler {
|
||||||
|
constructor() {
|
||||||
|
this.fileOps = new FileOps();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all custom.yaml files in the project
|
||||||
|
* @param {string} projectRoot - Project root directory
|
||||||
|
* @returns {Array} List of custom content paths
|
||||||
|
*/
|
||||||
|
async findCustomContent(projectRoot) {
|
||||||
|
const customPaths = [];
|
||||||
|
|
||||||
|
// Helper function to recursively scan directories
|
||||||
|
async function scanDirectory(dir, excludePaths = []) {
|
||||||
|
try {
|
||||||
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = path.join(dir, entry.name);
|
||||||
|
|
||||||
|
// Skip hidden directories and common exclusions
|
||||||
|
if (
|
||||||
|
entry.name.startsWith('.') ||
|
||||||
|
entry.name === 'node_modules' ||
|
||||||
|
entry.name === 'dist' ||
|
||||||
|
entry.name === 'build' ||
|
||||||
|
entry.name === '.git' ||
|
||||||
|
entry.name === 'bmad'
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip excluded paths
|
||||||
|
if (excludePaths.some((exclude) => fullPath.startsWith(exclude))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
// Recursively scan subdirectories
|
||||||
|
await scanDirectory(fullPath, excludePaths);
|
||||||
|
} else if (entry.name === 'custom.yaml') {
|
||||||
|
// Found a custom.yaml file
|
||||||
|
customPaths.push(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore errors (e.g., permission denied)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the entire project, but exclude source directories
|
||||||
|
await scanDirectory(projectRoot, [path.join(projectRoot, 'src'), path.join(projectRoot, 'tools'), path.join(projectRoot, 'test')]);
|
||||||
|
|
||||||
|
return customPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom content info from a custom.yaml file
|
||||||
|
* @param {string} customYamlPath - Path to custom.yaml file
|
||||||
|
* @returns {Object|null} Custom content info
|
||||||
|
*/
|
||||||
|
async getCustomInfo(customYamlPath) {
|
||||||
|
try {
|
||||||
|
const configContent = await fs.readFile(customYamlPath, 'utf8');
|
||||||
|
|
||||||
|
// Try to parse YAML with error handling
|
||||||
|
let config;
|
||||||
|
try {
|
||||||
|
config = yaml.load(configContent);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.warn(chalk.yellow(`Warning: YAML parse error in ${customYamlPath}:`, parseError.message));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customDir = path.dirname(customYamlPath);
|
||||||
|
const relativePath = path.relative(process.cwd(), customDir);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: config.code || path.basename(customDir),
|
||||||
|
name: config.name || `Custom: ${path.basename(customDir)}`,
|
||||||
|
description: config.description || 'Custom agents and workflows',
|
||||||
|
path: customDir,
|
||||||
|
relativePath: relativePath,
|
||||||
|
defaultSelected: config.default_selected === true,
|
||||||
|
config: config,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(chalk.yellow(`Warning: Failed to read ${customYamlPath}:`, error.message));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install custom content
|
||||||
|
* @param {string} customPath - Path to custom content directory
|
||||||
|
* @param {string} bmadDir - Target bmad directory
|
||||||
|
* @param {Object} config - Configuration from custom.yaml
|
||||||
|
* @param {Function} fileTrackingCallback - Optional callback to track installed files
|
||||||
|
* @returns {Object} Installation result
|
||||||
|
*/
|
||||||
|
async install(customPath, bmadDir, config, fileTrackingCallback = null) {
|
||||||
|
const results = {
|
||||||
|
agentsInstalled: 0,
|
||||||
|
workflowsInstalled: 0,
|
||||||
|
filesCopied: 0,
|
||||||
|
preserved: 0,
|
||||||
|
errors: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create custom directories in bmad
|
||||||
|
const bmadCustomDir = path.join(bmadDir, 'custom');
|
||||||
|
const bmadAgentsDir = path.join(bmadCustomDir, 'agents');
|
||||||
|
const bmadWorkflowsDir = path.join(bmadCustomDir, 'workflows');
|
||||||
|
|
||||||
|
await fs.ensureDir(bmadCustomDir);
|
||||||
|
await fs.ensureDir(bmadAgentsDir);
|
||||||
|
await fs.ensureDir(bmadWorkflowsDir);
|
||||||
|
|
||||||
|
// Process agents - copy entire agents directory structure
|
||||||
|
const agentsDir = path.join(customPath, 'agents');
|
||||||
|
if (await fs.pathExists(agentsDir)) {
|
||||||
|
await this.copyDirectory(agentsDir, bmadAgentsDir, results, fileTrackingCallback, config);
|
||||||
|
|
||||||
|
// Count agent files
|
||||||
|
const agentFiles = await this.findFilesRecursively(agentsDir, ['.agent.yaml', '.md']);
|
||||||
|
results.agentsInstalled = agentFiles.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process workflows - copy entire workflows directory structure
|
||||||
|
const workflowsDir = path.join(customPath, 'workflows');
|
||||||
|
if (await fs.pathExists(workflowsDir)) {
|
||||||
|
await this.copyDirectory(workflowsDir, bmadWorkflowsDir, results, fileTrackingCallback, config);
|
||||||
|
|
||||||
|
// Count workflow files
|
||||||
|
const workflowFiles = await this.findFilesRecursively(workflowsDir, ['.md']);
|
||||||
|
results.workflowsInstalled = workflowFiles.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process any additional files at root
|
||||||
|
const entries = await fs.readdir(customPath, { withFileTypes: true });
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.isFile() && entry.name !== 'custom.yaml' && !entry.name.startsWith('.') && !entry.name.endsWith('.md')) {
|
||||||
|
// Skip .md files at root as they're likely docs
|
||||||
|
const sourcePath = path.join(customPath, entry.name);
|
||||||
|
const targetPath = path.join(bmadCustomDir, entry.name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if file already exists
|
||||||
|
if (await fs.pathExists(targetPath)) {
|
||||||
|
// File already exists, preserve it
|
||||||
|
results.preserved = (results.preserved || 0) + 1;
|
||||||
|
} else {
|
||||||
|
await fs.copy(sourcePath, targetPath);
|
||||||
|
results.filesCopied++;
|
||||||
|
|
||||||
|
if (fileTrackingCallback) {
|
||||||
|
fileTrackingCallback(targetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.errors.push(`Failed to copy file ${entry.name}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.errors.push(`Installation failed: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all files with specific extensions recursively
|
||||||
|
* @param {string} dir - Directory to search
|
||||||
|
* @param {Array} extensions - File extensions to match
|
||||||
|
* @returns {Array} List of matching files
|
||||||
|
*/
|
||||||
|
async findFilesRecursively(dir, extensions) {
|
||||||
|
const files = [];
|
||||||
|
|
||||||
|
async function search(currentDir) {
|
||||||
|
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = path.join(currentDir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
await search(fullPath);
|
||||||
|
} else if (extensions.some((ext) => entry.name.endsWith(ext))) {
|
||||||
|
files.push(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await search(dir);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively copy a directory
|
||||||
|
* @param {string} sourceDir - Source directory
|
||||||
|
* @param {string} targetDir - Target directory
|
||||||
|
* @param {Object} results - Results object to update
|
||||||
|
* @param {Function} fileTrackingCallback - Optional callback
|
||||||
|
* @param {Object} config - Configuration for placeholder replacement
|
||||||
|
*/
|
||||||
|
async copyDirectory(sourceDir, targetDir, results, fileTrackingCallback, config) {
|
||||||
|
await fs.ensureDir(targetDir);
|
||||||
|
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const sourcePath = path.join(sourceDir, entry.name);
|
||||||
|
const targetPath = path.join(targetDir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
await this.copyDirectory(sourcePath, targetPath, results, fileTrackingCallback, config);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// Check if file already exists
|
||||||
|
if (await fs.pathExists(targetPath)) {
|
||||||
|
// File already exists, preserve it
|
||||||
|
results.preserved = (results.preserved || 0) + 1;
|
||||||
|
} else {
|
||||||
|
// Copy with placeholder replacement for text files
|
||||||
|
const textExtensions = ['.md', '.yaml', '.yml', '.txt', '.json'];
|
||||||
|
if (textExtensions.some((ext) => entry.name.endsWith(ext))) {
|
||||||
|
await this.fileOps.copyFile(sourcePath, targetPath, {
|
||||||
|
bmadFolder: config.bmad_folder || 'bmad',
|
||||||
|
userName: config.user_name || 'User',
|
||||||
|
communicationLanguage: config.communication_language || 'English',
|
||||||
|
outputFolder: config.output_folder || 'docs',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await fs.copy(sourcePath, targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.filesCopied++;
|
||||||
|
if (fileTrackingCallback) {
|
||||||
|
fileTrackingCallback(targetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.name.endsWith('.md')) {
|
||||||
|
results.workflowsInstalled++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.errors.push(`Failed to copy ${entry.name}: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { CustomHandler };
|
||||||
@ -137,10 +137,11 @@ class ModuleManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this directory contains a module (only install-config.yaml is valid now)
|
// Check if this directory contains a module (install-config.yaml OR custom.yaml)
|
||||||
const installerConfigPath = path.join(fullPath, '_module-installer', 'install-config.yaml');
|
const installerConfigPath = path.join(fullPath, '_module-installer', 'install-config.yaml');
|
||||||
|
const customConfigPath = path.join(fullPath, 'custom.yaml');
|
||||||
|
|
||||||
if (await fs.pathExists(installerConfigPath)) {
|
if ((await fs.pathExists(installerConfigPath)) || (await fs.pathExists(customConfigPath))) {
|
||||||
modulePaths.add(fullPath);
|
modulePaths.add(fullPath);
|
||||||
// Don't scan inside modules - they might have their own nested structures
|
// Don't scan inside modules - they might have their own nested structures
|
||||||
continue;
|
continue;
|
||||||
@ -225,11 +226,19 @@ class ModuleManager {
|
|||||||
* @returns {Object|null} Module info or null if not a valid module
|
* @returns {Object|null} Module info or null if not a valid module
|
||||||
*/
|
*/
|
||||||
async getModuleInfo(modulePath, defaultName, sourceDescription) {
|
async getModuleInfo(modulePath, defaultName, sourceDescription) {
|
||||||
// Check for module structure (only install-config.yaml is valid now)
|
// Check for module structure (install-config.yaml OR custom.yaml)
|
||||||
const installerConfigPath = path.join(modulePath, '_module-installer', 'install-config.yaml');
|
const installerConfigPath = path.join(modulePath, '_module-installer', 'install-config.yaml');
|
||||||
|
const customConfigPath = path.join(modulePath, 'custom.yaml');
|
||||||
|
let configPath = null;
|
||||||
|
|
||||||
|
if (await fs.pathExists(installerConfigPath)) {
|
||||||
|
configPath = installerConfigPath;
|
||||||
|
} else if (await fs.pathExists(customConfigPath)) {
|
||||||
|
configPath = customConfigPath;
|
||||||
|
}
|
||||||
|
|
||||||
// Skip if this doesn't look like a module
|
// Skip if this doesn't look like a module
|
||||||
if (!(await fs.pathExists(installerConfigPath))) {
|
if (!configPath) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,11 +252,12 @@ class ModuleManager {
|
|||||||
description: 'BMAD Module',
|
description: 'BMAD Module',
|
||||||
version: '5.0.0',
|
version: '5.0.0',
|
||||||
source: sourceDescription,
|
source: sourceDescription,
|
||||||
|
isCustom: configPath === customConfigPath,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read module config for metadata
|
// Read module config for metadata
|
||||||
try {
|
try {
|
||||||
const configContent = await fs.readFile(installerConfigPath, 'utf8');
|
const configContent = await fs.readFile(configPath, 'utf8');
|
||||||
const config = yaml.load(configContent);
|
const config = yaml.load(configContent);
|
||||||
|
|
||||||
// Use the code property as the id if available
|
// Use the code property as the id if available
|
||||||
@ -284,6 +294,12 @@ class ModuleManager {
|
|||||||
if (await fs.pathExists(installerConfigPath)) {
|
if (await fs.pathExists(installerConfigPath)) {
|
||||||
return srcModulePath;
|
return srcModulePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also check for custom.yaml in src/modules
|
||||||
|
const customConfigPath = path.join(srcModulePath, 'custom.yaml');
|
||||||
|
if (await fs.pathExists(customConfigPath)) {
|
||||||
|
return srcModulePath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found in src/modules, search the entire project
|
// If not found in src/modules, search the entire project
|
||||||
@ -298,10 +314,18 @@ class ModuleManager {
|
|||||||
// Need to read configs to match by ID
|
// Need to read configs to match by ID
|
||||||
for (const modulePath of allModulePaths) {
|
for (const modulePath of allModulePaths) {
|
||||||
const installerConfigPath = path.join(modulePath, '_module-installer', 'install-config.yaml');
|
const installerConfigPath = path.join(modulePath, '_module-installer', 'install-config.yaml');
|
||||||
|
const customConfigPath = path.join(modulePath, 'custom.yaml');
|
||||||
|
|
||||||
|
let configPath = null;
|
||||||
if (await fs.pathExists(installerConfigPath)) {
|
if (await fs.pathExists(installerConfigPath)) {
|
||||||
|
configPath = installerConfigPath;
|
||||||
|
} else if (await fs.pathExists(customConfigPath)) {
|
||||||
|
configPath = customConfigPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configPath) {
|
||||||
try {
|
try {
|
||||||
const configContent = await fs.readFile(installerConfigPath, 'utf8');
|
const configContent = await fs.readFile(configPath, 'utf8');
|
||||||
const config = yaml.load(configContent);
|
const config = yaml.load(configContent);
|
||||||
if (config.code === moduleName) {
|
if (config.code === moduleName) {
|
||||||
return modulePath;
|
return modulePath;
|
||||||
|
|||||||
@ -491,11 +491,13 @@ class UI {
|
|||||||
const availableModules = await moduleManager.listAvailable();
|
const availableModules = await moduleManager.listAvailable();
|
||||||
|
|
||||||
const isNewInstallation = installedModuleIds.size === 0;
|
const isNewInstallation = installedModuleIds.size === 0;
|
||||||
return availableModules.map((mod) => ({
|
const moduleChoices = availableModules.map((mod) => ({
|
||||||
name: mod.name,
|
name: mod.isCustom ? `${mod.name} ${chalk.red('(Custom)')}` : mod.name,
|
||||||
value: mod.id,
|
value: mod.id,
|
||||||
checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
|
checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
return moduleChoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user