bmad-plus 0.23.0 → 0.23.1
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/CHANGELOG.md +40 -0
- package/README.md +34 -24
- package/osint-agent-package/agents/osint-investigator.md +3 -3
- package/osint-agent-package/skills/bmad-osint-investigate/osint/SKILL.md +51 -51
- package/osint-agent-package/skills/bmad-osint-investigate/osint/references/content-extraction.md +7 -7
- package/osint-agent-package/skills/bmad-osint-investigate/osint/references/platforms.md +2 -2
- package/osint-agent-package/skills/bmad-osint-investigate/osint/references/tools.md +31 -41
- package/package.json +21 -5
- package/readme-international/README.de.md +34 -24
- package/readme-international/README.es.md +35 -25
- package/readme-international/README.fr.md +34 -24
- package/src/bmad-plus/agents/agent-maker/SKILL.md +39 -14
- package/src/bmad-plus/module.yaml +5 -4
- package/src/bmad-plus/packs/pack-animated/animated-website-agent.md +40 -14
- package/src/bmad-plus/packs/pack-animated/templates/animated-website-workflow.md +15 -12
- package/src/bmad-plus/packs/pack-backup/backup-agent.md +2 -1
- package/src/bmad-plus/packs/pack-backup/templates/backup-workflow.md +2 -0
- package/src/bmad-plus/packs/pack-memory/zecher-agent.md +1 -1
- package/src/bmad-plus/packs/pack-shield/README.md +1 -1
- package/src/bmad-plus/packs/pack-shield/SKILL.md +3 -3
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/pci-dss-agent.md +1 -1
- package/src/bmad-plus/packs/pack-shield/shield-orchestrator.md +2 -2
- package/src/bmad-plus/skills/bmad-plus-parallel/SKILL.md +1 -1
- package/src/bmad-plus/skills/bmad-plus-swarm/SKILL.md +1 -1
- package/tools/build/adapters.config.js +1 -1
- package/tools/build/generate-adapters.js +1 -1
- package/tools/cli/commands/install.js +18 -11
- package/tools/cli/commands/nexus.js +2 -1
- package/tools/cli/commands/review.js +1 -1
- package/tools/cli/commands/update.js +30 -1
- package/tools/cli/i18n.js +30 -30
- package/tools/cli/lib/packs.js +6 -6
- package/tools/cli/lib/review.js +2 -1
- package/tools/cli/lib/update-dispatch.js +10 -2
- package/tools/cli/lib/update-transaction.js +1 -2
|
@@ -135,20 +135,33 @@ pack: {pack-name}
|
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
#### 3. `pack-definition.yaml`
|
|
138
|
-
A ready-to-merge snippet for `
|
|
138
|
+
A ready-to-merge snippet for the `packs:` mapping of `registry.yaml`, the single source of truth
|
|
139
|
+
for packs and agents. `order` must be an integer no other pack uses, `cli.icon` a non-empty
|
|
140
|
+
string, and `summary` must not hard-code a count of agents, skills or workflows (the build
|
|
141
|
+
derives those):
|
|
139
142
|
|
|
140
143
|
```yaml
|
|
141
144
|
{pack-name}:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
order: {next free integer}
|
|
146
|
+
display_name: "{Pack Display Name}"
|
|
147
|
+
icon_emoji: "{icon}"
|
|
148
|
+
cli: { name: "{Short CLI name}", icon: "{one letter}", desc: "{CLI description}" }
|
|
145
149
|
required: false
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
runtime: [node]
|
|
151
|
+
summary: "{one sentence, no counts}"
|
|
152
|
+
agents: [agent-{name}]
|
|
153
|
+
personas:
|
|
154
|
+
- { id: agent-{name}, name: {PersonaName}, role: {Title}, description: "{description}" }
|
|
148
155
|
skills: []
|
|
149
|
-
|
|
156
|
+
install_layout: loose
|
|
157
|
+
compliance_tags: []
|
|
158
|
+
required_keys: [] # only if API keys are needed
|
|
150
159
|
```
|
|
151
160
|
|
|
161
|
+
`install_layout: loose` copies the agent directory `agents/agent-{name}/` into the project. A
|
|
162
|
+
pack that ships its files in one folder uses `install_layout: packaged` with `pack_dir`,
|
|
163
|
+
`pack_src_dir` and `doctor.pack_agents` instead: see the existing `backup` entry.
|
|
164
|
+
|
|
152
165
|
#### 4. `INTEGRATION.md`
|
|
153
166
|
Instructions for integrating the agent into BMAD+:
|
|
154
167
|
|
|
@@ -158,14 +171,26 @@ Instructions for integrating the agent into BMAD+:
|
|
|
158
171
|
## Files to copy
|
|
159
172
|
- `agents/agent-{name}/` → `src/bmad-plus/agents/agent-{name}/`
|
|
160
173
|
|
|
161
|
-
##
|
|
162
|
-
|
|
174
|
+
## Register the pack (registry first)
|
|
175
|
+
`registry.yaml` is the single source of truth. Never edit the files generated from it
|
|
176
|
+
(`tools/cli/lib/packs.js`, the pack metadata of `src/bmad-plus/module.yaml`, `AGENTS.md` and the
|
|
177
|
+
other adapters).
|
|
178
|
+
- New pack: add the entry from `pack-definition.yaml` under `packs:` in `registry.yaml`.
|
|
179
|
+
- New agent in an existing pack: add its id to that pack's `agents:` list and a line to its
|
|
180
|
+
`personas:` list (and to `doctor.pack_agents` when the pack uses the packaged layout).
|
|
163
181
|
|
|
164
182
|
## module-help.csv update
|
|
165
|
-
Add
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
183
|
+
This file is maintained by hand. Add to `src/bmad-plus/module-help.csv`:
|
|
184
|
+
bmad-plus-agent-{name},"{help text}"
|
|
185
|
+
|
|
186
|
+
## Regenerate and check
|
|
187
|
+
From the repository root, in this order:
|
|
188
|
+
1. `npm run build` regenerates `tools/cli/lib/packs.js` and `src/bmad-plus/module.yaml`.
|
|
189
|
+
2. `node tools/build/generate-adapters.js --adopt` regenerates `AGENTS.md` and the tool adapters
|
|
190
|
+
(`CLAUDE.md`, `GEMINI.md`, ...) with the new roster.
|
|
191
|
+
3. `npm run build:check`, `node tools/build/generate-adapters.js --check --adopt` and
|
|
192
|
+
`npm run check:counts` must report no drift; `npm run check:triggers` too if you added
|
|
193
|
+
role triggers to `src/bmad-plus/data/role-triggers.yaml`.
|
|
169
194
|
|
|
170
195
|
## Test
|
|
171
196
|
Run `npx bmad-plus install --packs {pack-name}` in a test project.
|
|
@@ -175,7 +200,7 @@ Run `npx bmad-plus install --packs {pack-name}` in a test project.
|
|
|
175
200
|
After generating, run a self-check:
|
|
176
201
|
- [ ] SKILL.md follows v6 format
|
|
177
202
|
- [ ] Manifest has all required fields
|
|
178
|
-
- [ ] Pack definition is valid
|
|
203
|
+
- [ ] Pack definition is a valid `registry.yaml` pack entry (unique `order`, `cli`, `personas`)
|
|
179
204
|
- [ ] Capabilities have unique 2-letter codes
|
|
180
205
|
- [ ] Integration guide is complete
|
|
181
206
|
|
|
@@ -22,7 +22,7 @@ install_packs:
|
|
|
22
22
|
- value: maker
|
|
23
23
|
label: 🧬 Agent Creator — Design, build, validate, and package new BMAD+-compatible agents.
|
|
24
24
|
- value: shield
|
|
25
|
-
label: 🛡️ Shield — GRC Compliance — 27 compliance agents + 11 workflows across
|
|
25
|
+
label: 🛡️ Shield — GRC Compliance — 27 compliance agents + 11 workflows across 27+ frameworks.
|
|
26
26
|
- value: seo
|
|
27
27
|
label: 🔍 SEO Audit 360 — 3 agents (Scout, Chief, Judge) + 6-phase audit + PageSpeed loop.
|
|
28
28
|
- value: memory
|
|
@@ -136,13 +136,14 @@ packs:
|
|
|
136
136
|
- agent-shadow
|
|
137
137
|
skills: []
|
|
138
138
|
external_package: osint-agent-package
|
|
139
|
-
required_keys:
|
|
140
|
-
- APIFY_API_TOKEN
|
|
141
139
|
optional_keys:
|
|
140
|
+
- APIFY_API_TOKEN
|
|
142
141
|
- PERPLEXITY_API_KEY
|
|
143
142
|
- EXA_API_KEY
|
|
144
143
|
- TAVILY_API_KEY
|
|
145
144
|
- JINA_API_KEY
|
|
145
|
+
- PARALLEL_API_KEY
|
|
146
|
+
- BRIGHTDATA_MCP_URL
|
|
146
147
|
maker:
|
|
147
148
|
name: Agent Creator
|
|
148
149
|
icon: 🧬
|
|
@@ -155,7 +156,7 @@ packs:
|
|
|
155
156
|
shield:
|
|
156
157
|
name: Shield — GRC Compliance
|
|
157
158
|
icon: 🛡️
|
|
158
|
-
description: 27 compliance agents + 11 workflows across
|
|
159
|
+
description: 27 compliance agents + 11 workflows across 27+ frameworks.
|
|
159
160
|
required: false
|
|
160
161
|
agents:
|
|
161
162
|
- shield-orchestrator
|
|
@@ -7,10 +7,12 @@ Tu es un expert en création de sites web animés de luxe. Tu convertis des vid
|
|
|
7
7
|
Déclenché par les requêtes contenant : "animated website", "scroll animation", "video to website", "Apple-style page", "scroll-driven site", "frame animation", "convert video to website", "luxury website from video", "site animé", "animation scroll".
|
|
8
8
|
|
|
9
9
|
## Pré-requis
|
|
10
|
-
- FFmpeg + FFprobe installés
|
|
11
|
-
- Python 3
|
|
10
|
+
- FFmpeg + FFprobe installés, avec l'encodeur `libwebp` (vérification : `ffmpeg -hide_banner -encoders`, la liste doit contenir `libwebp`)
|
|
11
|
+
- Python 3 (uniquement pour l'aperçu local de l'étape 5 ; tout autre serveur de fichiers statiques convient)
|
|
12
12
|
- Fichier vidéo MP4 source
|
|
13
13
|
|
|
14
|
+
Ce pack ne livre aucun script d'extraction : les frames s'extraient avec les commandes FFmpeg de l'étape 2.
|
|
15
|
+
|
|
14
16
|
---
|
|
15
17
|
|
|
16
18
|
## Processus Complet
|
|
@@ -44,24 +46,38 @@ Recommander le nombre de frames :
|
|
|
44
46
|
|
|
45
47
|
### Étape 2 — Extraire et optimiser les frames
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
Deux commandes FFmpeg suffisent (aucun script à installer). Soit `D` la durée en secondes relevée à l'étape 1 et `N` le nombre de frames confirmé par l'utilisateur ; le filtre `fps=N/D` échantillonne la vidéo à intervalles réguliers et `-frames:v N` plafonne la sortie à `N` images. Créer d'abord les dossiers de sortie, FFmpeg ne les crée pas.
|
|
50
|
+
|
|
51
|
+
Durée de la vidéo, si elle n'a pas été relevée :
|
|
52
|
+
```bash
|
|
53
|
+
ffprobe -v error -show_entries format=duration -of csv=p=0 "/path/to/video.mp4"
|
|
54
|
+
```
|
|
48
55
|
|
|
49
|
-
**Windows :**
|
|
56
|
+
**Windows (PowerShell) :**
|
|
50
57
|
```powershell
|
|
51
|
-
|
|
58
|
+
New-Item -ItemType Directory -Force "output/frames/desktop", "output/frames/mobile"
|
|
59
|
+
ffmpeg -i "C:/path/to/video.mp4" -vf "fps=120/12.4,scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080" -c:v libwebp -quality 80 -compression_level 6 -frames:v 120 -start_number 0 "output/frames/desktop/frame-%04d.webp"
|
|
60
|
+
ffmpeg -i "C:/path/to/video.mp4" -vf "fps=120/12.4,scale=960:540:force_original_aspect_ratio=increase,crop=960:540" -c:v libwebp -quality 80 -compression_level 6 -frames:v 120 -start_number 0 "output/frames/mobile/frame-%04d.webp"
|
|
52
61
|
```
|
|
53
62
|
|
|
54
63
|
**Mac/Linux :**
|
|
55
64
|
```bash
|
|
56
|
-
|
|
65
|
+
mkdir -p output/frames/desktop output/frames/mobile
|
|
66
|
+
ffmpeg -i "/path/to/video.mp4" -vf "fps=120/12.4,scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080" -c:v libwebp -quality 80 -compression_level 6 -frames:v 120 -start_number 0 "output/frames/desktop/frame-%04d.webp"
|
|
67
|
+
ffmpeg -i "/path/to/video.mp4" -vf "fps=120/12.4,scale=960:540:force_original_aspect_ratio=increase,crop=960:540" -c:v libwebp -quality 80 -compression_level 6 -frames:v 120 -start_number 0 "output/frames/mobile/frame-%04d.webp"
|
|
57
68
|
```
|
|
58
69
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- `frames/
|
|
70
|
+
Les exemples supposent `N = 120` et `D = 12.4` : remplacer `120/12.4` et `-frames:v 120` par les valeurs réelles. `-quality 80` est la qualité WebP (1-100).
|
|
71
|
+
|
|
72
|
+
Résultat :
|
|
73
|
+
- `frames/desktop/` — WebP 1920x1080, `frame-0000.webp` à `frame-<N-1>.webp`
|
|
74
|
+
- `frames/mobile/` — WebP 960x540, même numérotation
|
|
75
|
+
|
|
76
|
+
`scale=…:force_original_aspect_ratio=increase,crop=…` remplit le cadre 16:9 et rogne les bords d'une source qui n'est pas en 16:9 ; pour une source verticale, demander à l'utilisateur quel cadrage il veut avant d'extraire.
|
|
63
77
|
|
|
64
|
-
|
|
78
|
+
Écrire ensuite `frames/manifest.json` avec le nombre de frames et le motif de nom (par exemple `{"count":120,"pattern":"frame-%04d.webp","desktop":"1920x1080","mobile":"960x540"}`) : c'est la valeur `FRAME_COUNT` du site généré. Vérifier que le nombre de fichiers de chaque dossier est égal à `N`.
|
|
79
|
+
|
|
80
|
+
**Budget payload :** Desktop < 10MB, Mobile < 5MB. Mesurer la taille des deux dossiers (`du -sh output/frames/desktop output/frames/mobile`, ou la somme des tailles de fichiers sous PowerShell) avant de continuer.
|
|
65
81
|
|
|
66
82
|
### Étape 3 — Contenu des 6 sections
|
|
67
83
|
|
|
@@ -126,6 +142,16 @@ python3 -m http.server 8080
|
|
|
126
142
|
- **Labels :** DM Sans, 8-9px, weight 500, uppercase, letter-spacing 0.25-0.35em
|
|
127
143
|
- **Hero :** `clamp(42px, 5.5vw, 76px)` — grand mais light
|
|
128
144
|
|
|
145
|
+
#### Chargement des polices : un choix à faire avec l'utilisateur
|
|
146
|
+
|
|
147
|
+
Playfair Display et DM Sans ne sont pas embarquées par BMAD+. Avant de générer le site, demander laquelle de ces options l'utilisateur veut (la première si aucune réponse) :
|
|
148
|
+
|
|
149
|
+
1. **Polices système (défaut).** Ne rien charger : les piles de `--heading` et `--body` ci-dessus retombent sur Georgia et sur la police système. Aucune requête externe.
|
|
150
|
+
2. **Polices auto-hébergées.** L'utilisateur fournit les fichiers `.woff2` (Playfair Display et DM Sans sont sous licence SIL Open Font ; il vérifie la licence de toute autre police), à placer dans le dossier du site et à déclarer avec `@font-face`. Aucune requête vers un tiers.
|
|
151
|
+
3. **Google Fonts.** À n'utiliser que sur demande explicite, après avoir prévenu l'utilisateur que le navigateur de **chaque visiteur du site généré** contactera fonts.googleapis.com et fonts.gstatic.com (son adresse IP est donc transmise à Google) et que cela peut exiger une mention dans la politique de confidentialité du site. Cette requête est une propriété du site généré, pas de BMAD+ : BMAD+ lui-même n'envoie rien à Google.
|
|
152
|
+
|
|
153
|
+
Balise à insérer uniquement pour l'option 3 :
|
|
154
|
+
|
|
129
155
|
```html
|
|
130
156
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&family=Playfair+Display:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400&display=swap" rel="stylesheet">
|
|
131
157
|
```
|
|
@@ -213,7 +239,7 @@ Fichier HTML unique. Ordre structurel :
|
|
|
213
239
|
|
|
214
240
|
```
|
|
215
241
|
HTML :
|
|
216
|
-
1. Google Fonts
|
|
242
|
+
1. Chargement des polices (option choisie : système, auto-hébergée ou lien Google Fonts)
|
|
217
243
|
2. <style> — tout le CSS
|
|
218
244
|
3. Cursor custom divs (#cursor-dot, #cursor-ring)
|
|
219
245
|
4. Film grain overlay
|
|
@@ -316,8 +342,8 @@ Avant livraison, vérifier :
|
|
|
316
342
|
| Problème | Solution |
|
|
317
343
|
|---------|---------|
|
|
318
344
|
| FFmpeg non trouvé | `winget install FFmpeg` (Win), `brew install ffmpeg` (Mac) |
|
|
319
|
-
| Pas de libwebp |
|
|
320
|
-
| Frames trop lourdes (>10MB) |
|
|
345
|
+
| Pas de libwebp | Installer une build de FFmpeg qui inclut `libwebp` (`ffmpeg -hide_banner -encoders` doit le lister) |
|
|
346
|
+
| Frames trop lourdes (>10MB) | `-quality 60` ou `-frames:v 90` (avec `fps=90/D`) |
|
|
321
347
|
| Animation saccadée | Réduire frames, vérifier DPR cap à 2, réduire particules |
|
|
322
348
|
| Flash blanc entre frames | Vérifier extraction, fallback nearest-frame |
|
|
323
349
|
| Canvas blanc sur mobile | Vérifier existence des frames mobile, chemin FRAME_DIR |
|
|
@@ -8,32 +8,33 @@ Converts an MP4 video into a luxury scroll-driven animated website with canvas f
|
|
|
8
8
|
|
|
9
9
|
## Pre-requisites
|
|
10
10
|
|
|
11
|
-
1. FFmpeg installed (`winget install FFmpeg` on Windows, `brew install ffmpeg` on Mac)
|
|
12
|
-
2. Python 3 installed
|
|
11
|
+
1. FFmpeg installed, with the `libwebp` encoder (`winget install FFmpeg` on Windows, `brew install ffmpeg` on Mac; `ffmpeg -hide_banner -encoders` must list `libwebp`)
|
|
12
|
+
2. Python 3 installed (only for the local preview in step 6; any static file server works)
|
|
13
13
|
3. Source MP4 video file
|
|
14
14
|
|
|
15
|
+
This pack ships no extraction script: the frames are extracted with the FFmpeg commands of step 3.
|
|
16
|
+
|
|
15
17
|
## Steps
|
|
16
18
|
|
|
17
19
|
1. Ask the user for:
|
|
18
20
|
- Path to the MP4 video file
|
|
19
21
|
- Website concept (product, real estate, portfolio, etc.)
|
|
20
22
|
- Optional: brand colors, section content, target frame count
|
|
23
|
+
- How fonts are loaded in the generated site (see step 5)
|
|
21
24
|
|
|
22
25
|
2. Analyze the video:
|
|
23
26
|
```bash
|
|
24
27
|
ffprobe -v quiet -print_format json -show_format -show_streams "VIDEO_PATH"
|
|
25
28
|
```
|
|
26
29
|
|
|
27
|
-
3. Extract frames
|
|
30
|
+
3. Extract the frames with FFmpeg. `DURATION` is the video length in seconds from step 2; create the two output folders first (`mkdir -p OUTPUT_DIR/frames/desktop OUTPUT_DIR/frames/mobile`):
|
|
28
31
|
```bash
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
--output "OUTPUT_DIR/frames" \
|
|
32
|
-
--frames FRAME_COUNT \
|
|
33
|
-
--quality 80
|
|
32
|
+
ffmpeg -i "VIDEO_PATH" -vf "fps=FRAME_COUNT/DURATION,scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080" -c:v libwebp -quality 80 -compression_level 6 -frames:v FRAME_COUNT -start_number 0 "OUTPUT_DIR/frames/desktop/frame-%04d.webp"
|
|
33
|
+
ffmpeg -i "VIDEO_PATH" -vf "fps=FRAME_COUNT/DURATION,scale=960:540:force_original_aspect_ratio=increase,crop=960:540" -c:v libwebp -quality 80 -compression_level 6 -frames:v FRAME_COUNT -start_number 0 "OUTPUT_DIR/frames/mobile/frame-%04d.webp"
|
|
34
34
|
```
|
|
35
|
+
Then write `OUTPUT_DIR/frames/manifest.json` with the frame count and the file name pattern, and check that each folder holds `FRAME_COUNT` files and stays under the payload budget (desktop under 10 MB, mobile under 5 MB).
|
|
35
36
|
|
|
36
|
-
4. Generate the complete index.html following the design system in `
|
|
37
|
+
4. Generate the complete index.html following the design system in `animated-website-agent.md` (the agent file of this pack):
|
|
37
38
|
- Canvas frame-by-frame scroll animation
|
|
38
39
|
- Scroll dwell engine with Gaussian density
|
|
39
40
|
- 6 overlay sections (Hero, Vision, Details, Grid, Context, CTA)
|
|
@@ -42,14 +43,16 @@ python3 scripts/extract_frames.py \
|
|
|
42
43
|
- Custom cursor, chapter markers, branded loader
|
|
43
44
|
- Gallery with parallax
|
|
44
45
|
|
|
45
|
-
5.
|
|
46
|
+
5. Fonts. Use system fonts by default. Self-hosted `.woff2` files are the alternative that sends nothing to a third party. Use Google Fonts only when the user explicitly asks for it, after telling them that each visitor's browser will then contact Google's font servers (this concerns the generated site, not BMAD+).
|
|
47
|
+
|
|
48
|
+
6. Serve and preview:
|
|
46
49
|
```bash
|
|
47
50
|
cd OUTPUT_DIR
|
|
48
51
|
python3 -m http.server 8080
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
7. Iterate based on user feedback (scroll speed, colors, content, etc.)
|
|
52
55
|
|
|
53
56
|
## Reference
|
|
54
57
|
|
|
55
|
-
See `
|
|
58
|
+
See `animated-website-agent.md` for the complete design system, code architecture, and quality checklist.
|
|
@@ -35,7 +35,8 @@ PROJECT_NAME=$(basename "$PROJECT_ROOT")
|
|
|
35
35
|
mkdir -p "$PROJECT_ROOT/backups"
|
|
36
36
|
cd "$PROJECT_ROOT" && zip -r "backups/${PROJECT_NAME}_backup_$TIMESTAMP.zip" . \
|
|
37
37
|
-x "backups/*" "node_modules/*" ".git/*" "vendor/*" "__pycache__/*" "*.backup_*"
|
|
38
|
-
|
|
38
|
+
SIZE=$(du -h "backups/${PROJECT_NAME}_backup_$TIMESTAMP.zip" | cut -f1)
|
|
39
|
+
echo "✅ Backup: ${PROJECT_NAME}_backup_$TIMESTAMP.zip ($SIZE)"
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
### 2. `/backup-list` — Lister les backups
|
|
@@ -40,6 +40,8 @@ PROJECT_NAME=$(basename "$PROJECT_ROOT")
|
|
|
40
40
|
mkdir -p "$PROJECT_ROOT/backups"
|
|
41
41
|
cd "$PROJECT_ROOT" && zip -r "backups/${PROJECT_NAME}_backup_$TIMESTAMP.zip" . \
|
|
42
42
|
-x "backups/*" "node_modules/*" ".git/*" "vendor/*" "__pycache__/*" "*.backup_*"
|
|
43
|
+
SIZE=$(du -h "backups/${PROJECT_NAME}_backup_$TIMESTAMP.zip" | cut -f1)
|
|
44
|
+
echo "Backup: ${PROJECT_NAME}_backup_$TIMESTAMP.zip ($SIZE)"
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
2. Confirm the backup was created and report the file name and size.
|
|
@@ -101,7 +101,7 @@ You are NOT an orchestrator. You are a **utility agent** — called upon by othe
|
|
|
101
101
|
Recursively walk the target path
|
|
102
102
|
Identify project roots by marker files (package.json, .git, Cargo.toml, etc.)
|
|
103
103
|
Skip: node_modules, .git internals, vendor, __pycache__, dist, build
|
|
104
|
-
Depth limit: configurable (default
|
|
104
|
+
Depth limit: configurable with `bmad-plus scan --depth <n>` (default 4 levels below the scanned directory)
|
|
105
105
|
</step>
|
|
106
106
|
<step n="2" goal="Analyze each project">
|
|
107
107
|
For each discovered project root:
|
|
@@ -41,7 +41,7 @@ Pack Shield transforms BMAD+ into a comprehensive GRC (Governance, Risk & Compli
|
|
|
41
41
|
| Agent | Framework | Jurisdiction |
|
|
42
42
|
|-------|-----------|-------------|
|
|
43
43
|
| `soc2-agent` | SOC 2 Type I/II | US/Global |
|
|
44
|
-
| `pci-dss-agent` | PCI DSS v4.0 | International |
|
|
44
|
+
| `pci-dss-agent` | PCI DSS v4.0.1 | International |
|
|
45
45
|
| `hipaa-agent` | HIPAA | US Healthcare |
|
|
46
46
|
| `swift-csp-agent` | SWIFT CSP | Intl. Banking |
|
|
47
47
|
| `dora-agent` | DORA | EU Financial |
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
Shield transforms BMAD+ into a comprehensive GRC (Governance, Risk & Compliance) assistant. It serves as an intelligent orchestrator for 27 compliance agents across 6 categories, plus 11 GDPR & AI Act workflows, covering
|
|
11
|
+
Shield transforms BMAD+ into a comprehensive GRC (Governance, Risk & Compliance) assistant. It serves as an intelligent orchestrator for 27 compliance agents across 6 categories, plus 11 GDPR & AI Act workflows, covering 27 regulatory frameworks. Route requests to the appropriate specialist agent, combine insights for cross-framework analysis, and provide consolidated compliance reports.
|
|
12
12
|
|
|
13
13
|
## Capabilities
|
|
14
14
|
|
|
@@ -29,7 +29,7 @@ Shield transforms BMAD+ into a comprehensive GRC (Governance, Risk & Compliance)
|
|
|
29
29
|
|
|
30
30
|
### Industry Compliance (6 frameworks)
|
|
31
31
|
- **SOC 2 Type I/II** — Service Organization Controls
|
|
32
|
-
- **PCI DSS v4.0** — Payment Card Industry
|
|
32
|
+
- **PCI DSS v4.0.1** — Payment Card Industry
|
|
33
33
|
- **HIPAA** — Healthcare Privacy & Security
|
|
34
34
|
- **SWIFT CSP** — Banking Security
|
|
35
35
|
- **DORA** — EU Digital Operational Resilience
|
|
@@ -66,7 +66,7 @@ Shield transforms BMAD+ into a comprehensive GRC (Governance, Risk & Compliance)
|
|
|
66
66
|
To use Shield, include this pack in your BMAD+ installation:
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
npx bmad-plus install --
|
|
69
|
+
npx bmad-plus install --packs shield
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
Then invoke the orchestrator from any conversation:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# PCI DSS Compliance Agent
|
|
2
2
|
|
|
3
3
|
> **Pack:** Shield (GRC Audit) -- Industry Compliance
|
|
4
|
-
> **Framework:** PCI DSS v4.0
|
|
4
|
+
> **Framework:** PCI DSS v4.0.1
|
|
5
5
|
> **Version:** 1.0.0
|
|
6
6
|
> **Based on:** Claude Skills for GRC by Hemant Naik (Sushegaad) -- MIT License
|
|
7
7
|
> **Upstream:** https://github.com/Sushegaad/Claude-Skills-Governance-Risk-and-Compliance
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
## Persona
|
|
13
13
|
|
|
14
|
-
You are **Shield**, an expert GRC (Governance, Risk & Compliance) orchestrator. You serve as the intelligent entry point for regulatory and compliance queries. You understand
|
|
14
|
+
You are **Shield**, an expert GRC (Governance, Risk & Compliance) orchestrator. You serve as the intelligent entry point for regulatory and compliance queries. You understand 27 compliance frameworks and 11 workflow agents. You route requests to the appropriate specialist agent, combine insights from multiple agents for cross-framework analysis, and provide consolidated compliance reports.
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -40,7 +40,7 @@ You are **Shield**, an expert GRC (Governance, Risk & Compliance) orchestrator.
|
|
|
40
40
|
| Agent | Framework | Jurisdiction |
|
|
41
41
|
|-------|-----------|-------------|
|
|
42
42
|
| `soc2-agent` | SOC 2 Type I/II | US (global use) |
|
|
43
|
-
| `pci-dss-agent` | PCI DSS v4.0 | International |
|
|
43
|
+
| `pci-dss-agent` | PCI DSS v4.0.1 | International |
|
|
44
44
|
| `hipaa-agent` | HIPAA Privacy & Security | US Healthcare |
|
|
45
45
|
| `swift-csp-agent` | SWIFT CSP | International Banking |
|
|
46
46
|
| `dora-agent` | DORA (EU 2022/2554) | EU Financial |
|
|
@@ -109,7 +109,7 @@ This skill is automatically invoked by the Autopilot when `{parallel_execution}`
|
|
|
109
109
|
## Swarms
|
|
110
110
|
|
|
111
111
|
Parallel stories share one goal and differ in content; a **swarm** repeats one kind of work
|
|
112
|
-
across many units.
|
|
112
|
+
across many units. Three kinds, one runtime (`bmad-plus swarm`), one moderator skill
|
|
113
113
|
(`bmad-plus-swarm`):
|
|
114
114
|
|
|
115
115
|
| Kind | Units | Substrate |
|
|
@@ -22,7 +22,7 @@ definition + profile|list|units ─► init ─► cards.json ─► briefs ─
|
|
|
22
22
|
|
|
23
23
|
Read `ref/definition.md` for the four file contracts with one example each.
|
|
24
24
|
|
|
25
|
-
## The
|
|
25
|
+
## The three kinds
|
|
26
26
|
|
|
27
27
|
| Kind | Units come from | Typical use | Tally |
|
|
28
28
|
|---|---|---|---|
|
|
@@ -72,7 +72,7 @@ const UPDATE_INSTRUCTIONS = [
|
|
|
72
72
|
'## Framework updates',
|
|
73
73
|
'',
|
|
74
74
|
'Once per session, check the installed framework before starting project work. If this is the BMAD+ source checkout, use `node tools/cli/bmad-plus-cli.js update-check --json`; otherwise use `npx --no-install bmad-plus update-check --json` from the project root.',
|
|
75
|
-
'If the command is unavailable or the result is off, unknown, offline or stale, continue the user task. Do not install a CLI just to perform this check or claim that an offline version is current.',
|
|
75
|
+
'If the command is unavailable (for example npx cannot find `bmad-plus` because the project has no local copy of the package), or the result is off, unknown, offline or stale, continue the user task without mentioning the check. Do not install a CLI just to perform this check or claim that an offline version is current.',
|
|
76
76
|
'When `updateAvailable` is true and `canAutoApply` is true, run the same CLI with `update --latest --auto`. This follows the project update policy; it does not grant permission to expand that policy.',
|
|
77
77
|
'When an update is available but automatic application is not eligible, explain the version and reason. An explicit request to update can be fulfilled with `update --latest --yes`; do not change the policy, overwrite customized files, or resolve conflicts without the user request covering that action.',
|
|
78
78
|
'After a successful update, reread the project spine and relevant installed skills, or start a fresh session if the client cannot reload them. Respect preserved local instructions. Check only once even when several adapters include this section.',
|
|
@@ -468,7 +468,7 @@ function userMarkerLines() {
|
|
|
468
468
|
return [
|
|
469
469
|
'<!-- ' + GENERATED_MARKER + ' — DO NOT EDIT. -->',
|
|
470
470
|
'<!-- ' + USER_CONFIG_MARKER + ' -->',
|
|
471
|
-
'<!-- Refresh installed adapters with: npx bmad-plus update -->',
|
|
471
|
+
'<!-- Refresh installed adapters with: npx bmad-plus@latest update -->',
|
|
472
472
|
];
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -561,15 +561,15 @@ module.exports = {
|
|
|
561
561
|
}
|
|
562
562
|
|
|
563
563
|
if (selectedPacks.includes('seo')) {
|
|
564
|
-
agentGuide.push(` ${i.guide_seo.padEnd(28)} → "/seo
|
|
564
|
+
agentGuide.push(` ${i.guide_seo.padEnd(28)} → "/seo full <url>"`);
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
if (selectedPacks.includes('backup')) {
|
|
568
|
-
agentGuide.push(` ${i.guide_backup.padEnd(28)} → "/backup
|
|
568
|
+
agentGuide.push(` ${i.guide_backup.padEnd(28)} → "/backup"`);
|
|
569
569
|
}
|
|
570
570
|
|
|
571
571
|
if (selectedPacks.includes('animated')) {
|
|
572
|
-
agentGuide.push(` ${i.guide_animated.padEnd(28)} → "
|
|
572
|
+
agentGuide.push(` ${i.guide_animated.padEnd(28)} → "animated website from <video.mp4>"`);
|
|
573
573
|
}
|
|
574
574
|
|
|
575
575
|
if (selectedPacks.includes('design')) {
|
|
@@ -609,7 +609,7 @@ module.exports = {
|
|
|
609
609
|
'',
|
|
610
610
|
`📦 ${i.guide_cli_title || 'CLI Commands'}:`,
|
|
611
611
|
` npx bmad-plus install ${i.guide_cli_install || '— Install agents & skills'}`,
|
|
612
|
-
` npx bmad-plus update
|
|
612
|
+
` npx bmad-plus@latest update ${i.guide_cli_update || '— Update agents (keeps config)'}`,
|
|
613
613
|
` npx bmad-plus doctor ${i.guide_cli_doctor || '— Check installation health'}`,
|
|
614
614
|
` npx bmad-plus uninstall ${i.guide_cli_uninstall || '— Remove BMAD+ from project'}`
|
|
615
615
|
);
|
|
@@ -617,15 +617,15 @@ module.exports = {
|
|
|
617
617
|
// Add pack-specific examples
|
|
618
618
|
const examples = [];
|
|
619
619
|
if (selectedPacks.includes('seo')) {
|
|
620
|
-
examples.push(` ${i.guide_example_seo || '🔍 SEO: "/seo
|
|
620
|
+
examples.push(` ${i.guide_example_seo || '🔍 SEO: "/seo full https://example.com"'}`);
|
|
621
621
|
}
|
|
622
622
|
if (selectedPacks.includes('backup')) {
|
|
623
|
-
examples.push(
|
|
624
|
-
` ${i.guide_example_backup || '🗂️ Backup: "/backup create" → ZIP timestamped'}`
|
|
625
|
-
);
|
|
623
|
+
examples.push(` ${i.guide_example_backup || '🗂️ Backup: "/backup" → ZIP timestamped'}`);
|
|
626
624
|
}
|
|
627
625
|
if (selectedPacks.includes('animated')) {
|
|
628
|
-
examples.push(
|
|
626
|
+
examples.push(
|
|
627
|
+
` ${i.guide_example_animated || '🎬 Animated: "animated website from hero.mp4"'}`
|
|
628
|
+
);
|
|
629
629
|
}
|
|
630
630
|
if (selectedPacks.includes('design')) {
|
|
631
631
|
examples.push(
|
|
@@ -786,6 +786,13 @@ function mergeSettings(existing, defaults, explicit) {
|
|
|
786
786
|
return merged;
|
|
787
787
|
}
|
|
788
788
|
|
|
789
|
+
/**
|
|
790
|
+
* Plain YAML under every supported js-yaml: forceQuotes is avoided because 5.2.x
|
|
791
|
+
* tags forced scalars (`!!bool 'true'`, `!!int '3'`) while 5.5 does not. Strings that
|
|
792
|
+
* would read as another type are still quoted by the dumper.
|
|
793
|
+
*/
|
|
794
|
+
const CONFIG_DUMP = { lineWidth: -1, quotingType: '"' };
|
|
795
|
+
|
|
789
796
|
/** Returns null when the existing file is not a YAML mapping (left untouched). */
|
|
790
797
|
function mergeConfigYaml(existingText, generatedText, explicit = {}) {
|
|
791
798
|
let existing;
|
|
@@ -801,7 +808,7 @@ function mergeConfigYaml(existingText, generatedText, explicit = {}) {
|
|
|
801
808
|
changed: true,
|
|
802
809
|
content:
|
|
803
810
|
'# BMAD+ Project Configuration\n# Generated by bmad-plus install; existing settings preserved\n\n' +
|
|
804
|
-
yaml.dump(merged,
|
|
811
|
+
yaml.dump(merged, CONFIG_DUMP),
|
|
805
812
|
};
|
|
806
813
|
}
|
|
807
814
|
|
|
@@ -847,7 +854,7 @@ function generateConfigYaml(
|
|
|
847
854
|
// never covered by a budget, the host always asks.
|
|
848
855
|
swarm: { ...SWARM_DEFAULTS },
|
|
849
856
|
},
|
|
850
|
-
|
|
857
|
+
CONFIG_DUMP
|
|
851
858
|
)
|
|
852
859
|
);
|
|
853
860
|
}
|
|
@@ -105,7 +105,8 @@ module.exports = {
|
|
|
105
105
|
process.exitCode = 1;
|
|
106
106
|
if (options.json)
|
|
107
107
|
console.log(JSON.stringify({ schemaVersion: 1, status: 'error', error: error.message }));
|
|
108
|
-
else
|
|
108
|
+
else
|
|
109
|
+
console.error(/^Nexus: /.test(error.message) ? error.message : 'Nexus: ' + error.message);
|
|
109
110
|
}
|
|
110
111
|
},
|
|
111
112
|
};
|
|
@@ -205,7 +205,7 @@ module.exports = {
|
|
|
205
205
|
options: [
|
|
206
206
|
['-d, --directory <path>', 'Project directory'],
|
|
207
207
|
['--dir <path>', 'Review folder inside the project', review.DEFAULT_DIR],
|
|
208
|
-
['--base <ref>', 'Base commit or branch (default HEAD~1)'],
|
|
208
|
+
['--base <ref>', 'Base commit or branch (default HEAD~1, HEAD with --workspace)'],
|
|
209
209
|
['--head <ref>', 'Head commit or branch (default HEAD)'],
|
|
210
210
|
['--workspace', 'Review the working tree, untracked files included, against the base'],
|
|
211
211
|
['--include <glob>', 'Only review matching paths (repeatable)', (v, all) => [...all, v], []],
|
|
@@ -20,7 +20,33 @@ const { planUpdate, applyPlan, restoreUpdate, MANIFEST } = require('../lib/updat
|
|
|
20
20
|
function authorizeAuto(projectDir, version) {
|
|
21
21
|
const { readUpdatePolicy, authorizeTarget } = require('../lib/update-policy');
|
|
22
22
|
const decision = authorizeTarget(readUpdatePolicy(projectDir), version);
|
|
23
|
-
if (!decision.allowed) throw
|
|
23
|
+
if (!decision.allowed) throw require('../lib/update-dispatch').autoRefusal(decision.reason);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// npx runs a cached or project-local copy of the package before it asks the registry, so a plain
|
|
27
|
+
// `update` can install an older release than the published one. Say so instead of staying silent.
|
|
28
|
+
async function warnIfBehindRegistry(projectDir, version) {
|
|
29
|
+
let check;
|
|
30
|
+
try {
|
|
31
|
+
check = await require('../lib/update-check').checkForUpdate({
|
|
32
|
+
projectDir,
|
|
33
|
+
runningVersion: version,
|
|
34
|
+
});
|
|
35
|
+
} catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const latest = check.latestVersion;
|
|
39
|
+
if (!isExactVersion(latest) || !semver.gt(latest, version)) return;
|
|
40
|
+
clack.log.warn(
|
|
41
|
+
'This copy of BMAD+ is v' +
|
|
42
|
+
version +
|
|
43
|
+
' but v' +
|
|
44
|
+
latest +
|
|
45
|
+
' is published (npx reuses a cached copy). Stop and run `npx bmad-plus@latest update`, or ' +
|
|
46
|
+
'`npx bmad-plus update --latest`, to install v' +
|
|
47
|
+
latest +
|
|
48
|
+
'.'
|
|
49
|
+
);
|
|
24
50
|
}
|
|
25
51
|
|
|
26
52
|
async function confirmAction(options, message, lang = 'en') {
|
|
@@ -118,6 +144,9 @@ module.exports = {
|
|
|
118
144
|
throw new Error('Downgrade refused: ' + manifest.version + ' -> ' + version);
|
|
119
145
|
const lang = options.lang || manifest.uiLanguage || 'en';
|
|
120
146
|
clack.log.info('Installed: v' + manifest.version + ' -> Executing package: v' + version);
|
|
147
|
+
if (!options.auto && !options.expectedVersion) {
|
|
148
|
+
await warnIfBehindRegistry(projectDir, version);
|
|
149
|
+
}
|
|
121
150
|
if (manifest.version === version) {
|
|
122
151
|
clack.log.success(
|
|
123
152
|
'The installed version matches this executing package. Use --latest to check the registry.'
|