bmad-fh 6.0.0-alpha.23.96db56c9 → 6.0.0-alpha.23.bed978b2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/{publish-multi-artifact.yaml → publish.yaml} +4 -4
- package/README.md +117 -14
- package/package.json +2 -2
- package/src/core/lib/scope/scope-manager.js +37 -4
- package/test/test-scope-cli.js +1306 -0
- package/test/test-scope-e2e.js +618 -17
- package/test/test-scope-system.js +907 -97
- package/tools/cli/bmad-cli.js +5 -0
- package/tools/cli/commands/scope.js +1178 -43
- package/tools/cli/installers/lib/modules/manager.js +4 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: Publish
|
|
1
|
+
name: Publish
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -41,8 +41,8 @@ jobs:
|
|
|
41
41
|
env:
|
|
42
42
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
43
43
|
run: |
|
|
44
|
-
echo "Publishing bmad-fh@${{ steps.version.outputs.version }}
|
|
45
|
-
npm publish
|
|
44
|
+
echo "Publishing bmad-fh@${{ steps.version.outputs.version }}"
|
|
45
|
+
npm publish
|
|
46
46
|
|
|
47
47
|
- name: Summary
|
|
48
48
|
run: |
|
|
@@ -50,5 +50,5 @@ jobs:
|
|
|
50
50
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
51
51
|
echo "### Installation" >> $GITHUB_STEP_SUMMARY
|
|
52
52
|
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
|
|
53
|
-
echo "npx bmad-fh
|
|
53
|
+
echo "npx bmad-fh install" >> $GITHUB_STEP_SUMMARY
|
|
54
54
|
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Traditional AI tools do the thinking for you, producing average results. BMad ag
|
|
|
23
23
|
**Prerequisites**: [Node.js](https://nodejs.org) v20+
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npx bmad-fh
|
|
26
|
+
npx bmad-fh install
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Follow the installer prompts to configure your project. Then run:
|
|
@@ -66,31 +66,134 @@ BMad supports running multiple workflows in parallel across different terminal s
|
|
|
66
66
|
- **Multi-team projects** — Each team works in their own scope
|
|
67
67
|
- **Parallel feature development** — Develop auth, payments, and catalog simultaneously
|
|
68
68
|
- **Microservices** — One scope per service with shared contracts
|
|
69
|
+
- **Experimentation** — Create isolated scopes for spikes and prototypes
|
|
70
|
+
|
|
71
|
+
### Quick Start
|
|
69
72
|
|
|
70
73
|
```bash
|
|
71
74
|
# Initialize scope system
|
|
72
|
-
bmad scope init
|
|
75
|
+
npx bmad-fh scope init
|
|
73
76
|
|
|
74
77
|
# Create scopes for different services
|
|
75
|
-
bmad scope create auth --name "Authentication"
|
|
76
|
-
bmad scope create payments --name "
|
|
78
|
+
npx bmad-fh scope create auth --name "Authentication Service"
|
|
79
|
+
npx bmad-fh scope create payments --name "Payment Processing" --deps auth
|
|
80
|
+
|
|
81
|
+
# Set the active scope for your session
|
|
82
|
+
npx bmad-fh scope set auth
|
|
77
83
|
|
|
78
84
|
# Run workflows in parallel (different terminals)
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
# Terminal 1: Set scope to auth, run agent workflows
|
|
86
|
+
# Terminal 2: Set scope to payments, run agent workflows
|
|
81
87
|
|
|
82
88
|
# Share artifacts between scopes
|
|
83
|
-
bmad scope sync-up auth # Promote to shared layer
|
|
84
|
-
bmad scope sync-down payments # Pull shared updates
|
|
89
|
+
npx bmad-fh scope sync-up auth # Promote to shared layer
|
|
90
|
+
npx bmad-fh scope sync-down payments # Pull shared updates
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### CLI Reference
|
|
94
|
+
|
|
95
|
+
| Command | Description |
|
|
96
|
+
| ---------------------------------- | ------------------------------------------- |
|
|
97
|
+
| `npx bmad-fh scope init` | Initialize the scope system in your project |
|
|
98
|
+
| `npx bmad-fh scope list` | List all scopes (alias: `ls`) |
|
|
99
|
+
| `npx bmad-fh scope create <id>` | Create a new scope (alias: `new`) |
|
|
100
|
+
| `npx bmad-fh scope info <id>` | Show scope details (alias: `show`) |
|
|
101
|
+
| `npx bmad-fh scope set [id]` | Set active scope for session (alias: `use`) |
|
|
102
|
+
| `npx bmad-fh scope unset` | Clear active scope (alias: `clear`) |
|
|
103
|
+
| `npx bmad-fh scope remove <id>` | Remove a scope (aliases: `rm`, `delete`) |
|
|
104
|
+
| `npx bmad-fh scope archive <id>` | Archive a completed scope |
|
|
105
|
+
| `npx bmad-fh scope activate <id>` | Reactivate an archived scope |
|
|
106
|
+
| `npx bmad-fh scope sync-up <id>` | Promote artifacts to shared layer |
|
|
107
|
+
| `npx bmad-fh scope sync-down <id>` | Pull shared updates into scope |
|
|
108
|
+
| `npx bmad-fh scope help [cmd]` | Show help (add command for detailed help) |
|
|
109
|
+
|
|
110
|
+
### Create Options
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx bmad-fh scope create auth \
|
|
114
|
+
--name "Authentication Service" \
|
|
115
|
+
--description "User auth, SSO, and session management" \
|
|
116
|
+
--deps users,notifications \
|
|
117
|
+
--context # Create scope-specific project-context.md
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Directory Structure
|
|
121
|
+
|
|
122
|
+
After initialization and scope creation:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
project-root/
|
|
126
|
+
├── _bmad/
|
|
127
|
+
│ ├── _config/
|
|
128
|
+
│ │ └── scopes.yaml # Scope registry and settings
|
|
129
|
+
│ └── _events/
|
|
130
|
+
│ ├── event-log.yaml # Event history
|
|
131
|
+
│ └── subscriptions.yaml # Cross-scope subscriptions
|
|
132
|
+
│
|
|
133
|
+
├── _bmad-output/
|
|
134
|
+
│ ├── _shared/ # Shared knowledge layer
|
|
135
|
+
│ │ ├── project-context.md # Global project context
|
|
136
|
+
│ │ ├── contracts/ # Integration contracts
|
|
137
|
+
│ │ └── principles/ # Architecture principles
|
|
138
|
+
│ │
|
|
139
|
+
│ ├── auth/ # Auth scope artifacts
|
|
140
|
+
│ │ ├── planning-artifacts/
|
|
141
|
+
│ │ ├── implementation-artifacts/
|
|
142
|
+
│ │ └── tests/
|
|
143
|
+
│ │
|
|
144
|
+
│ └── payments/ # Payments scope artifacts
|
|
145
|
+
│ └── ...
|
|
146
|
+
│
|
|
147
|
+
└── .bmad-scope # Session-sticky active scope (gitignored)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Access Model
|
|
151
|
+
|
|
152
|
+
Scopes follow a "read-any, write-own" isolation model:
|
|
153
|
+
|
|
154
|
+
| Operation | Own Scope | Other Scopes | \_shared/ |
|
|
155
|
+
| --------- | --------- | ------------ | ----------- |
|
|
156
|
+
| **Read** | Allowed | Allowed | Allowed |
|
|
157
|
+
| **Write** | Allowed | Blocked | via sync-up |
|
|
158
|
+
|
|
159
|
+
### Workflow Integration
|
|
160
|
+
|
|
161
|
+
Workflows (run via agent menus like `CP` for Create PRD, `DS` for Dev Story) automatically detect and use scope context. Resolution order:
|
|
162
|
+
|
|
163
|
+
1. Session context from `.bmad-scope` file (set via `scope set`)
|
|
164
|
+
2. `BMAD_SCOPE` environment variable
|
|
165
|
+
3. Prompt user to select or create scope
|
|
166
|
+
|
|
167
|
+
**Setting your active scope:**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Set scope for your terminal session
|
|
171
|
+
npx bmad-fh scope set auth
|
|
172
|
+
|
|
173
|
+
# Or use environment variable (useful for CI/CD)
|
|
174
|
+
export BMAD_SCOPE=auth
|
|
85
175
|
```
|
|
86
176
|
|
|
87
|
-
**
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
177
|
+
**Scope-aware path variables in workflows:**
|
|
178
|
+
|
|
179
|
+
- `{scope}` → Scope ID (e.g., "auth")
|
|
180
|
+
- `{scope_path}` → `_bmad-output/auth`
|
|
181
|
+
- `{scope_planning}` → `_bmad-output/auth/planning-artifacts`
|
|
182
|
+
- `{scope_implementation}` → `_bmad-output/auth/implementation-artifacts`
|
|
183
|
+
- `{scope_tests}` → `_bmad-output/auth/tests`
|
|
184
|
+
|
|
185
|
+
### Getting Help
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Show comprehensive help for all scope commands
|
|
189
|
+
npx bmad-fh scope help
|
|
190
|
+
|
|
191
|
+
# Get detailed help for a specific command
|
|
192
|
+
npx bmad-fh scope help create
|
|
193
|
+
npx bmad-fh scope help sync-up
|
|
194
|
+
```
|
|
92
195
|
|
|
93
|
-
See [Multi-Scope Guide](docs/multi-scope-guide.md) for
|
|
196
|
+
See [Multi-Scope Guide](docs/multi-scope-guide.md) for complete documentation.
|
|
94
197
|
|
|
95
198
|
## Community
|
|
96
199
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-fh",
|
|
4
|
-
"version": "6.0.0-alpha.23.
|
|
4
|
+
"version": "6.0.0-alpha.23.bed978b2",
|
|
5
5
|
"description": "Breakthrough Method of Agile AI-driven Development",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agile",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"lint:fix": "eslint . --ext .js,.cjs,.mjs,.yaml --fix",
|
|
40
40
|
"lint:md": "markdownlint-cli2 \"**/*.md\"",
|
|
41
41
|
"prepare": "husky",
|
|
42
|
-
"publish
|
|
42
|
+
"publish": "npm publish",
|
|
43
43
|
"rebundle": "node tools/cli/bundlers/bundle-web.js rebundle",
|
|
44
44
|
"release:major": "gh workflow run \"Manual Release\" -f version_bump=major",
|
|
45
45
|
"release:minor": "gh workflow run \"Manual Release\" -f version_bump=minor",
|
|
@@ -2,6 +2,7 @@ const path = require('node:path');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const yaml = require('yaml');
|
|
4
4
|
const { ScopeValidator } = require('./scope-validator');
|
|
5
|
+
const { ScopeInitializer } = require('./scope-initializer');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Manages scope lifecycle and CRUD operations
|
|
@@ -25,6 +26,7 @@ class ScopeManager {
|
|
|
25
26
|
this.scopesFilePath = options.scopesFilePath || path.join(this.configPath, 'scopes.yaml');
|
|
26
27
|
|
|
27
28
|
this.validator = new ScopeValidator();
|
|
29
|
+
this.initializer = new ScopeInitializer({ projectRoot: this.projectRoot });
|
|
28
30
|
this._config = null; // Cached configuration
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -38,6 +40,7 @@ class ScopeManager {
|
|
|
38
40
|
this.configPath = path.join(this.bmadPath, '_config');
|
|
39
41
|
this.scopesFilePath = path.join(this.configPath, 'scopes.yaml');
|
|
40
42
|
this._config = null; // Clear cache
|
|
43
|
+
this.initializer.setProjectRoot(projectRoot);
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
/**
|
|
@@ -59,6 +62,9 @@ class ScopeManager {
|
|
|
59
62
|
await this.saveConfig(defaultConfig);
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
// Initialize scope system directories (_shared, _events)
|
|
66
|
+
await this.initializer.initializeScopeSystem();
|
|
67
|
+
|
|
62
68
|
// Load and validate configuration
|
|
63
69
|
const config = await this.loadConfig();
|
|
64
70
|
return config !== null;
|
|
@@ -239,6 +245,9 @@ class ScopeManager {
|
|
|
239
245
|
// Save configuration
|
|
240
246
|
await this.saveConfig(config);
|
|
241
247
|
|
|
248
|
+
// Create scope directory structure
|
|
249
|
+
await this.initializer.initializeScope(scopeId, options);
|
|
250
|
+
|
|
242
251
|
return scope;
|
|
243
252
|
} catch (error) {
|
|
244
253
|
throw new Error(`Failed to create scope '${scopeId}': ${error.message}`);
|
|
@@ -311,7 +320,7 @@ class ScopeManager {
|
|
|
311
320
|
}
|
|
312
321
|
|
|
313
322
|
// Check if other scopes depend on this one
|
|
314
|
-
const dependentScopes = this.
|
|
323
|
+
const dependentScopes = this.findDependentScopesSync(scopeId, config.scopes);
|
|
315
324
|
if (dependentScopes.length > 0 && !options.force) {
|
|
316
325
|
throw new Error(
|
|
317
326
|
`Cannot remove scope '${scopeId}'. The following scopes depend on it: ${dependentScopes.join(', ')}. Use force option to remove anyway.`,
|
|
@@ -396,7 +405,7 @@ class ScopeManager {
|
|
|
396
405
|
const tree = {
|
|
397
406
|
scope: scopeId,
|
|
398
407
|
dependencies: [],
|
|
399
|
-
dependents: this.
|
|
408
|
+
dependents: this.findDependentScopesSync(scopeId, config.scopes),
|
|
400
409
|
};
|
|
401
410
|
|
|
402
411
|
// Build dependency tree recursively
|
|
@@ -422,10 +431,34 @@ class ScopeManager {
|
|
|
422
431
|
/**
|
|
423
432
|
* Find scopes that depend on a given scope
|
|
424
433
|
* @param {string} scopeId - The scope ID
|
|
425
|
-
* @param {object} allScopes - All scopes object
|
|
434
|
+
* @param {object} allScopes - All scopes object (optional, will load if not provided)
|
|
435
|
+
* @returns {Promise<string[]>|string[]} Array of dependent scope IDs
|
|
436
|
+
*/
|
|
437
|
+
async findDependentScopes(scopeId, allScopes = null) {
|
|
438
|
+
// If allScopes not provided, load from config
|
|
439
|
+
if (!allScopes) {
|
|
440
|
+
const config = await this.loadConfig();
|
|
441
|
+
allScopes = config.scopes || {};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const dependents = [];
|
|
445
|
+
|
|
446
|
+
for (const [sid, scope] of Object.entries(allScopes)) {
|
|
447
|
+
if (scope.dependencies && scope.dependencies.includes(scopeId)) {
|
|
448
|
+
dependents.push(sid);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return dependents;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Find scopes that depend on a given scope (synchronous version)
|
|
457
|
+
* @param {string} scopeId - The scope ID
|
|
458
|
+
* @param {object} allScopes - All scopes object (required)
|
|
426
459
|
* @returns {string[]} Array of dependent scope IDs
|
|
427
460
|
*/
|
|
428
|
-
|
|
461
|
+
findDependentScopesSync(scopeId, allScopes) {
|
|
429
462
|
const dependents = [];
|
|
430
463
|
|
|
431
464
|
for (const [sid, scope] of Object.entries(allScopes)) {
|