From 29d4dc030c94b752f4746754d59785aad78890ab Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 30 Sep 2025 20:07:04 +0300 Subject: [PATCH] feat(bmvcs): add VCS adaptation examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add practical examples demonstrating VCS-agnostic adaptation: - vcs-adaptation-examples.md: 6 real-world scenarios (GitHub Flow, GitFlow, No VCS, SVN, Trunk-Based, Multi-VCS) - vcs-detection-implementation.py: Reference implementation of Git workflow auto-detection with confidence scoring - examples/README.md: Guide to using examples and integration Examples demonstrate "Detection as a HINT, not a DECISION" principle with evidence-based suggestions and user confirmation. Part 4/5 of BMVCS migration (#661) šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/modules/bmvcs/examples/README.md | 79 ++++ .../bmvcs/examples/vcs-adaptation-examples.md | 293 ++++++++++++++ .../examples/vcs-detection-implementation.py | 380 ++++++++++++++++++ 3 files changed, 752 insertions(+) create mode 100644 src/modules/bmvcs/examples/README.md create mode 100644 src/modules/bmvcs/examples/vcs-adaptation-examples.md create mode 100644 src/modules/bmvcs/examples/vcs-detection-implementation.py diff --git a/src/modules/bmvcs/examples/README.md b/src/modules/bmvcs/examples/README.md new file mode 100644 index 00000000..bb3a365b --- /dev/null +++ b/src/modules/bmvcs/examples/README.md @@ -0,0 +1,79 @@ +# BMVCS Examples + +Practical examples demonstrating VCS-agnostic adaptation in BMAD. + +## Files in This Directory + +### [vcs-adaptation-examples.md](./vcs-adaptation-examples.md) + +**Real-world scenarios** showing how BMAD adapts to different VCS workflows: + +- **Startup with GitHub Flow**: Fast-paced web development +- **Enterprise with GitFlow**: Structured releases with versions +- **No Version Control**: One-time scripts and prototypes +- **Custom SVN Workflow**: Legacy system adaptation +- **Trunk-Based with Feature Flags**: Continuous deployment +- **Complex Multi-VCS Setup**: Mixed systems in one organization + +Each example shows discovery dialogue, BMAD adaptations, and generated artifacts. + +### [vcs-detection-implementation.py](./vcs-detection-implementation.py) + +**Reference implementation** of Git workflow auto-detection: + +- Analyzes repository history to detect workflow patterns +- Calculates confidence scores for GitFlow, GitHub Flow, and Trunk-Based +- Follows "Detection as a HINT, not a DECISION" principle +- Interactive confirmation with evidence presentation +- Handles edge cases (migration, unclear patterns, fresh repos) + +**Note**: This is an example implementation in Python. The actual BMAD implementation may use JavaScript/TypeScript. This demonstrates the detection logic that can be adapted to any language. + +## Usage + +### Running the Detector Example + +```bash +cd /path/to/your/git/repo +python /path/to/vcs-detection-implementation.py +``` + +The script will: + +1. Analyze your Git history +2. Score workflow indicators +3. Present detection results with evidence +4. Ask for confirmation (never auto-decides) +5. Save configuration to `.bmad/vcs_config.json` + +### Understanding the Examples + +The adaptation examples show specific output for each workflow type. Use them as: + +- **Reference**: See how BMAD should adapt terminology and structure +- **Templates**: Copy patterns for custom integrations +- **Documentation**: Explain VCS-agnostic behavior to users + +## Key Principles Demonstrated + +1. **Discovery First**: Always ask, never assume +2. **Evidence-Based**: Show detection reasoning transparently +3. **User Confirmation**: Detection is advisory, not prescriptive +4. **Graceful Fallback**: Handle unclear cases with questions +5. **Respect Existing**: Adapt to their workflow, don't change it + +## Integration with BMAD Agents + +These examples inform how all BMAD agents should adapt: + +- **Architect**: Generate VCS-appropriate architecture docs +- **PM**: Create requirements matching workflow style +- **SM**: Size stories for the team's release cadence +- **Dev**: Suggest VCS-appropriate code delivery +- **QA**: Align test plans with workflow gates + +## Further Reading + +- [VCS Agnostic Principles](../docs/VCS_AGNOSTIC_PRINCIPLES.md) +- [Detection Confidence Scoring](../docs/VCS_DETECTION_CONFIDENCE.md) +- [Discovery Task Implementation](../tasks/discover-vcs.md) diff --git a/src/modules/bmvcs/examples/vcs-adaptation-examples.md b/src/modules/bmvcs/examples/vcs-adaptation-examples.md new file mode 100644 index 00000000..7373e314 --- /dev/null +++ b/src/modules/bmvcs/examples/vcs-adaptation-examples.md @@ -0,0 +1,293 @@ +# VCS Adaptation Examples + +## Real-World Scenarios: How BMAD Adapts + +### Example 1: Startup with GitHub Flow + +**Context:** 5-person team, web SaaS, deploys daily + +**Discovery:** + +``` +BMAD: "How does your team manage code versions?" +User: "Git with GitHub" +BMAD: "Which Git workflow best describes your approach?" +User: "GitHub Flow - simple feature branches" +``` + +**BMAD Adapts:** + +- Architect generates lightweight, PR-sized architecture updates +- SM creates 1-3 day stories that map to single PRs +- Dev suggests branch names like `feature/add-user-auth` +- All docs optimized for quick review in PR comments + +**Generated Architecture Snippet:** + +```markdown +## Payment Service Update + +_PR: #234 - feature/add-stripe-integration_ + +### Changes in This PR + +- New Stripe webhook handler +- Updated payment models +- Added retry logic + +### Testing + +- [ ] Unit tests for webhook handler +- [ ] Integration test with Stripe test mode +- [ ] Manual testing checklist in PR +``` + +--- + +### Example 2: Enterprise with GitFlow + +**Context:** 50-person team, banking software, quarterly releases + +**Discovery:** + +``` +BMAD: "How does your team manage code versions?" +User: "Git with corporate server" +BMAD: "Which Git workflow?" +User: "GitFlow - we have develop, release, and hotfix branches" +``` + +**BMAD Adapts:** + +- Architect creates version-oriented architecture docs +- PM generates release-scoped PRDs +- SM groups stories by release version +- Dev follows strict branch naming + +**Generated Architecture Snippet:** + +```markdown +## Release 2.4.0 Architecture + +### Version Highlights + +- New authentication system (breaking change) +- Performance improvements +- Database migration required + +### Branch Status + +- develop: v2.5.0 features in progress +- release/2.4.0: Final testing +- hotfix/2.3.1: Critical fix for production + +### Migration Guide + +From 2.3.x to 2.4.0: + +1. Run migration script +2. Update config files +3. Restart services in order +``` + +--- + +### Example 3: No Version Control + +**Context:** Data scientist, one-time analysis script + +**Discovery:** + +``` +BMAD: "How does your team manage code versions?" +User: "No version control needed - this is a one-time script" +``` + +**BMAD Adapts:** + +- All code in single, runnable package +- Extensive inline documentation +- No commit messages or branch references +- Date-stamped delivery + +**Generated Package:** + +``` +customer_analysis_20240315/ +ā”œā”€ā”€ README.md # Complete instructions +ā”œā”€ā”€ requirements.txt # All Python dependencies +ā”œā”€ā”€ analysis.py # Full script with comments +ā”œā”€ā”€ data/ +│ └── sample.csv # Sample data format +└── output/ + └── results_template.xlsx +``` + +**README Content:** + +```markdown +# Customer Analysis Script + +Generated: 2024-03-15 + +## Quick Start + +1. Install dependencies: pip install -r requirements.txt +2. Place your data in data/input.csv +3. Run: python analysis.py +4. Results appear in output/ + +## No Version Control Required + +This is a complete, self-contained package. +``` + +--- + +### Example 4: Custom SVN Workflow + +**Context:** Game studio using Subversion + +**Discovery:** + +``` +BMAD: "How does your team manage code versions?" +User: "Other version control system" +BMAD: "Which system?" +User: "Subversion (SVN)" +``` + +**BMAD Adapts:** + +- Uses "revision" instead of "commit" +- References trunk/branches/tags structure +- Revision numbers, not hashes +- SVN-specific commands + +**Generated Instructions:** + +```markdown +## Integration Steps + +1. Update your working copy: + svn update + +2. Create feature branch: + svn copy ^/trunk ^/branches/feature-player-inventory + +3. After implementation: + svn merge ^/branches/feature-player-inventory + +4. Commit with revision message: + svn commit -m "Add player inventory system (refs ticket #456)" +``` + +--- + +### Example 5: Trunk-Based with Feature Flags + +**Context:** Netflix-style continuous deployment + +**Discovery:** + +``` +BMAD: "How does your team manage code versions?" +User: "Git with GitHub" +BMAD: "Which Git workflow?" +User: "Trunk-Based - we deploy continuously" +``` + +**BMAD Adapts:** + +- Everything behind feature flags +- Tiny, hours-long tasks +- Direct commits or same-day PRs +- Progressive rollout plans + +**Generated Story:** + +````markdown +## Story: Add Recommendation Engine + +Size: 4 hours +Flag: `recommendation-engine-v2` + +### Implementation + +```python +if feature_flag.is_enabled("recommendation-engine-v2", user_id): + return new_recommendation_engine(user_id) +else: + return legacy_recommendations(user_id) +``` +```` + +### Rollout Plan + +- Hour 1-2: Implement behind flag (0% users) +- Hour 3: Deploy and enable for employees +- Hour 4: Enable for 1% external users +- Day 2: 10% if metrics good +- Day 3: 50% +- Day 5: 100% and schedule flag removal + +``` + +--- + +### Example 6: Complex Multi-VCS Setup + +**Context:** Enterprise with mixed systems + +**Discovery:** +``` + +BMAD: "How does your team manage code versions?" +User: "Custom/Complex setup" +BMAD: "Please describe:" +User: "Frontend in Git, backend in Perforce, configs in SVN" + +```` + +**BMAD Adapts:** +- Asks for component-specific preferences +- Generates VCS-appropriate artifacts per component +- Uses neutral terminology in cross-component docs + +**Generated Guidance:** +```markdown +## Multi-VCS Development Guide + +### Frontend (Git/GitHub Flow) +- Feature branches from main +- PR review process +- Deploy on merge + +### Backend (Perforce) +- Create changelist for features +- Submit after review +- Changelist numbers in deployment notes + +### Configuration (SVN) +- Update from trunk before changes +- Commit with revision references +- Tag for production releases + +### Cross-Component Changes +When updating across systems: +1. Frontend PR: #123 +2. Backend Changelist: 456789 +3. Config Revision: r1234 + +Reference all three in deployment ticket. +```` + +## Key Takeaways + +1. **BMAD never assumes** - always discovers first +2. **Adapts terminology** - commit/changelist/revision as appropriate +3. **Respects workflows** - doesn't try to "improve" existing processes +4. **Practical focus** - generates what works with their tools +5. **Clear communication** - uses the team's language + +This flexibility makes BMAD valuable to ANY team, regardless of their VCS choice. diff --git a/src/modules/bmvcs/examples/vcs-detection-implementation.py b/src/modules/bmvcs/examples/vcs-detection-implementation.py new file mode 100644 index 00000000..b148443d --- /dev/null +++ b/src/modules/bmvcs/examples/vcs-detection-implementation.py @@ -0,0 +1,380 @@ +#!/usr/bin/env python3 +""" +Example implementation of VCS workflow auto-detection for BMAD agents. +This can be adapted for different languages and Git libraries. +""" + +import subprocess +import json +from datetime import datetime, timedelta +from typing import Dict, List, Tuple, Optional + + +class GitWorkflowDetector: + """ + Auto-detect Git workflow from repository history. + Follows the principle: "Detection as a HINT, not a DECISION" + """ + + def __init__(self, repo_path: str = '.'): + self.repo_path = repo_path + self.confidence_threshold = 0.7 + + def run_git_command(self, cmd: str) -> Optional[str]: + """Execute git command and return output""" + try: + result = subprocess.run( + cmd.split(), + cwd=self.repo_path, + capture_output=True, + text=True, + check=True + ) + return result.stdout.strip() + except subprocess.CalledProcessError: + return None + + def detect_workflow(self) -> Dict: + """ + Main detection method that returns workflow suggestion with confidence. + """ + if not self.is_git_repo(): + return { + 'detected': False, + 'reason': 'Not a Git repository' + } + + # Calculate scores for each workflow + gitflow_score = self._score_gitflow() + github_flow_score = self._score_github_flow() + trunk_based_score = self._score_trunk_based() + + # Check for migration + migration_info = self._detect_migration() + + # Determine best match + scores = { + 'gitflow': gitflow_score, + 'github_flow': github_flow_score, + 'trunk_based': trunk_based_score + } + + best_workflow = max(scores.items(), key=lambda x: x[1]['score']) + workflow_name = best_workflow[0] + confidence = best_workflow[1]['score'] + evidence = best_workflow[1]['evidence'] + + # Check if confidence meets threshold + if confidence < self.confidence_threshold: + return { + 'detected': True, + 'workflow': 'unclear', + 'confidence': confidence, + 'evidence': evidence, + 'needs_clarification': True, + 'migration_detected': migration_info['detected'] + } + + return { + 'detected': True, + 'workflow': workflow_name, + 'confidence': confidence, + 'evidence': evidence, + 'migration_detected': migration_info['detected'], + 'migration_info': migration_info if migration_info['detected'] else None + } + + def is_git_repo(self) -> bool: + """Check if current directory is a Git repository""" + return self.run_git_command('git rev-parse --git-dir') is not None + + def _score_gitflow(self) -> Dict: + """Score GitFlow indicators""" + score = 0.0 + evidence = [] + + # Check for develop branch + branches = self.run_git_command('git branch -a') + if branches and ('develop' in branches or 'development' in branches): + score += 0.3 + evidence.append("Found develop branch") + + # Check for release branches + if branches and 'release/' in branches: + release_count = branches.count('release/') + score += 0.3 + evidence.append(f"Found {release_count} release branches") + + # Check for hotfix branches + if branches and 'hotfix/' in branches: + score += 0.2 + evidence.append("Found hotfix branches") + + # Check for version tags + tags = self.run_git_command('git tag -l v*') + if tags: + tag_count = len(tags.split('\n')) + score += 0.2 + evidence.append(f"Found {tag_count} version tags") + + return {'score': score, 'evidence': evidence} + + def _score_github_flow(self) -> Dict: + """Score GitHub Flow indicators""" + score = 0.0 + evidence = [] + + # Check for PR merge patterns in recent commits + recent_commits = self.run_git_command( + 'git log --oneline --since="90 days ago" --grep="Merge pull request"' + ) + if recent_commits: + pr_count = len(recent_commits.split('\n')) + score += 0.3 + evidence.append(f"Found {pr_count} PR merges in last 90 days") + + # Check for squash merge patterns + squash_commits = self.run_git_command( + 'git log --oneline --since="90 days ago" --grep="(#"' + ) + if squash_commits: + score += 0.2 + evidence.append("Found squash-merge patterns") + + # Check average branch lifespan (simplified) + branches = self.run_git_command('git branch -a') + if branches and 'feature/' in branches: + score += 0.3 + evidence.append("Using feature branch naming") + + # No develop branch is positive for GitHub Flow + if branches and 'develop' not in branches: + score += 0.2 + evidence.append("No develop branch (GitHub Flow indicator)") + + return {'score': score, 'evidence': evidence} + + def _score_trunk_based(self) -> Dict: + """Score Trunk-Based Development indicators""" + score = 0.0 + evidence = [] + + # Check ratio of direct commits to main + main_commits = self.run_git_command( + 'git log --oneline --since="90 days ago" --first-parent main' + ) + all_commits = self.run_git_command( + 'git log --oneline --since="90 days ago"' + ) + + if main_commits and all_commits: + main_count = len(main_commits.split('\n')) + total_count = len(all_commits.split('\n')) + ratio = main_count / total_count + + if ratio > 0.5: + score += 0.4 + evidence.append(f"{int(ratio * 100)}% commits directly to main") + + # Check for feature flags in commit messages + feature_flag_commits = self.run_git_command( + 'git log --oneline --since="90 days ago" --grep="feature flag" -i' + ) + if feature_flag_commits: + score += 0.3 + evidence.append("Found feature flag usage in commits") + + # Check for very short-lived branches (would need more complex analysis) + # Simplified: check if most branches are deleted quickly + deleted_branches = self.run_git_command('git reflog show --all | grep "branch:"') + if deleted_branches: + score += 0.3 + evidence.append("Pattern suggests short-lived branches") + + return {'score': score, 'evidence': evidence} + + def _detect_migration(self) -> Dict: + """Detect if workflow has changed recently""" + # Compare recent vs historical commit patterns + recent = self.run_git_command( + 'git log --oneline --since="30 days ago" --pretty=format:"%d"' + ) + historical = self.run_git_command( + 'git log --oneline --since="90 days ago" --until="30 days ago" --pretty=format:"%d"' + ) + + if not recent or not historical: + return {'detected': False} + + # Simple heuristic: check if branch naming patterns changed + recent_has_develop = 'develop' in recent + historical_has_develop = 'develop' in historical + + if recent_has_develop != historical_has_develop: + return { + 'detected': True, + 'recent_pattern': 'GitFlow-like' if recent_has_develop else 'GitHub Flow-like', + 'historical_pattern': 'GitFlow-like' if historical_has_develop else 'GitHub Flow-like' + } + + return {'detected': False} + + def interactive_confirmation(self, detection_result: Dict) -> str: + """ + Present detection results to user and get confirmation. + This demonstrates the "hint not decision" principle. + """ + if not detection_result['detected']: + print(f"āŒ {detection_result['reason']}") + return self.manual_selection() + + if detection_result['workflow'] == 'unclear': + print("šŸ¤” Could not confidently detect your workflow.") + print(f" Confidence: {detection_result['confidence']:.1%}") + return self.clarifying_questions() + + # Present detection with evidence + print(f"šŸ” Analyzed your Git history...") + print(f"\nDetected workflow: **{detection_result['workflow']}**") + print(f"Confidence: {detection_result['confidence']:.1%}\n") + print("Evidence:") + for item in detection_result['evidence']: + print(f" āœ“ {item}") + + if detection_result['migration_detected']: + print("\nšŸ“Š Note: Detected a possible workflow change recently") + print(f" Recent: {detection_result['migration_info']['recent_pattern']}") + print(f" Historical: {detection_result['migration_info']['historical_pattern']}") + + # Get confirmation + print("\nIs this correct?") + print("1. Yes, that's right") + print("2. No, we actually use something else") + print("3. We recently changed our approach") + print("4. It's more complex than that") + + choice = input("\nSelect (1-4): ") + + if choice == '1': + return detection_result['workflow'] + elif choice == '3': + return self.handle_migration() + else: + return self.manual_selection() + + def clarifying_questions(self) -> str: + """Ask progressive questions when detection is unclear""" + print("\nLet me ask a few questions to understand your workflow better:\n") + + # Progressive questions to increase confidence + score_adjustments = { + 'gitflow': 0, + 'github_flow': 0, + 'trunk_based': 0 + } + + # Question 1: Team size + print("1. How many developers actively commit code?") + print(" a) Just me") + print(" b) 2-5 developers") + print(" c) 6+ developers") + team_size = input("Select (a-c): ") + + if team_size == 'a': + score_adjustments['trunk_based'] += 0.3 + elif team_size == 'b': + score_adjustments['github_flow'] += 0.2 + elif team_size == 'c': + score_adjustments['gitflow'] += 0.2 + + # Question 2: Release frequency + print("\n2. How often do you release to production?") + print(" a) Multiple times daily") + print(" b) Weekly") + print(" c) Monthly or less frequently") + release_freq = input("Select (a-c): ") + + if release_freq == 'a': + score_adjustments['trunk_based'] += 0.3 + elif release_freq == 'b': + score_adjustments['github_flow'] += 0.3 + elif release_freq == 'c': + score_adjustments['gitflow'] += 0.3 + + # Determine recommendation + best_workflow = max(score_adjustments.items(), key=lambda x: x[1]) + return best_workflow[0] + + def manual_selection(self) -> str: + """Fallback to manual workflow selection""" + print("\nWhich Git workflow best describes your team's approach?\n") + print("1. GitHub Flow - Simple feature branches with pull requests") + print(" → Best for: Web apps, continuous deployment\n") + print("2. GitFlow - Structured branches (develop, release, hotfix)") + print(" → Best for: Versioned software, scheduled releases\n") + print("3. Trunk-Based - Direct commits or very short branches") + print(" → Best for: Mature CI/CD, experienced teams\n") + print("4. Custom Git workflow") + + choice = input("Select (1-4): ") + + workflow_map = { + '1': 'github_flow', + '2': 'gitflow', + '3': 'trunk_based', + '4': 'custom' + } + + return workflow_map.get(choice, 'github_flow') + + def handle_migration(self) -> str: + """Handle workflow migration scenario""" + print("\nWhich workflow should BMAD optimize for?") + print("1. The new approach (we've completed migration)") + print("2. The old approach (recent activity was exceptional)") + print("3. Both (we're still transitioning)") + + choice = input("Select (1-3): ") + + if choice == '3': + print("\nWhich workflow is your target state?") + + return self.manual_selection() + + +def main(): + """Example usage of the detector""" + detector = GitWorkflowDetector() + + # Run detection + result = detector.detect_workflow() + + # Get user confirmation (following "hint not decision" principle) + confirmed_workflow = detector.interactive_confirmation(result) + + # Save configuration + config = { + 'vcs_config': { + 'type': 'git', + 'workflow': confirmed_workflow, + 'detection_method': 'auto-detected' if result['detected'] else 'user-selected', + 'confidence_score': result.get('confidence', 0), + 'detection_evidence': result.get('evidence', []), + 'cache': { + 'detected_at': datetime.now().isoformat(), + 'valid_until': (datetime.now() + timedelta(days=7)).isoformat() + } + } + } + + print(f"\nāœ… Configuration saved!") + print(f" Workflow: {confirmed_workflow}") + print(f" All BMAD agents will adapt to your {confirmed_workflow} workflow.") + + # Save to file (in real implementation) + with open('.bmad/vcs_config.json', 'w') as f: + json.dump(config, f, indent=2) + + +if __name__ == '__main__': + main()