Compare commits
18 Commits
70cf1342ef
...
6c2503f9cf
| Author | SHA1 | Date |
|---|---|---|
|
|
6c2503f9cf | |
|
|
ea99b7ece5 | |
|
|
eabcd03f65 | |
|
|
17da5ca8ca | |
|
|
a0705af9be | |
|
|
f5030c7084 | |
|
|
daa7137623 | |
|
|
14fc7b2517 | |
|
|
edfb405e27 | |
|
|
202c842826 | |
|
|
128b252c32 | |
|
|
b018c7ad7c | |
|
|
7f7690dbfd | |
|
|
a92f5d626b | |
|
|
1d5a3caec5 | |
|
|
b161491ca8 | |
|
|
98f8786060 | |
|
|
229c1c57f9 |
51
CHANGELOG.md
51
CHANGELOG.md
|
|
@ -1,5 +1,56 @@
|
|||
# Changelog
|
||||
|
||||
## v6.3.0 - 2026-04-09
|
||||
|
||||
### 💥 Breaking Changes
|
||||
|
||||
* Remove custom content installation feature; use marketplace-based plugin installation instead (#2227)
|
||||
* Remove bmad-init skill; all agents and skills now load config directly from `{project-root}/_bmad/bmm/config.yaml` (#2159)
|
||||
* Remove spec-wip.md singleton; quick-dev now writes directly to `spec-{slug}.md` with status field, enabling parallel sessions (#2214)
|
||||
* Consolidate three agent personas into Developer agent (Amelia): remove Barry quick-flow-solo-dev (#2177), Quinn QA agent (#2179), and Bob Scrum Master agent (#2186)
|
||||
|
||||
### 🎁 Features
|
||||
|
||||
* Universal source support for custom module installs with 5-strategy PluginResolver cascade supporting any Git host (GitHub, GitLab, Bitbucket, self-hosted) and local file paths (#2233)
|
||||
* Community module browser with three-tier selection: official, community (category drill-down from marketplace index), and custom URL with unverified source warning (#2229)
|
||||
* Switch module source of truth from bundled config to remote marketplace registry with network-failure fallback (#2228)
|
||||
* Add bmad-prfaq skill implementing Amazon's Working Backwards methodology as alternative Phase 1 analysis path with 5-stage coached workflow and subagent architecture (#2157)
|
||||
* Add bmad-checkpoint-preview skill for guided, concern-ordered human review of commits, branches, or PRs (#2145)
|
||||
* Epic context compilation for quick-dev step-01: sub-agent compiles planning docs into cached `epic-{N}-context.md` for story implementation (#2218)
|
||||
* Previous story continuity in quick-dev: load completed spec from same epic as implementation context (#2201)
|
||||
* Planning artifact awareness in quick-dev: selectively load PRD, architecture, UX, and epics docs for context-informed specs (#2185)
|
||||
* One-shot route now generates lightweight spec trace file for consistent artifact tracking (#2121)
|
||||
* Improve checkpoint-preview UX with clickable spec paths, external edit detection, and missing-file halt (#2217)
|
||||
* Add Junie (JetBrains AI) platform support (#2142)
|
||||
* Restore KiloCoder support with native-skills installation (#2151)
|
||||
* Add bmad-help support for llms.txt general questions (#2230)
|
||||
|
||||
### ♻️ Refactoring
|
||||
|
||||
* Consolidate party-mode into single SKILL.md with real subagent spawning via Agent tool, replacing multi-file workflow architecture (#2160)
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
* Fix version display bug where marketplace.json walk-up reported wrong version (#2233)
|
||||
* Fix checkpoint-preview step-05 advancing without user confirmation by adding explicit HALT (#2184)
|
||||
* Address adversarial triage findings: clarify review_mode transitions, label walkthrough branches, fix terse commit handling (#2180)
|
||||
* Preserve local custom module sources during quick update (#2172)
|
||||
* Support skills/ folder as fallback module source location for bmb compatibility (#2149)
|
||||
|
||||
### 🔧 Maintenance
|
||||
|
||||
* Overhaul installer branding with responsive BMAD METHOD logo, blue color scheme, unified version sourcing from marketplace.json, and surgical manifest-based skill cleanup (#2223)
|
||||
* Stop copying skill prompts to _bmad by default (#2182)
|
||||
* Add Python 3.10+ and uv as documented prerequisites (#2221)
|
||||
|
||||
### 📚 Documentation
|
||||
|
||||
* Complete Czech (cs-CZ) documentation translation (#2134)
|
||||
* Complete Vietnamese (vi-VN) documentation translation (#2110, #2192)
|
||||
* Rewrite get-answers-about-bmad as 1-2-3 escalation flow, remove deprecated references (#2213)
|
||||
* Add checkpoint-preview explainer page and workflow diagram (#2183)
|
||||
* Update docs theme to match bmadcode.com with responsive logo and blue color scheme (#2176)
|
||||
|
||||
## v6.2.2 - 2026-03-25
|
||||
|
||||
### ♻️ Refactoring
|
||||
|
|
|
|||
15
README_VN.md
15
README_VN.md
|
|
@ -3,6 +3,8 @@
|
|||
[](https://www.npmjs.com/package/bmad-method)
|
||||
[](LICENSE)
|
||||
[](https://nodejs.org)
|
||||
[](https://www.python.org)
|
||||
[](https://docs.astral.sh/uv/)
|
||||
[](https://discord.gg/gk8jAdXWmj)
|
||||
|
||||
[English](README.md) | [简体中文](README_CN.md) | Tiếng Việt
|
||||
|
|
@ -36,7 +38,7 @@ Các công cụ AI truyền thống thường làm thay phần suy nghĩ của b
|
|||
|
||||
## Bắt đầu nhanh
|
||||
|
||||
**Điều kiện tiên quyết**: [Node.js](https://nodejs.org) v20+
|
||||
**Điều kiện tiên quyết**: [Node.js](https://nodejs.org) v20+ · [Python](https://www.python.org) 3.10+ · [uv](https://docs.astral.sh/uv/)
|
||||
|
||||
```bash
|
||||
npx bmad-method install
|
||||
|
|
@ -80,18 +82,15 @@ BMad Method có thể được mở rộng bằng các mô-đun chính thức ch
|
|||
## Cộng đồng
|
||||
|
||||
- [Discord](https://discord.gg/gk8jAdXWmj) - Nhận trợ giúp, chia sẻ ý tưởng, cộng tác
|
||||
- [Đăng ký trên YouTube](https://www.youtube.com/@BMadCode) - video hướng dẫn, lớp chuyên sâu và podcast (ra mắt tháng 2 năm 2025)
|
||||
- [YouTube](https://youtube.com/@BMadCode) - Video hướng dẫn, master class và nhiều nội dung khác
|
||||
- [X / Twitter](https://x.com/BMadCode)
|
||||
- [Website](https://bmadcode.com)
|
||||
- [GitHub Issues](https://github.com/bmad-code-org/BMAD-METHOD/issues) - Báo lỗi và yêu cầu tính năng
|
||||
- [Discussions](https://github.com/bmad-code-org/BMAD-METHOD/discussions) - Trao đổi cộng đồng
|
||||
|
||||
## Hỗ trợ BMad
|
||||
|
||||
BMad miễn phí cho tất cả mọi người - và sẽ luôn như vậy. Nếu bạn muốn hỗ trợ quá trình phát triển:
|
||||
|
||||
- ⭐ Hãy nhấn sao cho dự án ở góc trên bên phải của trang này
|
||||
- ☕ [Buy Me a Coffee](https://buymeacoffee.com/bmad) - Tiếp thêm năng lượng cho quá trình phát triển
|
||||
- 🏢 Tài trợ doanh nghiệp - Nhắn riêng trên Discord
|
||||
- 🎤 Diễn thuyết và truyền thông - Sẵn sàng cho hội nghị, podcast, phỏng vấn (BM trên Discord)
|
||||
BMad miễn phí cho tất cả mọi người và sẽ luôn như vậy. Hãy nhấn sao cho repo này, [mời tôi một ly cà phê](https://buymeacoffee.com/bmad), hoặc gửi email tới <contact@bmadcode.com> nếu bạn muốn tài trợ doanh nghiệp.
|
||||
|
||||
## Đóng góp
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: "Fáze analýzy: od nápadu k základům"
|
||||
description: Co je brainstorming, výzkum, product brief a PRFAQ — a kdy který nástroj použít
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
Fáze analýzy (fáze 1) vám pomůže jasně si promyslet váš produkt, než se pustíte do jeho tvorby. Každý nástroj v této fázi je volitelný, ale úplné vynechání analýzy znamená, že váš PRD je postaven na předpokladech namísto vhledu.
|
||||
|
||||
## Proč analýza před plánováním?
|
||||
|
||||
PRD odpovídá na otázku „Co bychom měli postavit a proč?“. Pokud jej nakrmíte vágním myšlením, získáte vágní PRD — a každý navazující dokument tuto vágnost zdědí. Architektura postavená na slabém PRD sází na špatnou techniku. Příběhy odvozené ze slabé architektury opomíjejí okrajové případy. Náklady se zvyšují.
|
||||
|
||||
Existují analytické nástroje, které vám PRD zostří. Napadají problém z různých úhlů — kreativní průzkum, realita trhu, jasnost zákazníka, proveditelnost — takže v době, kdy sedíte s agentem PM, víte, co a pro koho stavíte.
|
||||
|
||||
## Nástroje
|
||||
|
||||
### Brainstorming
|
||||
|
||||
**Co to je.** Zprostředkované tvůrčí sezení s využitím osvědčených technik generování nápadů. AI funguje jako kouč, který z vás tahá nápady prostřednictvím strukturovaných cvičení — negeneruje nápady za vás.
|
||||
|
||||
**Proč je to tady.** Neotřelé nápady potřebují prostor pro rozvoj, než se zakotví v požadavcích. Brainstorming tento prostor vytváří. Je cenný zejména tehdy, když máte problémovou oblast, ale nemáte jasné řešení, nebo když chcete prozkoumat více směrů, než se k něčemu zavážete.
|
||||
|
||||
**Kdy jej použít.** Máte nejasnou představu o tom, co chcete vytvořit, ale nemáte vykrystalizovaný koncept. Nebo máte koncept, ale chcete ho otestovat pod tlakem oproti alternativám.
|
||||
|
||||
Viz [Brainstorming](./brainstorming.md), kde se dozvíte, jak relace fungují.
|
||||
|
||||
### Výzkum (trhu, domény, technický)
|
||||
|
||||
**Co to je.** Tři cílené pracovní postupy výzkumu, které zkoumají různé rozměry vašeho nápadu. Výzkum trhu zkoumá konkurenci, trendy a nálady uživatelů. Doménový výzkum vytváří odborné znalosti v daném oboru a terminologii. Technický výzkum hodnotí proveditelnost, možnosti architektury a přístupy k implementaci.
|
||||
|
||||
**Proč je to tady.** Stavět na předpokladech je nejrychlejší způsob, jak vytvořit něco, co nikdo nepotřebuje. Výzkum zakládá váš koncept na realitě — co již existuje u konkurence, s čím uživatelé skutečně bojují, co je technicky proveditelné a jakým omezením specifickým pro dané odvětví budete čelit.
|
||||
|
||||
**Kdy ho použít.** Vstupujete do neznámé oblasti, tušíte, že konkurence existuje, ale nemáte ji zmapovanou, nebo váš koncept závisí na technických možnostech, které nemáte ověřené. Proveďte jeden, dva nebo všechny tři — každý z nich je samostatný.
|
||||
|
||||
### Product Brief
|
||||
|
||||
**Co to je.** Řízené zjišťovací sezení, jehož výsledkem je 1–2stránkové shrnutí vašeho konceptu produktu. AI funguje jako spolupracující obchodní analytik, který vám pomůže formulovat vizi, cílovou skupinu, nabídku hodnoty a rozsah.
|
||||
|
||||
**Proč tu je.** Produktový brief je jemnější cestou k plánování. Zachycuje vaši strategickou vizi ve strukturovaném formátu, který se přímo promítá do tvorby PRD. Nejlépe funguje, když jste již o svém konceptu přesvědčeni — znáte zákazníka, problém a zhruba víte, co chcete vytvořit. Brief tyto úvahy uspořádá a vyostří.
|
||||
|
||||
**Kdy jej použít.** Váš koncept je relativně jasný a chcete jej efektivně zdokumentovat ještě před vytvořením PRD. Jste si jisti svým směřováním a nepotřebujete své předpoklady agresivně zpochybňovat.
|
||||
|
||||
### PRFAQ (Working Backwards)
|
||||
|
||||
**Co to je.** Metodika Working Backwards společnosti Amazon upravená jako interaktivní výzva. Napíšete tiskovou zprávu oznamující váš hotový produkt dříve, než existuje jediný řádek kódu, a pak odpovíte na nejtěžší otázky, které by vám zákazníci a zainteresované strany položili. Umělá inteligence funguje jako neúprosný, ale konstruktivní produktový kouč.
|
||||
|
||||
**Proč je to tady.** PRFAQ je přísná cesta k plánování. Vynucuje si jasnost v zájmu zákazníka tím, že vás nutí obhájit každé tvrzení. Pokud nedokážete napsat přesvědčivou tiskovou zprávu, produkt není připraven. Pokud odpovědi na časté dotazy zákazníků odhalí nedostatky, jsou to nedostatky, které byste objevili mnohem později — a nákladněji — při implementaci. Hozená rukavice odhalí slabé myšlení v rané fázi, kdy je nejlevnější ho opravit.
|
||||
|
||||
**Kdy ji použít.** Před vyčleněním zdrojů chcete, aby váš koncept prošel zátěžovým testem. Nejste si jisti, zda to uživatele bude skutečně zajímat. Chcete si ověřit, že dokážete formulovat jasnou a obhajitelnou nabídku hodnoty. Nebo si prostě chcete disciplínou Working Backwards zpřesnit své myšlení.
|
||||
|
||||
## Který nástroj bych měl použít?
|
||||
|
||||
| Situace | Doporučený nástroj |
|
||||
| --------- | ---------------- |
|
||||
| „Mám nejasný nápad, ale nevím, kde začít“ | Brainstorming |
|
||||
| „Než se rozhodnu, potřebuji pochopit trh“ | Výzkum |
|
||||
| „Vím, co chci vytvořit, jen to potřebuji zdokumentovat“ | Product Brief |
|
||||
| „Chci se ujistit, že tento nápad skutečně stojí za vybudování“ | PRFAQ |
|
||||
| „Chci prozkoumat, pak ověřit a pak zdokumentovat“ | Brainstorming → Výzkum → PRFAQ nebo Brief |
|
||||
|
||||
Product Brief i PRFAQ jsou vstupem pro PRD — vyberte si jeden z nich podle toho, jak moc chcete být nároční. Brief je společným objevováním. PRFAQ je hozená rukavice. Obojí vás dovede ke stejnému cíli; PRFAQ testuje, zda si váš koncept zaslouží se tam dostat.
|
||||
|
||||
:::tip[Nejste si jisti?]
|
||||
Spusťte `bmad-help` a popište svou situaci. Doporučí vám správný výchozí bod na základě toho, co jste již udělali a čeho se snažíte dosáhnout.
|
||||
:::
|
||||
|
||||
## Co se stane po analýze?
|
||||
|
||||
Výstupy analýzy se přímo promítají do fáze 2 (plánování). Pracovní postup PRD přijímá jako vstupy produktové briefy, dokumenty PRFAQ, výsledky výzkumu a zprávy z brainstormingu — syntetizuje vše, co jste vytvořili, do strukturovaných požadavků. Čím více analýz provedete, tím ostřejší bude vaše PRD.
|
||||
|
|
@ -17,7 +17,7 @@ Tato stránka uvádí výchozí BMM (Agile suite) agenty, kteří se instalují
|
|||
|
||||
| Agent | Skill ID | Spouštěče | Primární workflow |
|
||||
| --------------------------- | -------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `RS`, `CB`, `WB`, `DP` | Brainstorm projektu, výzkum, tvorba briefu, PRFAQ výzva, dokumentace projektu |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `MR`, `DR`, `TR`, `CB`, `WB`, `DP` | Brainstorm, průzkum trhu, doménový výzkum, technický výzkum, tvorba briefu, PRFAQ výzva, dokumentace projektu |
|
||||
| Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Tvorba/validace/editace PRD, tvorba epiců a stories, připravenost implementace, korekce kurzu |
|
||||
| Architect (Winston) | `bmad-architect` | `CA`, `IR` | Tvorba architektury, připravenost implementace |
|
||||
| Developer (Amelia) | `bmad-agent-dev` | `DS`, `QD`, `QA`, `CR`, `SP`, `CS`, `ER` | Dev story, Quick Dev, generování QA testů, revize kódu, plánování sprintu, tvorba story, retrospektiva epicu |
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ Workflow skills spouštějí strukturovaný, vícekrokový proces bez předchoz
|
|||
| Příklad skillu | Účel |
|
||||
| --- | --- |
|
||||
| `bmad-product-brief` | Vytvoření product briefu — řízené discovery, když je váš koncept jasný |
|
||||
| `bmad-prfaq` | Working Backwards PRFAQ výzva pro zátěžový test vašeho produktového konceptu |
|
||||
| `bmad-prfaq` | [Working Backwards PRFAQ](../explanation/analysis-phase.md#prfaq-working-backwards) výzva pro zátěžový test vašeho produktového konceptu |
|
||||
| `bmad-create-prd` | Vytvoření dokumentu požadavků (PRD) |
|
||||
| `bmad-create-architecture` | Návrh systémové architektury |
|
||||
| `bmad-create-epics-and-stories` | Vytvoření epiců a stories |
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ Uniquement pour les parcours méthode BMad et Enterprise. Quick Dev passe direct
|
|||
|
||||
### Puis-je modifier mon plan plus tard ?
|
||||
|
||||
Oui. Utilisez `bmad-correct-course` pour gérer les changements de portée.
|
||||
Oui. Utilisez `bmad-correct-course` pour gérer les changements de portée en cours d’implémentation.
|
||||
|
||||
**Une question sans réponse ici ?** [Ouvrez une issue](...) ou posez votre question sur [Discord](...).
|
||||
```
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Élicitation Avancée"
|
||||
description: Pousser le LLM à repenser son travail en utilisant des méthodes de raisonnement structurées
|
||||
sidebar:
|
||||
order: 6
|
||||
order: 8
|
||||
---
|
||||
|
||||
Faites repenser au LLM ce qu'il vient de générer. Vous choisissez une méthode de raisonnement, il l'applique à sa propre sortie, et vous décidez de conserver ou non les améliorations.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Revue Contradictoire"
|
||||
description: Technique de raisonnement forcée qui empêche les revues paresseuses du style "ça à l'air bon"
|
||||
sidebar:
|
||||
order: 5
|
||||
order: 7
|
||||
---
|
||||
|
||||
Forcez une analyse plus approfondie en exigeant que des problèmes soient trouvés.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
title: "Phase d'analyse : de l'Idée aux Fondations"
|
||||
description: Ce que sont le brainstorming, la recherche, les product briefs et les PRFAQs — et quand les utiliser
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
La phase d'Analyse (Phase 1) vous aide à penser clairement à votre produit avant de vous engager à le construire. Chaque outil de cette phase est optionnel, mais sauter l'analyse entièrement signifie que votre PRD sera construit sur des suppositions plutôt que sur des connaissances approfondies.
|
||||
|
||||
## Pourquoi Analyser avant de Planifier ?
|
||||
|
||||
Un PRD répond à la question « que devons-nous construire et pourquoi ? » Si vous l'alimentez avec une réflexion vague, vous obtiendrez un PRD vague — et chaque document en aval héritera de cette imprécision. Une architecture bâtie sur un PRD faible prend de mauvaises décisions techniques. Les stories dérivées d'une architecture faible manquent de edge cases. Le coût s'accumule.
|
||||
|
||||
Les outils d'analyse existent pour rendre votre PRD précis. Ils attaquent le problème sous différents angles — exploration créative, réalité du marché, clarté client, faisabilité — pour qu'au moment de vous asseoir avec l'agent PM, vous sachiez ce que vous construisez et pour qui.
|
||||
|
||||
## Les Outils
|
||||
|
||||
### Brainstorming
|
||||
|
||||
**Quoi.** Une session créative facilitée utilisant des techniques d'idéation éprouvées. L'IA agit comme coach, extrayant vos idées à travers des exercices structurés — pas en les générant pour vous.
|
||||
|
||||
**Pourquoi.** Les idées brutes ont besoin d'espace pour se développer avant d'être verrouillées dans des exigences. Le brainstorming crée cet espace. Il est particulièrement précieux quand vous avez un espace-problème mais pas de solution claire, ou quand vous voulez explorer plusieurs pistes avant de vous engager.
|
||||
|
||||
**Quand.** Vous avez une vague idée de ce que vous voulez construire mais n'avez pas encore cristallisé le concept. Ou vous avez un concept mais voulez l'éprouver face à des alternatives.
|
||||
|
||||
Voir [Brainstorming](./brainstorming.md) pour un aperçu plus approfondi du fonctionnement des sessions.
|
||||
|
||||
### Recherche (Marché, Domaine, Technique)
|
||||
|
||||
**Quoi.** Trois workflows de recherche ciblés qui investiguent différentes dimensions de votre idée. La recherche marché examine les concurrents, les tendances et le sentiment utilisateur. La recherche domaine construit l'expertise métier et la terminologie. La recherche technique évalue la faisabilité, les options d'architecture et les approches d'implémentation.
|
||||
|
||||
**Pourquoi.** Construire sur des suppositions est le moyen le plus rapide de construire quelque chose dont personne n'a besoin. La recherche ancre votre concept dans la réalité — quels concurrents existent déjà, avec quoi les utilisateurs luttent réellement, ce qui est techniquement faisable, et quelles contraintes spécifiques à l'industrie vous affronterez.
|
||||
|
||||
**Quand.** Vous entrez dans un domaine inconnu, vous soupçonnez que des concurrents existent mais ne les avez pas cartographiés, ou votre concept dépend de capacités techniques que vous n'avez pas validées. Lancez-en un, deux ou les trois — chaque workflow de recherche fonctionne de manière autonome.
|
||||
|
||||
### Product Brief[^1]
|
||||
|
||||
**Quoi.** Une session de découverte guidée qui produit un résumé exécutif de 1-2 pages de votre concept produit. L'IA agit comme un analyste commercial collaboratif, vous aidant à articuler la vision, le public cible, la proposition de valeur et le périmètre.
|
||||
|
||||
**Pourquoi.** Le product brief est le chemin le plus doux vers la planification. Il capture votre vision stratégique dans un format structuré qui alimente directement la création du PRD. Il fonctionne mieux quand vous avez déjà la conviction à propos de votre concept — vous connaissez le client, le problème et approximativement ce que vous voulez construire. Le brief organise et affine cette réflexion.
|
||||
|
||||
**Quand.** Votre concept est relativement clair et vous voulez le documenter efficacement avant de créer un PRD. Vous êtes confiant dans la direction et n'avez pas besoin que vos suppositions soient agressivement remises en question.
|
||||
|
||||
### PRFAQ (Working Backwards)
|
||||
|
||||
**Quoi.** La méthodologie Working Backwards d'Amazon adaptée en défi interactif. Vous rédigez le communiqué de presse annonçant votre produit fini avant qu'une seule ligne de code n'existe, puis répondez aux questions les plus difficiles que les clients et les parties prenantes poseraient. L'IA agit comme un coach produit implacable mais constructif.
|
||||
|
||||
**Pourquoi.** Le PRFAQ est le chemin rigoureux vers la planification. Il force la clarté orientée client en vous obligeant à défendre chaque affirmation. Si vous ne pouvez pas rédiger un communiqué de presse convaincant, le produit n'est pas prêt. Si les réponses de la FAQ client révèlent des lacunes, ce sont des lacunes que vous découvrirez bien plus tard — et plus coûteusement — pendant l'implémentation. Le défi fait remonter les failles de réflexion tôt, quand c'est le moins cher de les corriger.
|
||||
|
||||
**Quand.** Vous voulez que votre concept soit éprouvé avant d'engager des ressources. Vous n'êtes pas sûr que les utilisateurs s'en soucieront réellement. Vous voulez valider que vous pouvez articuler une proposition de valeur claire et défendable. Ou vous voulez simplement la discipline du Working Backwards pour affiner votre réflexion.
|
||||
|
||||
## Lequel utiliser ?
|
||||
|
||||
| Situation | Outil recommandé |
|
||||
|-------------------------------------------------------------------------------|--------------------------------------------|
|
||||
| « J'ai une idée vague, je ne sais pas par où commencer » | Brainstorming |
|
||||
| « J'ai besoin de comprendre le marché avant de décider » | Recherche |
|
||||
| « Je sais ce que je veux construire, j'ai juste besoin de le documenter » | Product Brief |
|
||||
| « Je veux m'assurer que cette idée vaut vraiment la peine d'être construite » | PRFAQ |
|
||||
| « Je veux explorer, puis valider, puis documenter » | Brainstorming → Recherche → PRFAQ ou Brief |
|
||||
|
||||
Le Product Brief et le PRFAQ produisent tous deux des entrées pour le PRD — choisissez-en un en fonction du niveau de défi que vous souhaitez. Le brief est une découverte collaborative. Le PRFAQ est un défi. Les deux vous mènent à la même destination ; le PRFAQ teste si votre concept mérite d'y arriver.
|
||||
|
||||
:::tip[Pas sûr ?]
|
||||
Exécutez `bmad-help` et décrivez votre situation. Il vous recommandera le bon point de départ en fonction de ce que vous avez déjà accompli et de ce que vous essayez de réaliser.
|
||||
:::
|
||||
|
||||
## Que se passe-t-il après l'analyse ?
|
||||
|
||||
Les résultats de l'analyse alimentent directement la Phase 2 (Planification). Le workflow PRD accepte les product briefs, les documents PRFAQ, les conclusions de recherche et les rapports de brainstorming en entrée — il synthétise tout ce que vous avez produit en exigences structurées. Plus vous faites d'analyse, plus votre PRD sera précis.
|
||||
|
||||
## Glossaire
|
||||
|
||||
[^1]: Brief : document synthétique qui formalise le contexte, les objectifs, le périmètre et les contraintes d'un projet ou d'une demande, afin d'aligner rapidement les parties prenantes avant le travail détaillé.
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
title: "Checkpoint Preview"
|
||||
description: Revue assistée par LLM, avec intervention humaine, qui vous guide à travers une modification, de son objectif jusqu’aux détails
|
||||
sidebar:
|
||||
order: 4
|
||||
---
|
||||
|
||||
`bmad-checkpoint-preview` est un workflow de revue interactif, assisté par LLM, avec intervention humaine. Il vous guide à travers une modification de code — de l'intention et du contexte jusqu'aux détails — afin que vous puissiez prendre une décision éclairée sur la mise en production, la refonte ou l'approfondissement.
|
||||
|
||||

|
||||
|
||||
## Le Flux Typique
|
||||
|
||||
Vous lancez `bmad-quick-dev`. Il clarifie votre intention, construit une spécification, implémente la modification, et une fois terminé, il ajoute un historique de revue au fichier de spécification et l'ouvre dans votre éditeur. Vous regardez la spec et constatez que la modification a touché 20 fichiers dans plusieurs modules.
|
||||
|
||||
Vous pourriez survoler le diff. Mais 20 fichiers, c'est le moment où le survol commence à échouer — on perd le fil, on rate un lien entre deux modifications éloignées, ou on approuve quelque chose qu'on n'a pas pleinement compris. Alors au lieu de cela, vous dites « checkpoint » et le LLM vous guide à travers la modification.
|
||||
|
||||
Ce passage de relais — de l'implémentation autonome au jugement humain — est le cas d'usage principal. Quick-dev s'exécute longtemps avec une supervision minimale. Checkpoint Preview, c'est là où vous reprenez le volant.
|
||||
|
||||
## Pourquoi
|
||||
|
||||
La revue de code a deux modes d'échec. Dans le premier, le réviseur survole le diff, rien ne saute aux yeux, et il approuve. Dans le second, il lit méthodiquement chaque fichier mais perd le fil — il voit les arbres et rate la forêt. Les deux aboutissent au même résultat : la revue n'a pas repéré ce qui comptait.
|
||||
|
||||
Le problème sous-jacent est le séquençage. Un diff brut présente les modifications dans l'ordre des fichiers, ce qui est presque jamais l'ordre qui construit la compréhension. Vous voyez une fonction utilitaire avant de savoir pourquoi elle existe. Vous voyez une modification de schéma avant de comprendre quelle fonctionnalité elle supporte. Le réviseur doit reconstruire l'intention de l'auteur à partir d'indices dispersés, et c'est cette reconstruction qui fait défaut à l'attention.
|
||||
|
||||
Checkpoint Preview résout ce problème en confiant le travail de reconstruction au LLM. Il lit le diff, la spécification (si elle existe) et la base de code environnante, puis présente la modification dans un ordre conçu pour la compréhension — et non pour `git diff`.
|
||||
|
||||
## Comment ça fonctionne
|
||||
|
||||
Le workflow comporte cinq étapes. Chaque étape s'appuie sur la précédente, passant progressivement de « qu'est-ce que c'est ? » à « devons-nous publier ça ? »
|
||||
|
||||
### 1. Orientation
|
||||
|
||||
Le workflow identifie la modification (à partir d'une PR, d'un commit, d'une branche, d'un fichier de spécification ou de l'état git actuel) et produit un résumé d'intention en une ligne ainsi que des statistiques de surface : fichiers modifiés, modules touchés, lignes de logique, dépassements de boundaries et nouvelles interfaces publiques.
|
||||
|
||||
C'est le moment « est-ce bien ce que je crois ? ». Avant de lire le moindre code, le réviseur confirme qu'il regarde la bonne chose et calibre ses attentes quant à la portée.
|
||||
|
||||
### 2. Visite guidée
|
||||
|
||||
La modification est organisée par **préoccupation** — des intentions de conception cohérentes comme « validation des entrées » ou « contrat d'API » — et non par fichier. Chaque préoccupation fait l'objet d'une courte explication du *pourquoi* de cette approche, suivie d'arrêts cliquables `chemin:ligne` que le réviseur peut suivre dans le code.
|
||||
|
||||
C'est l'étape du jugement de conception. Le réviseur évalue si l'approche est adaptée au système, et non si le code est correct. Les préoccupations sont séquencées de haut en bas : l'intention de plus haut niveau en premier, puis l'implémentation de support. Le réviseur ne rencontre jamais une référence à quelque chose qu'il n'a pas encore vu.
|
||||
|
||||
### 3. Passage en revue des détails
|
||||
|
||||
Une fois que le réviseur comprend la conception, le workflow met en évidence 2 à 5 endroits où une erreur aurait l’impact le plus important. Ceux-ci sont étiquetés par catégorie de risque — `[auth]`, `[schéma]`, `[facturation]`, `[API publique]`, `[sécurité]`, et d'autres — et ordonnés selon l'impact en cas d'erreur.
|
||||
|
||||
Ce n'est pas une chasse aux bugs. Les tests automatisés et la CI gèrent la correction. Le passage en revue des détails active la conscience du risque : « voici les endroits où se tromper coûte le plus cher ». Si le réviseur veut approfondir un domaine spécifique, il peut dire « approfondis [domaine] » pour une re-revue ciblée axée sur la correction.
|
||||
|
||||
Si la spécification a passé des boucles de revues contradictoires (machine hardening), ces résultats sont également présentés ici — pas les bugs qui ont été corrigés, mais les décisions que la boucle de revue a signalées et dont le réviseur devrait être conscient.
|
||||
|
||||
### 4. Tests
|
||||
|
||||
Propose 2 à 5 façons d'observer manuellement la modification en action. Pas des commandes de test automatisé — des observations manuelles qui renforcent la confiance au-delà de ce que toute suite de tests peut fournir. Une interaction UI à essayer, une commande CLI à lancer, une requête API à envoyer, avec les résultats attendus pour chacune.
|
||||
|
||||
Si la modification n'a aucun comportement visible par l'utilisateur, il le dit. Pas de travail inventé.
|
||||
|
||||
### 5. Conclusion
|
||||
|
||||
Le réviseur prend la décision : approuver, retravailler ou continuer la discussion. S'il approuve une PR, le workflow peut aider avec `gh pr review --approve`. S'il demande une refonte, il aide à diagnostiquer si le problème vient de l'approche, de la spécification ou de l'implémentation, et aide à rédiger un retour actionnable lié à des emplacements de code spécifiques.
|
||||
|
||||
## C'est une conversation, pas un rapport
|
||||
|
||||
Le workflow présente chaque étape comme un point de départ, pas un mot final. Entre les étapes — ou au milieu d'une — vous pouvez parler au LLM, poser des questions, remettre en question son cadrage ou faire appel à d'autres skills pour obtenir une perspective différente :
|
||||
|
||||
- **« lance l'élicitation avancée sur la gestion des erreurs »** — pousse le LLM à reconsidérer et affiner son analyse d'un domaine spécifique
|
||||
- **« active le party mode sur la sécurité de cette migration de schéma »** — fait intervenir plusieurs perspectives agentiques dans un débat ciblé
|
||||
- **« lance la revue de code »** — génère des résultats structurés avec analyse adversariale et cas limites
|
||||
|
||||
Le workflow checkpoint ne vous enferme pas dans un chemin linéaire. Il vous donne de la structure quand vous la souhaitez et s'efface quand vous voulez explorer. Les cinq étapes sont là pour s'assurer que vous voyez le tableau complet, mais la profondeur à laquelle vous allez à chaque étape — et les outils que vous y apportez — est entièrement entre vos mains.
|
||||
|
||||
## L'historique de revue
|
||||
|
||||
L'étape de visite guidée fonctionne mieux lorsqu'elle dispose d'un **ordre de revue suggéré** — une liste d'arrêts que l'auteur de la spécification a rédigée pour guider les réviseurs à travers la modification. Lorsqu'une spécification inclut cet ordre, le workflow l'utilise directement.
|
||||
|
||||
Lorsqu'aucun historique produit par l'auteur n'existe, le workflow en génère un à partir du diff et du contexte de la base de code. Un historique généré est de qualité inférieure à un historique produit par l'auteur, mais nettement supérieur à la lecture des modifications dans l'ordre des fichiers.
|
||||
|
||||
## Quand l'utiliser
|
||||
|
||||
Le scénario principal est le passage de relais depuis `bmad-quick-dev` : l'implémentation est terminée, le fichier de spécification est ouvert dans votre éditeur avec un historique de revue ajouté, et vous devez décider si vous publiez. Dites « checkpoint » et c'est parti.
|
||||
|
||||
Il fonctionne aussi de manière autonome :
|
||||
|
||||
- **Revue d'une PR** — surtout celles avec plus de quelques fichiers ou des modifications transversales
|
||||
- **Prise en main d'une modification** — quand vous devez comprendre ce qui s'est passé sur une branche que vous n'avez pas écrite
|
||||
- **Revue de sprint** — le workflow peut récupérer les stories marquées `review` dans votre fichier de statut de sprint
|
||||
|
||||
Invoquez-le en disant « checkpoint » ou « guide-moi à travers cette modification ». Il fonctionne dans n'importe quel terminal, mais vous en tirerez plus de parti dans un IDE — VS Code, Cursor ou similaire — car le workflow produit des références `chemin:ligne` à chaque étape. Dans un terminal intégré à un IDE, celles-ci sont cliquables, ce qui vous permet de sauter de fichier en fichier en suivant l'historique de revue.
|
||||
|
||||
## Ce que ce n'est pas
|
||||
|
||||
Checkpoint Preview ne remplace pas la revue automatisée. Il ne lance pas de linters, de vérificateurs de types ou de suites de tests. Il n'attribue pas de scores de sévérité et ne produit pas de verdicts pass/échec. C'est un guide de lecture qui aide un humain à appliquer son jugement là où cela compte le plus.
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
title: "FAQ Projets Existants"
|
||||
description: Questions courantes sur l'utilisation de la méthode BMad sur des projets existants
|
||||
sidebar:
|
||||
order: 8
|
||||
order: 11
|
||||
---
|
||||
Réponses rapides aux questions courantes sur l'utilisation de la méthode BMad (BMM) sur des projets existants.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Party Mode"
|
||||
description: Collaboration multi-agents - regroupez tous vos agents IA dans une seule conversation
|
||||
sidebar:
|
||||
order: 7
|
||||
order: 9
|
||||
---
|
||||
|
||||
Regroupez tous vos agents IA dans une seule conversation.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Prévention des conflits entre agents"
|
||||
description: Comment l'architecture empêche les conflits lorsque plusieurs agents implémentent un système
|
||||
sidebar:
|
||||
order: 4
|
||||
order: 6
|
||||
---
|
||||
|
||||
Lorsque plusieurs agents IA implémentent différentes parties d'un système, ils peuvent prendre des décisions techniques contradictoires. La documentation d'architecture prévient cela en établissant des standards partagés.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Contexte du Projet"
|
||||
description: Comment project-context.md guide les agents IA avec les règles et préférences de votre projet
|
||||
sidebar:
|
||||
order: 7
|
||||
order: 10
|
||||
---
|
||||
|
||||
Le fichier `project-context.md` est le guide d'implémentation de votre projet pour les agents IA. Similaire à une « constitution » dans d'autres systèmes de développement, il capture les règles, les patterns et les préférences qui garantissent une génération de code cohérente à travers tous les workflows.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Quick Dev"
|
||||
description: Réduire la friction de l’interaction humaine sans renoncer aux points de contrôle qui protègent la qualité des résultats
|
||||
sidebar:
|
||||
order: 2
|
||||
order: 3
|
||||
---
|
||||
|
||||
Intention en entrée, modifications de code en sortie, avec aussi peu d'interactions humaines dans la boucle que possible — sans sacrifier la qualité.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Pourquoi le Solutioning est Important"
|
||||
description: Comprendre pourquoi la phase de solutioning est critique pour les projets multi-epics
|
||||
sidebar:
|
||||
order: 3
|
||||
order: 5
|
||||
---
|
||||
|
||||
La Phase 3 (Solutioning) traduit le **quoi** construire (issu de la Planification) en **comment** le construire (conception technique). Cette phase évite les conflits entre agents dans les projets multi-epics en documentant les décisions architecturales avant le début de l'implémentation.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ Modifier la façon dont l'agent se présente :
|
|||
```yaml
|
||||
agent:
|
||||
metadata:
|
||||
name: 'Bob l’éponge' # Par défaut : "Mary"
|
||||
name: 'Bob l’éponge' # Par défaut : "Amelia"
|
||||
```
|
||||
|
||||
**Persona**
|
||||
|
|
|
|||
|
|
@ -5,111 +5,55 @@ sidebar:
|
|||
order: 4
|
||||
---
|
||||
|
||||
## Commencez ici : BMad-Help
|
||||
Utilisez l'aide intégrée de BMad, la documentation source ou la communauté pour obtenir des réponses — du plus rapide au plus approfondi.
|
||||
|
||||
**Le moyen le plus rapide d'obtenir des réponses sur BMad est le skill `bmad-help`.** Ce guide intelligent répondra à plus de 80 % de toutes les questions et est disponible directement dans votre IDE pendant que vous travaillez.
|
||||
## 1. Demandez à BMad-Help
|
||||
|
||||
BMad-Help est bien plus qu'un outil de recherche — il :
|
||||
- **Inspecte votre projet** pour voir ce qui a déjà été réalisé
|
||||
- **Comprend le langage naturel** — posez vos questions en français courant
|
||||
- **S'adapte à vos modules installés** — affiche les options pertinentes
|
||||
- **Se lance automatiquement après les workflows** — vous indique exactement quoi faire ensuite
|
||||
- **Recommande la première tâche requise** — plus besoin de deviner par où commencer
|
||||
|
||||
### Comment utiliser BMad-Help
|
||||
|
||||
Appelez-le par son nom dans votre session IA :
|
||||
Le moyen le plus rapide d'obtenir des réponses. Le skill `bmad-help` est disponible directement dans votre session IA et répond à plus de 80 % des questions — il inspecte votre projet, voit ce que vous avez accompli et vous dit quoi faire ensuite.
|
||||
|
||||
```
|
||||
bmad-help
|
||||
bmad-help J'ai une idée de SaaS et je connais toutes les fonctionnalités. Par où commencer ?
|
||||
bmad-help Quelles sont mes options pour le design UX ?
|
||||
bmad-help Je suis bloqué sur le workflow PRD
|
||||
```
|
||||
|
||||
:::tip
|
||||
Vous pouvez également utiliser `/bmad-help` ou `$bmad-help` selon votre plateforme, mais `bmad-help` tout seul devrait fonctionner partout.
|
||||
:::
|
||||
|
||||
Combinez-le avec une requête en langage naturel :
|
||||
## 2. Approfondissez avec les sources
|
||||
|
||||
```
|
||||
bmad-help J'ai une idée de SaaS et je connais toutes les fonctionnalités. Par où commencer ?
|
||||
bmad-help Quelles sont mes options pour le design UX ?
|
||||
bmad-help Je suis bloqué sur le workflow PRD
|
||||
bmad-help Montre-moi ce qui a été fait jusqu'à maintenant
|
||||
```
|
||||
BMad-Help s'appuie sur votre configuration installée. Pour les questions sur les éléments internes de BMad, son historique ou son architecture — ou si vous faites des recherches sur BMad avant de l'installer — pointez votre IA directement vers les sources.
|
||||
|
||||
BMad-Help répond avec :
|
||||
- Ce qui est recommandé pour votre situation
|
||||
- Quelle est la première tâche requise
|
||||
- À quoi ressemble le reste du processus
|
||||
|
||||
## Quand utiliser ce guide
|
||||
|
||||
Utilisez cette section lorsque :
|
||||
- Vous souhaitez comprendre l'architecture ou les éléments internes de BMad
|
||||
- Vous avez besoin de réponses au-delà de ce que BMad-Help fournit
|
||||
- Vous faites des recherches sur BMad avant l'installation
|
||||
- Vous souhaitez explorer le code source directement
|
||||
|
||||
## Étapes
|
||||
|
||||
### 1. Choisissez votre source
|
||||
|
||||
| Source | Idéal pour | Exemples |
|
||||
|-------------------------|------------------------------------------------------|---------------------------------------|
|
||||
| **Dossier `_bmad`** | Comment fonctionne BMad — agents, workflows, prompts | "Que fait l'agent Analyste ?" |
|
||||
| **Repo GitHub complet** | Historique, installateur, architecture | "Qu'est-ce qui a changé dans la v6 ?" |
|
||||
| **`llms-full.txt`** | Aperçu rapide depuis la documentation | "Expliquez les quatre phases de BMad" |
|
||||
|
||||
Le dossier `_bmad` est créé lorsque vous installez BMad. Si vous ne l'avez pas encore, clonez le repo à la place.
|
||||
|
||||
### 2. Pointez votre IA vers la source
|
||||
|
||||
**Si votre IA peut lire des fichiers (Claude Code, Cursor, etc.) :**
|
||||
|
||||
- **BMad installé :** Pointez vers le dossier `_bmad` et posez vos questions directement
|
||||
- **Vous voulez plus de contexte :** Clonez le [repo complet](https://github.com/bmad-code-org/BMAD-METHOD)
|
||||
|
||||
**Si vous utilisez ChatGPT ou Claude.ai (LLM en ligne) :**
|
||||
|
||||
Importez `llms-full.txt` dans votre session :
|
||||
|
||||
```text
|
||||
https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
|
||||
```
|
||||
|
||||
|
||||
### 3. Posez votre question
|
||||
Clonez ou ouvrez le [dépôt BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) et posez vos questions à votre IA. Tout outil capable d'utiliser des agents (Claude Code, Cursor, Windsurf, etc.) peut lire les sources et répondre directement à vos questions.
|
||||
|
||||
:::note[Exemple]
|
||||
**Q :** "Quel est le moyen le plus rapide de construire quelque chose avec BMad ?"
|
||||
|
||||
**R :** Utilisez le workflow Quick Dev : Lancez `bmad-quick-dev` — il clarifie votre intention, planifie, implémente, révise et présente les résultats dans un seul workflow, en sautant les phases de planification complètes.
|
||||
**R :** Utilisez le flux rapide : Lancez `bmad-quick-dev` — il clarifie votre intention, planifie, implémente, révise et présente les résultats dans un seul workflow, en sautant les phases de planification complètes.
|
||||
:::
|
||||
|
||||
## Ce que vous obtenez
|
||||
**Conseils pour de meilleures réponses :**
|
||||
|
||||
Des réponses directes sur BMad — comment fonctionnent les agents, ce que font les workflows, pourquoi les choses sont structurées ainsi — sans attendre la réponse de quelqu'un.
|
||||
|
||||
## Conseils
|
||||
|
||||
- **Vérifiez les réponses surprenantes** — Les LLM font parfois des erreurs. Consultez le fichier source ou posez la question sur Discord.
|
||||
- **Soyez précis** — "Que fait l'étape 3 du workflow PRD ?" est mieux que "Comment fonctionne le PRD ?"
|
||||
- **Vérifiez les affirmations surprenantes** — Les LLM font parfois des erreurs. Consultez le fichier source ou posez la question sur Discord.
|
||||
|
||||
## Toujours bloqué ?
|
||||
### Vous n'utilisez pas d'agent ? Utilisez le site de documentation
|
||||
|
||||
Avez-vous essayé l'approche LLM et avez encore besoin d'aide ? Vous avez maintenant une bien meilleure question à poser.
|
||||
Si votre IA ne peut pas lire des fichiers locaux (ChatGPT, Claude.ai, etc.), importez [llms-full.txt](https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt) dans votre session — c'est un instantané en un seul fichier de la documentation BMad.
|
||||
|
||||
## 3. Demandez à quelqu'un
|
||||
|
||||
Si ni BMad-Help ni la source n'ont répondu à votre question, vous avez maintenant une bien meilleure question à poser.
|
||||
|
||||
| Canal | Utilisé pour |
|
||||
| ------------------------- | ------------------------------------------- |
|
||||
| `#bmad-method-help` | Questions rapides (chat en temps réel) |
|
||||
| Forum `help-requests` | Questions détaillées (recherchables, persistants) |
|
||||
| Forum `help-requests` | Questions |
|
||||
| `#suggestions-feedback` | Idées et demandes de fonctionnalités |
|
||||
| `#report-bugs-and-issues` | Rapports de bugs |
|
||||
|
||||
**Discord :** [discord.gg/gk8jAdXWmj](https://discord.gg/gk8jAdXWmj)
|
||||
|
||||
**GitHub Issues :** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues) (pour les bugs clairs)
|
||||
|
||||
**GitHub Issues :** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)
|
||||
*Toi !*
|
||||
*Bloqué*
|
||||
*dans la file d'attente—*
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ Si vous avez des stories[^3] créées ou implémentées :
|
|||
|
||||
1. Terminez l'installation v6
|
||||
2. Placez `epics.md` ou `epics/epic*.md`[^2] dans `_bmad-output/planning-artifacts/`
|
||||
3. Lancez le workflow `bmad-sprint-planning`[^4]
|
||||
4. Indiquez quels epics/stories sont déjà terminés
|
||||
3. Lancez le workflow Développeur `bmad-sprint-planning`[^4]
|
||||
4. Indiquez à l’agent quels epics/stories sont déjà terminés
|
||||
|
||||
## Ce que vous obtenez
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,28 @@
|
|||
---
|
||||
title: Agents
|
||||
description: Agents BMM par défaut avec leurs identifiants de skill, déclencheurs de menu et workflows principaux (Analyst, Developer, Architect, UX Designer, Technical Writer)
|
||||
description: Agents BMM par défaut avec leurs identifiants de skill, déclencheurs de menu et workflows principaux
|
||||
sidebar:
|
||||
order: 2
|
||||
---
|
||||
|
||||
## Agents par défaut
|
||||
|
||||
Cette page liste les cinq agents BMM (suite Agile) par défaut installés avec la méthode BMad, ainsi que leurs identifiants de skill, déclencheurs de menu et workflows principaux. Chaque agent est invoqué en tant que skill.
|
||||
Cette page liste les agents BMM (suite Agile) par défaut installés avec la méthode BMad, ainsi que leurs identifiants de skill, déclencheurs de menu et workflows principaux. Chaque agent est invoqué en tant que skill.
|
||||
|
||||
## Notes
|
||||
|
||||
- Chaque agent est disponible en tant que skill, généré par l’installateur. L’identifiant de skill (par exemple, `bmad-analyst`) est utilisé pour invoquer l’agent.
|
||||
- Chaque agent est disponible en tant que skill, généré par l’installateur. L’identifiant de skill (par exemple, `bmad-dev`) est utilisé pour invoquer l’agent.
|
||||
- Les déclencheurs sont les codes courts de menu (par exemple, `BP`) et les correspondances approximatives affichés dans chaque menu d’agent.
|
||||
- La génération de tests QA est gérée par le skill de workflow `bmad-qa-generate-e2e-tests`. L’architecte de tests complet (TEA) se trouve dans son propre module.
|
||||
- La génération de tests QA est gérée par le skill de workflow `bmad-qa-generate-e2e-tests`, disponible par l’agent Développeur. L’architecte de tests complet (TEA) se trouve dans son propre module.
|
||||
|
||||
| Agent | Identifiant de skill | Déclencheurs | Workflows principaux |
|
||||
|------------------------|----------------------|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Analyste (Mary) | `bmad-analyst` | `BP`, `MR`, `DR`, `TR`, `CB`, `DP` | Brainstorming du projet, Recherche marché/domaine/technique, Création du brief[^1], Documentation du projet |
|
||||
| Architecte (Winston) | `bmad-architect` | `CA`, `IR` | Créer l’architecture, Préparation à l’implémentation |
|
||||
| Développeur (Amelia) | `bmad-dev` | `DS`, `QD`, `CR` | Dev Story, Quick Dev, Code Review |
|
||||
| Designer UX (Sally) | `bmad-ux-designer` | `CU` | Création du design UX[^2] |
|
||||
| Rédacteur Technique (Paige) | `bmad-tech-writer` | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Documentation du projet, Rédaction de documents, Mise à jour des standards, Génération de diagrammes Mermaid, Validation de documents, Explication de concepts |
|
||||
| Agent | Identifiant de skill | Déclencheurs | Workflows principaux |
|
||||
|-----------------------------|----------------------|------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Analyste (Mary) | `bmad-analyst` | `BP`, `MR`, `DR`, `TR`, `CB`, `WB`, `DP` | Brainstorming du projet, Recherche marché/domaine/technique, Création du brief[^1], Défi PRFAQ, Documentation du projet |
|
||||
| Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Créer/Valider/Éditer un PRD, Créer des Epics et Stories, vérifier l’état de préparation à l’Implémentation, Corriger le Cours |
|
||||
| Architecte (Winston) | `bmad-architect` | `CA`, `IR` | Créer l’architecture, Préparation à l’implémentation |
|
||||
| Développeur (Amelia) | `bmad-agent-dev` | `DS`, `QD`, `QA`, `CR`, `SP`, `CS`, `ER` | Dev Story, Quick Dev, Génération de Tests QA, Code Review, Sprint Planning, Créer Story, Rétrospective d’Epic |
|
||||
| Designer UX (Sally) | `bmad-ux-designer` | `CU` | Création du design UX[^2] |
|
||||
| Rédacteur Technique (Paige) | `bmad-tech-writer` | `DP`, `WD`, `US`, `MG`, `VD`, `EC` | Documentation du projet, Rédaction de documents, Mise à jour des standards, Génération de diagrammes Mermaid, Validation de documents, Explication de concepts |
|
||||
|
||||
## Types de déclencheurs
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ Les déclencheurs de menu d'agent utilisent deux types d'invocation différents.
|
|||
|
||||
La plupart des déclencheurs chargent un fichier de workflow structuré. Tapez le code du déclencheur et l'agent démarre le workflow, vous demandant de saisir les informations à chaque étape.
|
||||
|
||||
Exemples : `BP` (Brainstorm Project), `CA` (Create Architecture), `CU` (Create UX Design)
|
||||
Exemples : `CP` (Create PRD), `DS` (Dev Story), `CA` (Create Architecture), `QD` (Quick Dev)
|
||||
|
||||
### Déclencheurs conversationnels (arguments requis)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: Skills
|
||||
description: Référence des skills BMad — ce qu'ils sont, comment ils fonctionnent et où les trouver.
|
||||
sidebar:
|
||||
order: 3
|
||||
order: 4
|
||||
---
|
||||
|
||||
Les skills sont des prompts pré-construits qui chargent des agents, exécutent des workflows ou lancent des tâches dans votre IDE. L'installateur BMad les génère à partir de vos modules installés au moment de l'installation. Si vous ajoutez, supprimez ou modifiez des modules ultérieurement, relancez l'installateur pour garder les skills synchronisés (voir [Dépannage](#dépannage)).
|
||||
|
|
@ -54,12 +54,12 @@ Chaque skill est un répertoire contenant un fichier `SKILL.md`. Par exemple, un
|
|||
│ └── SKILL.md
|
||||
├── bmad-create-prd/
|
||||
│ └── SKILL.md
|
||||
├── bmad-analyst/
|
||||
├── bmad-agent-dev/
|
||||
│ └── SKILL.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
Le nom du répertoire détermine le nom du skill dans votre IDE. Par exemple, le répertoire `bmad-analyst/` enregistre le skill `bmad-analyst`.
|
||||
Le nom du répertoire détermine le nom du skill dans votre IDE. Par exemple, le répertoire `bmad-agent-dev/` enregistre le skill `bmad-agent-dev`.
|
||||
|
||||
## Comment découvrir vos skills
|
||||
|
||||
|
|
@ -75,23 +75,24 @@ Les répertoires de skills générés dans votre projet sont la liste de référ
|
|||
|
||||
### Skills d'agent
|
||||
|
||||
Les skills d'agent chargent une persona[^2] IA spécialisée avec un rôle défini, un style de communication et un menu de workflows. Une fois chargé, l'agent reste en caractère et répond aux déclencheurs du menu.
|
||||
Les skills d'agent chargent un persona[^2] IA spécialisé avec un rôle défini, un style de communication et un menu de workflows. Une fois chargé, l'agent reste en caractère et répond aux déclencheurs du menu.
|
||||
|
||||
| Exemple de skill | Agent | Rôle |
|
||||
| --- | --- | --- |
|
||||
| `bmad-analyst` | Mary (Analyste) | Brainstorming de projets, recherche, création de briefs |
|
||||
| `bmad-architect` | Winston (Architecte) | Conçoit l'architecture système |
|
||||
| `bmad-ux-designer` | Sally (Designer UX) | Crée les designs UX |
|
||||
| `bmad-tech-writer` | Paige (Rédacteur Technique) | Documente les projets, rédige des guides, génère des diagrammes |
|
||||
| Exemple de skill | Agent | Rôle |
|
||||
|------------------|------------------------|-------------------------------------------------------------|
|
||||
| `bmad-agent-dev` | Amelia (Développeur) | Implémente les stories avec une adhérence stricte aux specs |
|
||||
| `bmad-pm` | John (Product Manager) | Crée et valide les PRDs[^1] |
|
||||
| `bmad-architect` | Winston (Architecte) | Conçoit l'architecture système |
|
||||
|
||||
Consultez [Agents](./agents.md) pour la liste complète des agents par défaut et leurs déclencheurs.
|
||||
|
||||
### Skills de workflow
|
||||
|
||||
Les skills de workflow exécutent un processus structuré en plusieurs étapes sans charger d'abord une persona d'agent. Ils chargent une configuration de workflow et suivent ses étapes.
|
||||
Les skills de workflow exécutent un processus structuré en plusieurs étapes sans charger d'abord un persona d'agent. Ils chargent une configuration de workflow et suivent ses étapes.
|
||||
|
||||
| Exemple de skill | Objectif |
|
||||
| --- | --- |
|
||||
| `bmad-product-brief` | Créer un product brief[^3] — découverte guidée lorsque votre concept est clair |
|
||||
| `bmad-prfaq` | Défi [PRFAQ Working Backwards](../explanation/analysis-phase.md#prfaq-working-backwards) pour éprouver votre concept produit |
|
||||
| `bmad-create-prd` | Créer un PRD[^1] |
|
||||
| `bmad-create-architecture` | Concevoir l'architecture système |
|
||||
| `bmad-create-epics-and-stories` | Créer des epics et des stories |
|
||||
|
|
@ -123,7 +124,7 @@ Le module principal inclut 11 outils intégrés — revues, compression, brainst
|
|||
|
||||
## Convention de nommage
|
||||
|
||||
Tous les skills utilisent le préfixe `bmad-` suivi d'un nom descriptif (ex. `bmad-analyst`, `bmad-create-prd`, `bmad-help`). Consultez [Modules](./modules.md) pour les modules disponibles.
|
||||
Tous les skills utilisent le préfixe `bmad-` suivi d'un nom descriptif (ex. `bmad-agent-dev`, `bmad-create-prd`, `bmad-help`). Consultez [Modules](./modules.md) pour les modules disponibles.
|
||||
|
||||
## Dépannage
|
||||
|
||||
|
|
@ -136,4 +137,5 @@ Tous les skills utilisent le préfixe `bmad-` suivi d'un nom descriptif (ex. `bm
|
|||
## Glossaire
|
||||
|
||||
[^1]: PRD (Product Requirements Document) : document de référence qui décrit les objectifs du produit, les besoins utilisateurs, les fonctionnalités attendues, les contraintes et les critères de succès, afin d’aligner les équipes sur ce qui doit être construit et pourquoi.
|
||||
[^2]: Persona : dans le contexte de BMad, une persona désigne un agent IA avec un rôle défini, un style de communication et une expertise spécifiques (ex. Mary l'analyste, Winston l'architecte). Chaque persona garde son "caractère" pendant les interactions.
|
||||
[^2]: Persona : dans le contexte de BMad, un persona désigne un agent IA avec un rôle défini, un style de communication et une expertise spécifiques (ex. Mary l'analyste, Winston l'architecte). Chaque persona garde son "caractère" pendant les interactions.
|
||||
[^3]: Brief : document synthétique qui formalise le contexte, les objectifs, le périmètre et les contraintes d'un projet ou d'une demande, afin d'aligner rapidement les parties prenantes avant le travail détaillé.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: Outils Principaux
|
||||
description: Référence pour toutes les tâches et tous les workflows intégrés disponibles dans chaque installation BMad sans modules supplémentaires.
|
||||
sidebar:
|
||||
order: 2
|
||||
order: 3
|
||||
---
|
||||
|
||||
Chaque installation BMad comprend un ensemble de compétences principales qui peuvent être utilisées conjointement avec tout ce que vous faites — des tâches et des workflows autonomes qui fonctionnent dans tous les projets, tous les modules et toutes les phases. Ceux-ci sont toujours disponibles, quels que soient les modules optionnels que vous installez.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: Modules Officiels
|
||||
description: Modules additionnels pour créer des agents personnalisés, de l'intelligence créative, du développement de jeux et des tests
|
||||
sidebar:
|
||||
order: 4
|
||||
order: 5
|
||||
---
|
||||
|
||||
BMad s'étend via des modules officiels que vous sélectionnez lors de l'installation. Ces modules additionnels fournissent des agents, des workflows et des tâches spécialisés pour des domaines spécifiques, au-delà du noyau intégré et de BMM (suite Agile).
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: Options de Testing
|
||||
description: Comparaison du workflow QA intégré avec le module Test Architect (TEA) pour l'automatisation des tests.
|
||||
sidebar:
|
||||
order: 5
|
||||
order: 6
|
||||
---
|
||||
|
||||
BMad propose deux approches de test : un workflow QA[^1] intégré pour une génération rapide de tests et un module Test Architect installable pour une stratégie de test de qualité entreprise.
|
||||
|
|
|
|||
|
|
@ -21,13 +21,14 @@ Note finale importante : Chaque workflow ci-dessous peut être exécuté directe
|
|||
|
||||
## Phase 1 : Analyse (Optionnelle)
|
||||
|
||||
Explorez l’espace problème et validez les idées avant de vous engager dans la planification.
|
||||
Explorez l’espace problème et validez les idées avant de vous engager dans la planification. [**Découvrez ce que fait chaque outil et quand l’utiliser**](../explanation/analysis-phase.md).
|
||||
|
||||
| Workflow | Objectif | Produit |
|
||||
|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------|---------------------------|
|
||||
| `bmad-brainstorming` | Brainstormez des idées de projet avec l'accompagnement guidé d'un coach de brainstorming | `brainstorming-report.md` |
|
||||
| `bmad-brainstorming` | Brainstormez des idées de projet avec l’accompagnement guidé d’un coach de brainstorming | `brainstorming-report.md` |
|
||||
| `bmad-domain-research`, `bmad-market-research`, `bmad-technical-research` | Validez les hypothèses de marché, techniques ou de domaine | Rapport de recherches |
|
||||
| `bmad-create-product-brief` | Capturez la vision stratégique | `product-brief.md` |
|
||||
| `bmad-product-brief` | Capturez la vision stratégique — idéal lorsque votre concept est clair | `product-brief.md` |
|
||||
| `bmad-prfaq` | Working Backwards — éprouvez et forgez votre concept produit | `prfaq-{project}.md` |
|
||||
|
||||
## Phase 2 : Planification
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ BMad vous aide à construire des logiciels grâce à des workflows guidés avec
|
|||
|
||||
| Phase | Nom | Ce qui se passe |
|
||||
|-------|----------------|----------------------------------------------------------------|
|
||||
| 1 | Analyse | Brainstorming, recherche, product brief *(optionnel)* |
|
||||
| 1 | Analyse | Brainstorming, recherche, product brief ou PRFAQ *(optionnel)* |
|
||||
| 2 | Planification | Créer les exigences (PRD[^1] ou spécification technique) |
|
||||
| 3 | Solutioning | Concevoir l'architecture *(BMad Method/Enterprise uniquement)* |
|
||||
| 4 | Implémentation | Construire epic[^2] par epic, story[^3] par story |
|
||||
|
|
@ -114,7 +114,7 @@ BMad-Help détectera ce que vous avez accompli et recommandera exactement quoi f
|
|||
:::
|
||||
|
||||
:::note[Comment charger les agents et exécuter les workflows]
|
||||
Chaque workflow possède une **skill** que vous invoquez par nom dans votre IDE (par ex., `bmad-create-prd`). Votre outil IA reconnaîtra le nom `bmad-*` et l'exécutera.
|
||||
Chaque workflow possède une **skill** que vous invoquez par nom dans votre IDE (par ex., `bmad-create-prd`). Votre outil IA reconnaîtra le nom `bmad-*` et l'exécutera — vous n'avez pas besoin de charger les agents séparément. Vous pouvez aussi invoquer directement une skill d'agent pour une conversation générale (par ex., `bmad-agent-pm` pour l'agent PM).
|
||||
:::
|
||||
|
||||
:::caution[Nouveaux chats]
|
||||
|
|
@ -133,29 +133,32 @@ Créez-le manuellement dans `_bmad-output/project-context.md` ou générez-le ap
|
|||
|
||||
### Phase 1 : Analyse (Optionnel)
|
||||
|
||||
Tous les workflows de cette phase sont optionnels :
|
||||
Tous les workflows de cette phase sont optionnels. [**Pas sûr de quel outil utiliser ?**](../explanation/analysis-phase.md)
|
||||
- **brainstorming** (`bmad-brainstorming`) — Idéation guidée
|
||||
- **research** (`bmad-market-research` / `bmad-domain-research` / `bmad-technical-research`) — Recherche marché, domaine et technique
|
||||
- **create-product-brief** (`bmad-create-product-brief`) — Document de base recommandé
|
||||
- **product-brief** (`bmad-product-brief`) — Document de base recommandé lorsque votre concept est clair
|
||||
- **prfaq** (`bmad-prfaq`) — Défi Working Backwards pour éprouver et forger votre concept produit
|
||||
|
||||
### Phase 2 : Planification (Requis)
|
||||
|
||||
**Pour les voies BMad Method et Enterprise :**
|
||||
1. Exécutez `bmad-create-prd` dans un nouveau chat
|
||||
2. Sortie : `PRD.md`
|
||||
1. Invoquez l'**agent PM** (`bmad-agent-pm`) dans un nouveau chat
|
||||
2. Exécutez le workflow `bmad-create-prd` (`bmad-create-prd`)
|
||||
3. Sortie : `PRD.md`
|
||||
|
||||
**Pour la voie Quick Dev :**
|
||||
- Utilisez le workflow `bmad-quick-dev` (`bmad-quick-dev`) à la place du PRD, puis passez à l'implémentation
|
||||
- Exécutez `bmad-quick-dev` — il gère la planification et l'implémentation dans un seul workflow, passez directement à l'implémentation
|
||||
|
||||
:::note[Design UX (Optionnel)]
|
||||
Si votre projet a une interface utilisateur, exécutez le workflow de design UX (`bmad-create-ux-design`) après avoir créé votre PRD.
|
||||
Si votre projet a une interface utilisateur, invoquez l'**agent Designer UX** (`bmad-agent-ux-designer`) et exécutez le workflow de design UX (`bmad-create-ux-design`) après avoir créé votre PRD.
|
||||
:::
|
||||
|
||||
### Phase 3 : Solutioning (méthode BMad/Enterprise)
|
||||
|
||||
**Créer l'Architecture**
|
||||
1. Exécutez `bmad-create-architecture` dans un nouveau chat
|
||||
2. Sortie : Document d'architecture avec les décisions techniques
|
||||
1. Invoquez l'**agent Architecte** (`bmad-agent-architect`) dans un nouveau chat
|
||||
2. Exécutez `bmad-create-architecture` (`bmad-create-architecture`)
|
||||
3. Sortie : Document d'architecture avec les décisions techniques
|
||||
|
||||
**Créer les Epics et Stories**
|
||||
|
||||
|
|
@ -163,12 +166,14 @@ Si votre projet a une interface utilisateur, exécutez le workflow de design UX
|
|||
Les epics et stories sont maintenant créés *après* l'architecture. Cela produit des stories de meilleure qualité car les décisions d'architecture (base de données, patterns d'API, pile technologique) affectent directement la façon dont le travail doit être décomposé.
|
||||
:::
|
||||
|
||||
1. Exécutez `bmad-create-epics-and-stories` dans un nouveau chat
|
||||
2. Le workflow utilise à la fois le PRD et l'Architecture pour créer des stories techniquement éclairées
|
||||
1. Invoquez l'**agent PM** (`bmad-agent-pm`) dans un nouveau chat
|
||||
2. Exécutez `bmad-create-epics-and-stories` (`bmad-create-epics-and-stories`)
|
||||
3. Le workflow utilise à la fois le PRD et l'Architecture pour créer des stories techniquement éclairées
|
||||
|
||||
**Vérification de préparation à l'implémentation** *(Hautement recommandé)*
|
||||
1. Exécutez `bmad-check-implementation-readiness` dans un nouveau chat
|
||||
2. Valide la cohérence entre tous les documents de planification
|
||||
1. Invoquez l'**agent Architecte** (`bmad-agent-architect`) dans un nouveau chat
|
||||
2. Exécutez `bmad-check-implementation-readiness` (`bmad-check-implementation-readiness`)
|
||||
3. Valide la cohérence entre tous les documents de planification
|
||||
|
||||
## Étape 2 : Construire votre projet
|
||||
|
||||
|
|
@ -176,19 +181,19 @@ Une fois la planification terminée, passez à l'implémentation. **Chaque workf
|
|||
|
||||
### Initialiser la planification de sprint
|
||||
|
||||
Exécutez `bmad-sprint-planning` dans un nouveau chat. Cela crée `sprint-status.yaml` pour suivre tous les epics et stories.
|
||||
Invoquez **l’agent Développeur** (`bmad-agent-dev`) et lancez `bmad-sprint-planning`. Cela crée `sprint-status.yaml` pour suivre tous les epics et stories.
|
||||
|
||||
### Le cycle de construction
|
||||
|
||||
Pour chaque story, répétez ce cycle avec de nouveaux chats :
|
||||
|
||||
| Étape | Workflow | Commande | Objectif |
|
||||
| ----- | --------------------- | --------------------- | ----------------------------------- |
|
||||
| 1 | `bmad-create-story` | `bmad-create-story` | Créer le fichier story depuis l'epic |
|
||||
| 2 | `bmad-dev-story` | `bmad-dev-story` | Implémenter la story |
|
||||
| 3 | `bmad-code-review` | `bmad-code-review` | Validation de qualité *(recommandé)* |
|
||||
| Étape | AGENT | Workflow | Commande | Objectif |
|
||||
|-------|-------|---------------------|---------------------|--------------------------------------|
|
||||
| 1 | DEV | `bmad-create-story` | `bmad-create-story` | Créer le fichier story depuis l'epic |
|
||||
| 2 | DEV | `bmad-dev-story` | `bmad-dev-story` | Implémenter la story |
|
||||
| 3 | DEV | `bmad-code-review` | `bmad-code-review` | Validation de qualité *(recommandé)* |
|
||||
|
||||
Après avoir terminé toutes les stories d'un epic, exécutez `bmad-retrospective` dans un nouveau chat.
|
||||
Après avoir terminé toutes les stories d'un epic, invoquez **l’agent Développeur** (`bmad-agent-dev`), et exécutez `bmad-retrospective`.
|
||||
|
||||
## Ce que vous avez accompli
|
||||
|
||||
|
|
@ -217,18 +222,18 @@ your-project/
|
|||
|
||||
## Référence rapide
|
||||
|
||||
| Workflow | Commande | Objectif |
|
||||
| ------------------------------------- | ------------------------------------------- | ------------------------------------------------ |
|
||||
| **`bmad-help`** ⭐ | `bmad-help` | **Votre guide intelligent — posez n'importe quelle question !** |
|
||||
| `bmad-create-prd` | `bmad-create-prd` | Créer le document d'exigences produit |
|
||||
| `bmad-create-architecture` | `bmad-create-architecture` | Créer le document d'architecture |
|
||||
| `bmad-generate-project-context` | `bmad-generate-project-context` | Créer le fichier de contexte projet |
|
||||
| `bmad-create-epics-and-stories` | `bmad-create-epics-and-stories` | Décomposer le PRD en epics |
|
||||
| `bmad-check-implementation-readiness` | `bmad-check-implementation-readiness` | Valider la cohérence de planification |
|
||||
| `bmad-sprint-planning` | `bmad-sprint-planning` | Initialiser le suivi de sprint |
|
||||
| `bmad-create-story` | `bmad-create-story` | Créer un fichier story |
|
||||
| `bmad-dev-story` | `bmad-dev-story` | Implémenter une story |
|
||||
| `bmad-code-review` | `bmad-code-review` | Revoir le code implémenté |
|
||||
| Workflow | Commande | Agent | Objectif |
|
||||
|---------------------------------------|---------------------------------------|-----------|-----------------------------------------------------------------|
|
||||
| **`bmad-help`** ⭐ | `bmad-help` | Tous | **Votre guide intelligent — posez n'importe quelle question !** |
|
||||
| `bmad-create-prd` | `bmad-create-prd` | PM | Créer le document d'exigences produit |
|
||||
| `bmad-create-architecture` | `bmad-create-architecture` | Architect | Créer le document d'architecture |
|
||||
| `bmad-generate-project-context` | `bmad-generate-project-context` | Analyst | Créer le fichier de contexte projet |
|
||||
| `bmad-create-epics-and-stories` | `bmad-create-epics-and-stories` | PM | Décomposer le PRD en epics |
|
||||
| `bmad-check-implementation-readiness` | `bmad-check-implementation-readiness` | Architect | Valider la cohérence de planification |
|
||||
| `bmad-sprint-planning` | `bmad-sprint-planning` | DEV | Initialiser le suivi de sprint |
|
||||
| `bmad-create-story` | `bmad-create-story` | DEV | Créer un fichier story |
|
||||
| `bmad-dev-story` | `bmad-dev-story` | DEV | Implémenter une story |
|
||||
| `bmad-code-review` | `bmad-code-review` | DEV | Revoir le code implémenté |
|
||||
|
||||
## Questions fréquentes
|
||||
|
||||
|
|
@ -236,7 +241,7 @@ your-project/
|
|||
Uniquement pour les voies méthode BMad et Enterprise. Quick Dev passe directement de la spécification technique (spec) à l'implémentation.
|
||||
|
||||
**Puis-je modifier mon plan plus tard ?**
|
||||
Oui. Utilisez `bmad-correct-course` pour gérer les changements de périmètre.
|
||||
Oui. Utilisez `bmad-correct-course` pour gérer les changements de périmètre en cours d’implémentation.
|
||||
|
||||
**Et si je veux d'abord faire du brainstorming ?**
|
||||
Invoquez l'agent Analyst (`bmad-agent-analyst`) et exécutez `bmad-brainstorming` (`bmad-brainstorming`) avant de commencer votre PRD.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ This page lists the default BMM (Agile suite) agents that install with BMad Meth
|
|||
|
||||
| Agent | Skill ID | Triggers | Primary workflows |
|
||||
| --------------------------- | -------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `RS`, `CB`, `WB`, `DP` | Brainstorm Project, Research, Create Brief, PRFAQ Challenge, Document Project |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `MR`, `DR`, `TR`, `CB`, `WB`, `DP` | Brainstorm, Market Research, Domain Research, Technical Research, Create Brief, PRFAQ Challenge, Document Project |
|
||||
| Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course |
|
||||
| Architect (Winston) | `bmad-architect` | `CA`, `IR` | Create Architecture, Implementation Readiness |
|
||||
| Developer (Amelia) | `bmad-agent-dev` | `DS`, `QD`, `QA`, `CR`, `SP`, `CS`, `ER` | Dev Story, Quick Dev, QA Test Generation, Code Review, Sprint Planning, Create Story, Epic Retrospective |
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ Workflow skills run a structured, multi-step process without loading an agent pe
|
|||
| Example skill | Purpose |
|
||||
| --- | --- |
|
||||
| `bmad-product-brief` | Create a product brief — guided discovery when your concept is clear |
|
||||
| `bmad-prfaq` | Working Backwards PRFAQ challenge to stress-test your product concept |
|
||||
| `bmad-prfaq` | [Working Backwards PRFAQ](../explanation/analysis-phase.md#prfaq-working-backwards) challenge to stress-test your product concept |
|
||||
| `bmad-create-prd` | Create a Product Requirements Document |
|
||||
| `bmad-create-architecture` | Design system architecture |
|
||||
| `bmad-create-epics-and-stories` | Create epics and stories |
|
||||
|
|
|
|||
|
|
@ -1,53 +1,53 @@
|
|||
---
|
||||
title: "Giai đoạn Analysis: từ ý tưởng đến nền tảng"
|
||||
description: Brainstorming, research, product brief và PRFAQ là gì, và nên dùng từng công cụ khi nào
|
||||
title: "Giai đoạn phân tích: từ ý tưởng đến nền tảng"
|
||||
description: Động não, nghiên cứu, product brief và PRFAQ là gì, và nên dùng từng công cụ khi nào
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
Giai đoạn Analysis (Phase 1) giúp bạn suy nghĩ rõ ràng về sản phẩm trước khi cam kết bắt tay vào xây dựng. Mọi công cụ trong giai đoạn này đều là tùy chọn, nhưng nếu bỏ qua toàn bộ phần analysis thì PRD của bạn sẽ được dựng trên giả định thay vì insight.
|
||||
Giai đoạn phân tích (giai đoạn 1) giúp bạn suy nghĩ rõ ràng về sản phẩm trước khi cam kết bắt tay vào xây dựng. Mọi công cụ trong giai đoạn này đều là tùy chọn, nhưng nếu bỏ qua toàn bộ phần phân tích thì PRD của bạn sẽ được dựng trên giả định thay vì hiểu biết thực chất.
|
||||
|
||||
## Vì sao cần Analysis trước Planning?
|
||||
## Vì sao cần phân tích trước khi lập kế hoạch?
|
||||
|
||||
PRD trả lời câu hỏi "chúng ta nên xây gì và vì sao?". Nếu đầu vào của nó là những suy nghĩ mơ hồ, bạn sẽ nhận lại một PRD mơ hồ, và mọi tài liệu phía sau đều kế thừa chính sự mơ hồ đó. Kiến trúc dựng trên một PRD yếu sẽ đặt cược sai về mặt kỹ thuật. Stories sinh ra từ một kiến trúc yếu sẽ bỏ sót edge case. Chi phí sẽ dồn lên theo từng tầng.
|
||||
PRD trả lời câu hỏi "chúng ta nên xây gì và vì sao?". Nếu đầu vào của nó là những suy nghĩ mơ hồ, bạn sẽ nhận lại một PRD mơ hồ, và mọi tài liệu phía sau đều kế thừa chính sự mơ hồ đó. Kiến trúc dựng trên một PRD yếu sẽ đặt cược sai về mặt kỹ thuật. Các story sinh ra từ một kiến trúc yếu sẽ bỏ sót trường hợp biên. Chi phí sẽ dồn lên theo từng tầng.
|
||||
|
||||
Các công cụ analysis tồn tại để làm PRD của bạn sắc bén hơn. Chúng tiếp cận vấn đề từ nhiều góc độ khác nhau: khám phá sáng tạo, thực tế thị trường, độ rõ ràng về khách hàng, tính khả thi. Nhờ vậy, đến khi bạn ngồi xuống làm việc với PM agent, bạn đã biết mình đang xây cái gì và cho ai.
|
||||
Các công cụ phân tích tồn tại để làm PRD của bạn sắc bén hơn. Chúng tiếp cận vấn đề từ nhiều góc độ khác nhau: khám phá sáng tạo, thực tế thị trường, độ rõ ràng về khách hàng, tính khả thi. Nhờ vậy, đến khi bạn ngồi xuống làm việc với agent PM, bạn đã biết mình đang xây cái gì và cho ai.
|
||||
|
||||
## Các công cụ
|
||||
|
||||
### Brainstorming
|
||||
### Động não
|
||||
|
||||
**Nó là gì.** Một phiên sáng tạo có điều phối, sử dụng các kỹ thuật ideation đã được kiểm chứng. AI đóng vai trò như người huấn luyện, kéo ý tưởng ra từ bạn thông qua các bài tập có cấu trúc, chứ không nghĩ thay cho bạn.
|
||||
**Nó là gì.** Một phiên sáng tạo có điều phối, sử dụng các kỹ thuật phát ý tưởng đã được kiểm chứng. AI đóng vai trò như người huấn luyện, kéo ý tưởng ra từ bạn thông qua các bài tập có cấu trúc, chứ không nghĩ thay cho bạn.
|
||||
|
||||
**Vì sao nó có mặt ở đây.** Ý tưởng thô cần không gian để phát triển trước khi bị khóa cứng thành requirement. Brainstorming tạo ra khoảng không đó. Nó đặc biệt có giá trị khi bạn có một miền vấn đề nhưng chưa có lời giải rõ ràng, hoặc khi bạn muốn khám phá nhiều hướng trước khi commit.
|
||||
**Vì sao nó có mặt ở đây.** Ý tưởng thô cần không gian để phát triển trước khi bị khóa cứng thành yêu cầu. Động não tạo ra khoảng không đó. Nó đặc biệt có giá trị khi bạn có một miền vấn đề nhưng chưa có lời giải rõ ràng, hoặc khi bạn muốn khám phá nhiều hướng trước khi cam kết.
|
||||
|
||||
**Khi nào nên dùng.** Bạn có một hình dung mơ hồ về thứ mình muốn xây nhưng chưa kết tinh được thành khái niệm rõ ràng. Hoặc bạn đã có concept ban đầu nhưng muốn pressure-test nó với các phương án thay thế.
|
||||
**Khi nào nên dùng.** Bạn có một hình dung mơ hồ về thứ mình muốn xây nhưng chưa kết tinh được thành khái niệm rõ ràng. Hoặc bạn đã có ý tưởng ban đầu nhưng muốn kiểm chứng độ vững của nó bằng các phương án thay thế.
|
||||
|
||||
Xem [Brainstorming](./brainstorming.md) để hiểu sâu hơn về cách một phiên làm việc diễn ra.
|
||||
|
||||
### Research (Thị trường, miền nghiệp vụ, kỹ thuật)
|
||||
### Nghiên cứu (thị trường, miền nghiệp vụ, kỹ thuật)
|
||||
|
||||
**Nó là gì.** Ba workflow nghiên cứu tập trung vào các chiều khác nhau của ý tưởng. Market research xem xét đối thủ, xu hướng và cảm nhận của người dùng. Domain research xây dựng hiểu biết về miền nghiệp vụ và thuật ngữ. Technical research đánh giá tính khả thi, các lựa chọn kiến trúc và hướng triển khai.
|
||||
**Nó là gì.** Ba quy trình nghiên cứu tập trung vào các chiều khác nhau của ý tưởng. Nghiên cứu thị trường xem xét đối thủ, xu hướng và cảm nhận của người dùng. Nghiên cứu miền nghiệp vụ xây dựng hiểu biết về lĩnh vực và thuật ngữ. Nghiên cứu kỹ thuật đánh giá tính khả thi, các lựa chọn kiến trúc và hướng triển khai.
|
||||
|
||||
**Vì sao nó có mặt ở đây.** Xây dựng dựa trên giả định là con đường nhanh nhất để tạo ra thứ chẳng ai cần. Research đặt concept của bạn xuống mặt đất: đối thủ nào đã tồn tại, người dùng thực sự đang vật lộn với điều gì, điều gì khả thi về kỹ thuật, và bạn sẽ phải đối mặt với những ràng buộc đặc thù ngành nào.
|
||||
**Vì sao nó có mặt ở đây.** Xây dựng dựa trên giả định là con đường nhanh nhất để tạo ra thứ chẳng ai cần. Nghiên cứu đặt ý tưởng của bạn xuống mặt đất: đối thủ nào đã tồn tại, người dùng thực sự đang vật lộn với điều gì, điều gì khả thi về kỹ thuật, và bạn sẽ phải đối mặt với những ràng buộc đặc thù ngành nào.
|
||||
|
||||
**Khi nào nên dùng.** Bạn đang bước vào một miền mới, nghi ngờ có đối thủ nhưng chưa lập bản đồ được, hoặc concept của bạn phụ thuộc vào những năng lực kỹ thuật mà bạn chưa kiểm chứng. Có thể chạy một, hai, hoặc cả ba; mỗi workflow đều đứng độc lập.
|
||||
**Khi nào nên dùng.** Bạn đang bước vào một miền mới, nghi ngờ có đối thủ nhưng chưa lập bản đồ được, hoặc ý tưởng của bạn phụ thuộc vào những năng lực kỹ thuật mà bạn chưa kiểm chứng. Có thể chạy một, hai, hoặc cả ba; mỗi quy trình đều đứng độc lập.
|
||||
|
||||
### Product Brief
|
||||
|
||||
**Nó là gì.** Một phiên discovery có hướng dẫn, tạo ra bản tóm tắt điều hành 1-2 trang cho concept sản phẩm của bạn. AI đóng vai trò Business Analyst cộng tác, giúp bạn diễn đạt tầm nhìn, đối tượng mục tiêu, giá trị cốt lõi và phạm vi.
|
||||
|
||||
**Vì sao nó có mặt ở đây.** Product brief là con đường nhẹ nhàng hơn để đi vào planning. Nó ghi lại tầm nhìn chiến lược của bạn theo định dạng có cấu trúc và đưa thẳng vào quá trình tạo PRD. Nó hoạt động tốt nhất khi bạn đã có niềm tin tương đối chắc vào concept của mình: bạn biết khách hàng là ai, vấn đề là gì, và đại khái muốn xây gì. Brief sẽ tổ chức lại và làm sắc nét lối suy nghĩ đó.
|
||||
**Vì sao nó có mặt ở đây.** Product brief là con đường nhẹ nhàng hơn để đi vào giai đoạn lập kế hoạch. Nó ghi lại tầm nhìn chiến lược của bạn theo định dạng có cấu trúc và đưa thẳng vào quá trình tạo PRD. Nó hoạt động tốt nhất khi bạn đã có niềm tin tương đối chắc vào ý tưởng của mình: bạn biết khách hàng là ai, vấn đề là gì, và đại khái muốn xây gì. Brief sẽ tổ chức lại và làm sắc nét lối suy nghĩ đó.
|
||||
|
||||
**Khi nào nên dùng.** Concept của bạn đã tương đối rõ và bạn muốn ghi lại nó một cách hiệu quả trước khi tạo PRD. Bạn tin vào hướng đi hiện tại và không cần bị thách thức giả định một cách quá quyết liệt.
|
||||
**Khi nào nên dùng.** Ý tưởng của bạn đã tương đối rõ và bạn muốn ghi lại nó một cách hiệu quả trước khi tạo PRD. Bạn tin vào hướng đi hiện tại và không cần bị thách thức giả định một cách quá quyết liệt.
|
||||
|
||||
### PRFAQ (Working Backwards)
|
||||
|
||||
**Nó là gì.** Phương pháp Working Backwards của Amazon được chuyển thành một thử thách tương tác. Bạn viết thông cáo báo chí công bố sản phẩm hoàn thiện trước khi tồn tại dù chỉ một dòng code, rồi trả lời những câu hỏi khó nhất mà khách hàng và stakeholder sẽ đặt ra. AI đóng vai trò product coach dai dẳng nhưng mang tính xây dựng.
|
||||
|
||||
**Vì sao nó có mặt ở đây.** PRFAQ là con đường nghiêm ngặt hơn để đi vào planning. Nó buộc bạn đạt đến sự rõ ràng theo hướng customer-first bằng cách bắt bạn bảo vệ từng phát biểu. Nếu bạn không viết nổi một thông cáo báo chí đủ thuyết phục, sản phẩm đó chưa sẵn sàng. Nếu phần FAQ lộ ra những khoảng trống, đó chính là những khoảng trống mà bạn sẽ phát hiện muộn hơn rất nhiều, và với chi phí lớn hơn nhiều, trong lúc triển khai. Bài kiểm tra này bóc tách lối suy nghĩ yếu ngay từ sớm, khi chi phí sửa còn rẻ nhất.
|
||||
**Vì sao nó có mặt ở đây.** PRFAQ là con đường nghiêm ngặt hơn để đi vào giai đoạn lập kế hoạch. Nó buộc bạn đạt đến sự rõ ràng theo hướng lấy khách hàng làm trung tâm bằng cách bắt bạn bảo vệ từng phát biểu. Nếu bạn không viết nổi một thông cáo báo chí đủ thuyết phục, sản phẩm đó chưa sẵn sàng. Nếu phần FAQ lộ ra những khoảng trống, đó chính là những khoảng trống mà bạn sẽ phát hiện muộn hơn rất nhiều, và với chi phí lớn hơn nhiều, trong lúc triển khai. Bài kiểm tra này bóc tách lối suy nghĩ yếu ngay từ sớm, khi chi phí sửa còn rẻ nhất.
|
||||
|
||||
**Khi nào nên dùng.** Bạn muốn stress-test concept trước khi commit tài nguyên. Bạn chưa chắc người dùng có thực sự quan tâm hay không. Bạn muốn xác nhận rằng mình có thể diễn đạt một value proposition rõ ràng và có thể bảo vệ được. Hoặc đơn giản là bạn muốn dùng sự kỷ luật của Working Backwards để làm suy nghĩ của mình sắc bén hơn.
|
||||
**Khi nào nên dùng.** Bạn muốn kiểm tra độ vững của ý tưởng trước khi cam kết tài nguyên. Bạn chưa chắc người dùng có thực sự quan tâm hay không. Bạn muốn xác nhận rằng mình có thể diễn đạt một giá trị cốt lõi rõ ràng và có thể bảo vệ được. Hoặc đơn giản là bạn muốn dùng sự kỷ luật của Working Backwards để làm suy nghĩ của mình sắc bén hơn.
|
||||
|
||||
## Tôi nên dùng cái nào?
|
||||
|
||||
|
|
@ -65,6 +65,6 @@ Product Brief và PRFAQ đều tạo ra đầu vào cho PRD. Hãy chọn một t
|
|||
Hãy chạy `bmad-help` và mô tả tình huống của bạn. Nó sẽ gợi ý điểm bắt đầu phù hợp dựa trên những gì bạn đã làm và điều bạn đang muốn đạt được.
|
||||
:::
|
||||
|
||||
## Sau Analysis thì chuyện gì xảy ra?
|
||||
## Sau giai đoạn phân tích thì chuyện gì xảy ra?
|
||||
|
||||
Output từ Analysis đi thẳng vào Phase 2 (Planning). Workflow tạo PRD chấp nhận product brief, tài liệu PRFAQ, kết quả research và báo cáo brainstorming làm đầu vào. Nó sẽ tổng hợp bất cứ thứ gì bạn đã tạo thành các requirement có cấu trúc. Bạn làm analysis càng kỹ, PRD của bạn càng sắc.
|
||||
Đầu ra từ giai đoạn phân tích đi thẳng vào giai đoạn 2, lập kế hoạch. Quy trình tạo PRD chấp nhận product brief, tài liệu PRFAQ, kết quả nghiên cứu và báo cáo động não làm đầu vào. Nó sẽ tổng hợp bất cứ thứ gì bạn đã tạo thành các yêu cầu có cấu trúc. Bạn làm phân tích càng kỹ, PRD của bạn càng sắc.
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Party Mode"
|
||||
title: "Chế độ Party"
|
||||
description: Cộng tác đa agent - đưa tất cả agent AI vào cùng một cuộc trò chuyện
|
||||
sidebar:
|
||||
order: 7
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Project Context"
|
||||
title: "Bối cảnh dự án"
|
||||
description: Cách project-context.md định hướng các agent AI theo quy tắc và ưu tiên của dự án
|
||||
sidebar:
|
||||
order: 7
|
||||
|
|
|
|||
|
|
@ -1,73 +1,73 @@
|
|||
---
|
||||
title: "Quick Dev"
|
||||
description: Giảm ma sát human-in-the-loop mà vẫn giữ các checkpoint bảo vệ chất lượng output
|
||||
title: "Phát triển nhanh"
|
||||
description: Giảm ma sát có người trong vòng lặp mà vẫn giữ các điểm kiểm tra bảo vệ chất lượng đầu ra
|
||||
sidebar:
|
||||
order: 2
|
||||
---
|
||||
|
||||
Đưa ý định vào, nhận thay đổi mã nguồn ra, với số lần cần con người nhảy vào giữa quy trình ít nhất có thể - nhưng không đánh đổi chất lượng.
|
||||
|
||||
Nó cho phép model tự vận hành lâu hơn giữa các checkpoint, rồi chỉ đưa con người quay lại khi tác vụ không thể tiếp tục an toàn nếu thiếu phán đoán của con người, hoặc khi đã đến lúc review kết quả cuối.
|
||||
Nó cho phép mô hình tự vận hành lâu hơn giữa các điểm kiểm tra, rồi chỉ đưa con người quay lại khi tác vụ không thể tiếp tục an toàn nếu thiếu phán đoán của con người, hoặc khi đã đến lúc rà soát kết quả cuối.
|
||||
|
||||

|
||||
|
||||
## Vì sao nó tồn tại
|
||||
|
||||
Các lượt human-in-the-loop vừa cần thiết vừa tốn kém.
|
||||
Các lượt có người trong vòng lặp vừa cần thiết vừa tốn kém.
|
||||
|
||||
LLM hiện tại vẫn thất bại theo những cách dễ đoán: hiểu sai ý định, tự điền vào khoảng trống bằng những phán đoán tự tin, lệch sang công việc không liên quan, và tạo ra các bản review nhiễu. Đồng thời, việc cần con người nhảy vào liên tục làm giảm tốc độ phát triển. Sự chú ý của con người là nút thắt.
|
||||
|
||||
`bmad-quick-dev` cân bằng lại đánh đổi đó. Nó tin model có thể chạy tự chủ lâu hơn, nhưng chỉ sau khi workflow đã tạo được một ranh giới đủ mạnh để làm điều đó an toàn.
|
||||
`bmad-quick-dev` cân bằng lại đánh đổi đó. Nó tin mô hình có thể chạy tự chủ lâu hơn, nhưng chỉ sau khi quy trình đã tạo được một ranh giới đủ mạnh để làm điều đó an toàn.
|
||||
|
||||
## Thiết kế cốt lõi
|
||||
|
||||
### 1. Nén ý định trước
|
||||
|
||||
Workflow bắt đầu bằng việc để con người và model nén yêu cầu thành một mục tiêu thống nhất. Đầu vào có thể bắt đầu như một ý định thô, nhưng trước khi workflow tự vận hành thì nó phải đủ nhỏ, đủ rõ ràng, và đủ ít mâu thuẫn để có thể thực thi.
|
||||
Quy trình bắt đầu bằng việc để con người và mô hình nén yêu cầu thành một mục tiêu thống nhất. Đầu vào có thể bắt đầu như một ý định thô, nhưng trước khi quy trình tự vận hành thì nó phải đủ nhỏ, đủ rõ ràng, và đủ ít mâu thuẫn để có thể thực thi.
|
||||
|
||||
Ý định có thể đến từ nhiều dạng: vài cụm từ, liên kết bug tracker, output từ plan mode, đoạn văn bản copy từ phiên chat, hoặc thậm chí một số story trong `epics.md` của chính BMAD. Ở trường hợp cuối, workflow không hiểu được ngữ nghĩa theo dõi story của BMAD, nhưng vẫn có thể lấy chính story đó và tiếp tục.
|
||||
Ý định có thể đến từ nhiều dạng: vài cụm từ, liên kết trình theo dõi lỗi, đầu ra từ chế độ lập kế hoạch, đoạn văn bản sao chép từ phiên chat, hoặc thậm chí một số story trong `epics.md` của chính BMAD. Ở trường hợp cuối, quy trình không hiểu được ngữ nghĩa theo dõi story của BMAD, nhưng vẫn có thể lấy chính story đó và tiếp tục.
|
||||
|
||||
Workflow này không loại bỏ quyền kiểm soát của con người. Nó chuyển nó về một số thời điểm có giá trị cao:
|
||||
Quy trình này không loại bỏ quyền kiểm soát của con người. Nó chuyển nó về một số thời điểm có giá trị cao:
|
||||
|
||||
- **Làm rõ ý định** - biến một yêu cầu lộn xộn thành một mục tiêu thống nhất, không mâu thuẫn ngầm
|
||||
- **Phê duyệt spec** - xác nhận rằng cách hiểu đã đóng băng là đúng thứ cần xây
|
||||
- **Review sản phẩm cuối** - checkpoint chính, nơi con người quyết định kết quả cuối có chấp nhận được hay không
|
||||
- **Phê duyệt đặc tả** - xác nhận rằng cách hiểu đã được chốt là đúng thứ cần xây
|
||||
- **Rà soát sản phẩm cuối** - điểm kiểm tra chính, nơi con người quyết định kết quả cuối có chấp nhận được hay không
|
||||
|
||||
### 2. Định tuyến theo con đường an toàn nhỏ nhất
|
||||
|
||||
Khi mục tiêu đã rõ, workflow sẽ quyết định đây có phải thay đổi one-shot thật sự hay cần đi theo đường đầy đủ hơn. Những thay đổi nhỏ, blast radius gần như bằng 0 có thể đi thẳng vào triển khai. Còn lại sẽ đi qua lập kế hoạch để model có được một ranh giới mạnh hơn trước khi tự chạy lâu hơn.
|
||||
Khi mục tiêu đã rõ, quy trình sẽ quyết định đây có phải thay đổi thực hiện một lần là xong hay cần đi theo đường đầy đủ hơn. Những thay đổi nhỏ, phạm vi ảnh hưởng gần như bằng 0 có thể đi thẳng vào triển khai. Còn lại sẽ đi qua lập kế hoạch để mô hình có được một ranh giới mạnh hơn trước khi tự chạy lâu hơn.
|
||||
|
||||
### 3. Chạy lâu hơn với ít giám sát hơn
|
||||
|
||||
Sau quyết định định tuyến đó, model có thể tự gánh thêm công việc. Trên con đường đầy đủ, spec đã được phê duyệt trở thành ranh giới mà model sẽ thực thi với ít giám sát hơn, và đó chính là mục tiêu của thiết kế này.
|
||||
Sau quyết định định tuyến đó, mô hình có thể tự gánh thêm công việc. Trên con đường đầy đủ, đặc tả đã được phê duyệt trở thành ranh giới mà mô hình sẽ thực thi với ít giám sát hơn, và đó chính là mục tiêu của thiết kế này.
|
||||
|
||||
### 4. Chẩn đoán lỗi ở đúng tầng
|
||||
|
||||
Nếu triển khai sai vì ý định sai, vậy sửa code không phải cách fix đúng. Nếu code sai vì spec yếu, thì vá diff cũng không phải cách fix đúng. Workflow được thiết kế để chẩn đoán lỗi đã đi vào hệ thống từ tầng nào, quay lại đúng tầng đó, rồi sinh lại từ đấy.
|
||||
Nếu triển khai sai vì ý định sai, vậy sửa code không phải cách sửa đúng. Nếu code sai vì đặc tả yếu, thì vá diff cũng không phải cách sửa đúng. Quy trình được thiết kế để chẩn đoán lỗi đã đi vào hệ thống từ tầng nào, quay lại đúng tầng đó, rồi sinh lại từ đấy.
|
||||
|
||||
Các phát hiện từ review được dùng để xác định vấn đề đến từ ý định, quá trình tạo spec, hay triển khai cục bộ. Chỉ những lỗi thật sự cục bộ mới được sửa tại chỗ.
|
||||
Các phát hiện từ bước rà soát được dùng để xác định vấn đề đến từ ý định, quá trình tạo đặc tả, hay triển khai cục bộ. Chỉ những lỗi thật sự cục bộ mới được sửa tại chỗ.
|
||||
|
||||
### 5. Chỉ đưa con người quay lại khi cần
|
||||
|
||||
Bước interview ý định có human-in-the-loop, nhưng nó không giống một checkpoint lặp đi lặp lại. Workflow cố gắng giảm thiểu những checkpoint lặp lại đó. Sau bước định hình ý định ban đầu, con người chủ yếu quay lại khi workflow không thể tiếp tục an toàn nếu thiếu phán đoán, và ở cuối quy trình để review kết quả.
|
||||
Bước phỏng vấn ý định có người trong vòng lặp, nhưng nó không giống một điểm kiểm tra lặp đi lặp lại. Quy trình cố gắng giảm thiểu những điểm kiểm tra lặp lại đó. Sau bước định hình ý định ban đầu, con người chủ yếu quay lại khi quy trình không thể tiếp tục an toàn nếu thiếu phán đoán, và ở cuối quy trình để rà soát kết quả.
|
||||
|
||||
- **Xử lý khoảng trống của ý định** - quay lại khi review cho thấy workflow không thể suy ra an toàn điều được hàm ý
|
||||
|
||||
Mọi thứ còn lại đều là ứng viên cho việc thực thi tự chủ lâu hơn. Đánh đổi này là có chủ đích. Các pattern cũ tốn nhiều sự chú ý của con người cho việc giám sát liên tục. Quick Dev đặt nhiều niềm tin hơn vào model, nhưng để dành sự chú ý của con người cho những thời điểm mà lý trí con người có đòn bẩy lớn nhất.
|
||||
Mọi thứ còn lại đều là ứng viên cho việc thực thi tự chủ lâu hơn. Đánh đổi này là có chủ đích. Các mẫu cũ tốn nhiều sự chú ý của con người cho việc giám sát liên tục. Quick Dev đặt nhiều niềm tin hơn vào mô hình, nhưng để dành sự chú ý của con người cho những thời điểm mà lý trí con người có đòn bẩy lớn nhất.
|
||||
|
||||
## Vì sao hệ thống review quan trọng
|
||||
|
||||
Giai đoạn review không chỉ để tìm bug. Nó còn để định tuyến cách sửa mà không phá hỏng động lượng.
|
||||
Giai đoạn rà soát không chỉ để tìm lỗi. Nó còn để định tuyến cách sửa mà không phá hỏng động lượng.
|
||||
|
||||
Workflow này hoạt động tốt nhất trên nền tảng có thể spawn subagent, hoặc ít nhất gọi được một LLM khác qua dòng lệnh và đợi kết quả. Nếu nền tảng của bạn không hỗ trợ sẵn, bạn có thể thêm skill để làm việc đó. Các subagent không mang context là một trụ cột trong thiết kế review.
|
||||
Quy trình này hoạt động tốt nhất trên nền tảng có thể tạo subagent, hoặc ít nhất gọi được một LLM khác qua dòng lệnh và đợi kết quả. Nếu nền tảng của bạn không hỗ trợ sẵn, bạn có thể thêm skill để làm việc đó. Các subagent không mang ngữ cảnh là một trụ cột trong thiết kế rà soát.
|
||||
|
||||
Review agentic thường sai theo hai cách:
|
||||
Rà soát kiểu agent thường sai theo hai cách:
|
||||
|
||||
- Tạo quá nhiều phát hiện, buộc con người lọc quá nhiều nhiễu.
|
||||
- Làm lệch thay đổi hiện tại bằng cách kéo vào các vấn đề không liên quan, biến mỗi lần chạy thành một dự án dọn dẹp ad-hoc.
|
||||
- Làm lệch thay đổi hiện tại bằng cách kéo vào các vấn đề không liên quan, biến mỗi lần chạy thành một dự án dọn dẹp chắp vá.
|
||||
|
||||
Quick Dev xử lý cả hai bằng cách coi review là triage.
|
||||
Quick Dev xử lý cả hai bằng cách coi rà soát là bước phân loại.
|
||||
|
||||
Có những phát hiện thuộc về thay đổi hiện tại. Có những phát hiện không thuộc về nó. Nếu một phát hiện chỉ là ngẫu nhiên xuất hiện, không gắn nhân quả với thay đổi đang làm, workflow có thể trì hoãn nó thay vì ép con người xử lý ngay. Điều đó giữ cho mỗi lần chạy tập trung và ngăn các ngả rẽ ngẫu nhiên ăn hết ngân sách chú ý.
|
||||
Có những phát hiện thuộc về thay đổi hiện tại. Có những phát hiện không thuộc về nó. Nếu một phát hiện chỉ là ngẫu nhiên xuất hiện, không gắn nhân quả với thay đổi đang làm, quy trình có thể trì hoãn nó thay vì ép con người xử lý ngay. Điều đó giữ cho mỗi lần chạy tập trung và ngăn các ngả rẽ ngẫu nhiên ăn hết ngân sách chú ý.
|
||||
|
||||
Quá trình triage này đôi khi sẽ không hoàn hảo. Điều đó chấp nhận được. Thường tốt hơn khi đánh giá sai một số phát hiện còn hơn là nhận về hàng ngàn bình luận review giá trị thấp. Hệ thống tối ưu cho chất lượng tín hiệu, không phải độ phủ tuyệt đối.
|
||||
|
|
|
|||
|
|
@ -5,79 +5,27 @@ sidebar:
|
|||
order: 4
|
||||
---
|
||||
|
||||
## Bắt đầu tại đây: BMad-Help
|
||||
Hãy dùng trợ giúp tích hợp sẵn của BMad, tài liệu nguồn, hoặc cộng đồng để tìm câu trả lời, theo thứ tự từ nhanh nhất đến đầy đủ nhất.
|
||||
|
||||
**Cách nhanh nhất để tìm câu trả lời về BMad là dùng skill `bmad-help`.** Đây là công cụ hướng dẫn thông minh có thể trả lời hơn 80% các câu hỏi và có sẵn ngay trong IDE khi bạn làm việc.
|
||||
## 1. Hỏi BMad-Help
|
||||
|
||||
BMad-Help không chỉ là công cụ tra cứu, nó còn:
|
||||
- **Kiểm tra dự án của bạn** để xem những gì đã hoàn thành
|
||||
- **Hiểu ngôn ngữ tự nhiên** - đặt câu hỏi bằng ngôn ngữ bình thường
|
||||
- **Thay đổi theo module đã cài** - hiển thị các lựa chọn liên quan
|
||||
- **Tự động chạy sau workflow** - nói rõ bạn cần làm gì tiếp theo
|
||||
- **Đề xuất tác vụ đầu tiên cần thiết** - không cần đoán nên bắt đầu từ đâu
|
||||
|
||||
### Cách dùng BMad-Help
|
||||
|
||||
Gọi nó trực tiếp trong phiên AI của bạn:
|
||||
Cách nhanh nhất để có câu trả lời. Skill `bmad-help` có sẵn ngay trong phiên AI của bạn và xử lý được hơn 80% câu hỏi. Nó sẽ kiểm tra dự án, nhìn xem bạn đã hoàn thành đến đâu và cho bạn biết nên làm gì tiếp theo.
|
||||
|
||||
```text
|
||||
bmad-help
|
||||
bmad-help Tôi có ý tưởng SaaS và đã biết tất cả tính năng. Tôi nên bắt đầu từ đâu?
|
||||
bmad-help Tôi có những lựa chọn nào cho thiết kế UX?
|
||||
bmad-help Tôi đang bị mắc ở workflow PRD
|
||||
```
|
||||
|
||||
:::tip
|
||||
Bạn cũng có thể dùng `/bmad-help` hoặc `$bmad-help` tùy nền tảng, nhưng chỉ `bmad-help` là cách nên hoạt động mọi nơi.
|
||||
:::
|
||||
|
||||
Kết hợp với câu hỏi ngôn ngữ tự nhiên:
|
||||
## 2. Đi sâu hơn với mã nguồn
|
||||
|
||||
```text
|
||||
bmad-help Tôi có ý tưởng SaaS và đã biết tất cả tính năng. Tôi nên bắt đầu từ đâu?
|
||||
bmad-help Tôi có những lựa chọn nào cho thiết kế UX?
|
||||
bmad-help Tôi đang bị mắc ở workflow PRD
|
||||
bmad-help Cho tôi xem tôi đã làm được gì đến giờ
|
||||
```
|
||||
BMad-Help dựa trên cấu hình bạn đã cài đặt. Nếu bạn cần tìm hiểu nội bộ, lịch sử, hay kiến trúc của BMad, hoặc đang nghiên cứu BMad trước khi cài, hãy để AI đọc trực tiếp mã nguồn.
|
||||
|
||||
BMad-Help sẽ trả lời:
|
||||
- Điều gì được khuyến nghị cho tình huống của bạn
|
||||
- Tác vụ đầu tiên cần thiết là gì
|
||||
- Phần còn lại của quy trình trông thế nào
|
||||
|
||||
## Khi nào nên dùng tài liệu này
|
||||
|
||||
Hãy xem phần này khi:
|
||||
- Bạn muốn hiểu kiến trúc hoặc nội bộ của BMad
|
||||
- Bạn cần câu trả lời nằm ngoài phạm vi BMad-Help cung cấp
|
||||
- Bạn đang nghiên cứu BMad trước khi cài đặt
|
||||
- Bạn muốn tự khám phá source code trực tiếp
|
||||
|
||||
## Các bước thực hiện
|
||||
|
||||
### 1. Chọn nguồn thông tin
|
||||
|
||||
| Nguồn | Phù hợp nhất cho | Ví dụ |
|
||||
| --- | --- | --- |
|
||||
| **Thư mục `_bmad`** | Cách BMad vận hành: agent, workflow, prompt | "PM agent làm gì?" |
|
||||
| **Toàn bộ repo GitHub** | Lịch sử, installer, kiến trúc | "v6 thay đổi gì?" |
|
||||
| **`llms-full.txt`** | Tổng quan nhanh từ tài liệu | "Giải thích bốn giai đoạn của BMad" |
|
||||
|
||||
Thư mục `_bmad` được tạo khi bạn cài đặt BMad. Nếu chưa có, hãy clone repo thay thế.
|
||||
|
||||
### 2. Cho AI của bạn truy cập nguồn thông tin
|
||||
|
||||
**Nếu AI của bạn đọc được tệp (Claude Code, Cursor, ...):**
|
||||
|
||||
- **Đã cài BMad:** Trỏ đến thư mục `_bmad` và hỏi trực tiếp
|
||||
- **Cần bối cảnh sâu hơn:** Clone [repo đầy đủ](https://github.com/bmad-code-org/BMAD-METHOD)
|
||||
|
||||
**Nếu bạn dùng ChatGPT hoặc Claude.ai:**
|
||||
|
||||
Nạp `llms-full.txt` vào phiên làm việc:
|
||||
|
||||
```text
|
||||
https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
|
||||
```
|
||||
|
||||
### 3. Đặt câu hỏi
|
||||
Hãy clone hoặc mở [repo BMAD-METHOD](https://github.com/bmad-code-org/BMAD-METHOD) rồi hỏi AI của bạn về nó. Bất kỳ công cụ nào có hỗ trợ agent như Claude Code, Cursor, Windsurf... đều có thể đọc mã nguồn và trả lời trực tiếp.
|
||||
|
||||
:::note[Ví dụ]
|
||||
**Q:** "Hãy chỉ tôi cách nhanh nhất để xây dựng một thứ gì đó bằng BMad"
|
||||
|
|
@ -85,29 +33,27 @@ https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt
|
|||
**A:** Dùng Quick Flow: Chạy `bmad-quick-dev` - nó sẽ làm rõ ý định, lập kế hoạch, triển khai, review và trình bày kết quả trong một workflow duy nhất, bỏ qua các giai đoạn lập kế hoạch đầy đủ.
|
||||
:::
|
||||
|
||||
## Bạn nhận được gì
|
||||
**Mẹo để có câu trả lời tốt hơn:**
|
||||
|
||||
Các câu trả lời trực tiếp về BMad: agent hoạt động ra sao, workflow làm gì, tại sao cấu trúc lại được tổ chức như vậy, mà không cần chờ người khác trả lời.
|
||||
- **Hãy hỏi thật cụ thể** - "Bước 3 trong workflow PRD làm gì?" sẽ tốt hơn "PRD hoạt động ra sao?"
|
||||
- **Kiểm tra lại những câu trả lời nghe lạ** - LLM đôi khi vẫn sai. Hãy kiểm tra file nguồn hoặc hỏi trên Discord.
|
||||
|
||||
## Mẹo
|
||||
### Không dùng agent? Dùng trang docs
|
||||
|
||||
- **Xác minh những câu trả lời gây bất ngờ** - LLM vẫn có lúc nhầm. Hãy kiểm tra tệp nguồn hoặc hỏi trên Discord.
|
||||
- **Đặt câu hỏi cụ thể** - "Bước 3 trong workflow PRD làm gì?" tốt hơn "PRD hoạt động ra sao?"
|
||||
Nếu AI của bạn không đọc được file cục bộ như ChatGPT hoặc Claude.ai, hãy nạp [llms-full.txt](https://bmad-code-org.github.io/BMAD-METHOD/llms-full.txt) vào phiên làm việc. Đây là bản chụp tài liệu BMad trong một file duy nhất.
|
||||
|
||||
## Vẫn bị mắc?
|
||||
## 3. Hỏi người thật
|
||||
|
||||
Đã thử cách tiếp cận bằng LLM mà vẫn cần trợ giúp? Lúc này bạn đã có một câu hỏi tốt hơn để đem đi hỏi.
|
||||
Nếu cả BMad-Help lẫn mã nguồn vẫn chưa trả lời được câu hỏi của bạn, lúc này bạn đã có một câu hỏi rõ hơn nhiều để đem đi hỏi cộng đồng.
|
||||
|
||||
| Kênh | Dùng cho |
|
||||
| --- | --- |
|
||||
| `#bmad-method-help` | Câu hỏi nhanh (trò chuyện thời gian thực) |
|
||||
| `help-requests` forum | Câu hỏi chi tiết (có thể tìm lại, tồn tại lâu dài) |
|
||||
| `help-requests` forum | Câu hỏi |
|
||||
| `#suggestions-feedback` | Ý tưởng và đề xuất tính năng |
|
||||
| `#report-bugs-and-issues` | Báo cáo lỗi |
|
||||
|
||||
**Discord:** [discord.gg/gk8jAdXWmj](https://discord.gg/gk8jAdXWmj)
|
||||
|
||||
**GitHub Issues:** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues) (dành cho các lỗi rõ ràng)
|
||||
**GitHub Issues:** [github.com/bmad-code-org/BMAD-METHOD/issues](https://github.com/bmad-code-org/BMAD-METHOD/issues)
|
||||
|
||||
*Chính bạn,*
|
||||
*đang mắc kẹt*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Quản lý Project Context"
|
||||
title: "Quản lý bối cảnh dự án"
|
||||
description: Tạo và duy trì project-context.md để định hướng cho các agent AI
|
||||
sidebar:
|
||||
order: 8
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Quick Fixes"
|
||||
title: "Sửa nhanh"
|
||||
description: Cách thực hiện các sửa nhanh và thay đổi ad-hoc
|
||||
sidebar:
|
||||
order: 5
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Agents
|
||||
title: Các agent
|
||||
description: Các agent mặc định của BMM cùng skill ID, trigger menu và workflow chính
|
||||
sidebar:
|
||||
order: 2
|
||||
|
|
@ -17,7 +17,7 @@ Trang này liệt kê các agent mặc định của BMM (bộ Agile suite) đư
|
|||
|
||||
| Agent | Skill ID | Trigger | Workflow chính |
|
||||
| --------------------------- | -------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `RS`, `CB`, `WB`, `DP` | Brainstorm Project, Research, Create Brief, PRFAQ Challenge, Document Project |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`, `MR`, `DR`, `TR`, `CB`, `WB`, `DP` | Brainstorm, Market Research, Domain Research, Technical Research, Create Brief, PRFAQ Challenge, Document Project |
|
||||
| Product Manager (John) | `bmad-pm` | `CP`, `VP`, `EP`, `CE`, `IR`, `CC` | Create/Validate/Edit PRD, Create Epics and Stories, Implementation Readiness, Correct Course |
|
||||
| Architect (Winston) | `bmad-architect` | `CA`, `IR` | Create Architecture, Implementation Readiness |
|
||||
| Developer (Amelia) | `bmad-agent-dev` | `DS`, `QD`, `QA`, `CR`, `SP`, `CS`, `ER` | Dev Story, Quick Dev, QA Test Generation, Code Review, Sprint Planning, Create Story, Epic Retrospective |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Skills
|
||||
title: Các skill
|
||||
description: Tài liệu tham chiếu cho skill của BMad — skill là gì, hoạt động ra sao và tìm ở đâu.
|
||||
sidebar:
|
||||
order: 3
|
||||
|
|
@ -92,7 +92,7 @@ Workflow skills chạy một quy trình có cấu trúc, nhiều bước mà kh
|
|||
| Ví dụ skill | Mục đích |
|
||||
| --- | --- |
|
||||
| `bmad-product-brief` | Tạo product brief — phiên discovery có hướng dẫn khi concept của bạn đã rõ |
|
||||
| `bmad-prfaq` | Bài kiểm tra Working Backwards PRFAQ để stress-test concept sản phẩm |
|
||||
| `bmad-prfaq` | Bài kiểm tra [Working Backwards PRFAQ](../explanation/analysis-phase.md#prfaq-working-backwards) để stress-test concept sản phẩm |
|
||||
| `bmad-create-prd` | Tạo Product Requirements Document |
|
||||
| `bmad-create-architecture` | Thiết kế kiến trúc hệ thống |
|
||||
| `bmad-create-epics-and-stories` | Tạo epics và stories |
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
---
|
||||
title: Core Tools
|
||||
description: Tài liệu tham chiếu cho mọi task và workflow tích hợp sẵn có trong mọi bản cài BMad mà không cần module bổ sung.
|
||||
title: Công cụ cốt lõi
|
||||
description: Tài liệu tham chiếu cho mọi tác vụ và quy trình tích hợp sẵn có trong mọi bản cài BMad mà không cần module bổ sung.
|
||||
sidebar:
|
||||
order: 2
|
||||
---
|
||||
|
||||
Mọi bản cài BMad đều bao gồm một tập core skills có thể dùng cùng với bất cứ việc gì bạn đang làm — các task và workflow độc lập hoạt động xuyên suốt mọi dự án, mọi module và mọi phase. Chúng luôn có sẵn bất kể bạn cài những module tùy chọn nào.
|
||||
Mọi bản cài BMad đều bao gồm một tập skill cốt lõi có thể dùng cùng với bất cứ việc gì bạn đang làm, các tác vụ và quy trình độc lập hoạt động xuyên suốt mọi dự án, mọi module và mọi giai đoạn. Chúng luôn có sẵn bất kể bạn cài những module tùy chọn nào.
|
||||
|
||||
:::tip[Lối đi nhanh]
|
||||
Chạy bất kỳ core tool nào bằng cách gõ tên skill của nó, ví dụ `bmad-help`, trong IDE của bạn. Không cần mở phiên agent trước.
|
||||
Chạy bất kỳ công cụ cốt lõi nào bằng cách gõ tên skill của nó, ví dụ `bmad-help`, trong IDE của bạn. Không cần mở phiên agent trước.
|
||||
:::
|
||||
|
||||
## Tổng Quan
|
||||
|
||||
| Công cụ | Loại | Mục đích |
|
||||
| --- | --- | --- |
|
||||
| [`bmad-help`](#bmad-help) | Task | Nhận hướng dẫn có ngữ cảnh về việc nên làm gì tiếp theo |
|
||||
| [`bmad-brainstorming`](#bmad-brainstorming) | Workflow | Tổ chức các phiên brainstorming có tương tác |
|
||||
| [`bmad-party-mode`](#bmad-party-mode) | Workflow | Điều phối thảo luận nhóm nhiều agent |
|
||||
| [`bmad-distillator`](#bmad-distillator) | Task | Nén tài liệu tối ưu cho LLM mà không mất thông tin |
|
||||
| [`bmad-advanced-elicitation`](#bmad-advanced-elicitation) | Task | Đẩy đầu ra của LLM qua các vòng tinh luyện lặp |
|
||||
| [`bmad-review-adversarial-general`](#bmad-review-adversarial-general) | Task | Review hoài nghi để tìm chỗ thiếu và chỗ sai |
|
||||
| [`bmad-review-edge-case-hunter`](#bmad-review-edge-case-hunter) | Task | Phân tích toàn bộ nhánh rẽ để tìm edge case chưa được xử lý |
|
||||
| [`bmad-editorial-review-prose`](#bmad-editorial-review-prose) | Task | Biên tập câu chữ nhằm tăng độ rõ ràng khi giao tiếp |
|
||||
| [`bmad-editorial-review-structure`](#bmad-editorial-review-structure) | Task | Biên tập cấu trúc — cắt, gộp và tổ chức lại |
|
||||
| [`bmad-shard-doc`](#bmad-shard-doc) | Task | Tách file markdown lớn thành các phần có tổ chức |
|
||||
| [`bmad-index-docs`](#bmad-index-docs) | Task | Tạo hoặc cập nhật mục lục cho toàn bộ tài liệu trong một thư mục |
|
||||
| [`bmad-help`](#bmad-help) | Tác vụ | Nhận hướng dẫn có ngữ cảnh về việc nên làm gì tiếp theo |
|
||||
| [`bmad-brainstorming`](#bmad-brainstorming) | Quy trình | Tổ chức các phiên brainstorming có tương tác |
|
||||
| [`bmad-party-mode`](#bmad-party-mode) | Quy trình | Điều phối thảo luận nhóm nhiều agent |
|
||||
| [`bmad-distillator`](#bmad-distillator) | Tác vụ | Nén tài liệu tối ưu cho LLM mà không mất thông tin |
|
||||
| [`bmad-advanced-elicitation`](#bmad-advanced-elicitation) | Tác vụ | Đẩy đầu ra của LLM qua các vòng tinh luyện lặp |
|
||||
| [`bmad-review-adversarial-general`](#bmad-review-adversarial-general) | Tác vụ | Rà soát hoài nghi để tìm chỗ thiếu và chỗ sai |
|
||||
| [`bmad-review-edge-case-hunter`](#bmad-review-edge-case-hunter) | Tác vụ | Phân tích toàn bộ nhánh rẽ để tìm trường hợp biên chưa được xử lý |
|
||||
| [`bmad-editorial-review-prose`](#bmad-editorial-review-prose) | Tác vụ | Biên tập câu chữ nhằm tăng độ rõ ràng khi giao tiếp |
|
||||
| [`bmad-editorial-review-structure`](#bmad-editorial-review-structure) | Tác vụ | Biên tập cấu trúc — cắt, gộp và tổ chức lại |
|
||||
| [`bmad-shard-doc`](#bmad-shard-doc) | Tác vụ | Tách file markdown lớn thành các phần có tổ chức |
|
||||
| [`bmad-index-docs`](#bmad-index-docs) | Tác vụ | Tạo hoặc cập nhật mục lục cho toàn bộ tài liệu trong một thư mục |
|
||||
|
||||
## bmad-help
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ Chạy bất kỳ core tool nào bằng cách gõ tên skill của nó, ví dụ
|
|||
|
||||
**Dùng khi:**
|
||||
|
||||
- Bạn vừa hoàn tất một workflow và muốn biết tiếp theo là gì
|
||||
- Bạn vừa hoàn tất một quy trình và muốn biết tiếp theo là gì
|
||||
- Bạn mới làm quen với BMad và cần định hướng
|
||||
- Bạn đang mắc kẹt và muốn lời khuyên có ngữ cảnh
|
||||
- Bạn vừa cài module mới và muốn xem có gì khả dụng
|
||||
|
|
@ -51,7 +51,7 @@ Chạy bất kỳ core tool nào bằng cách gõ tên skill của nó, ví dụ
|
|||
|
||||
## bmad-brainstorming
|
||||
|
||||
**Tạo ra nhiều ý tưởng đa dạng bằng các kỹ thuật sáng tạo có tương tác.** Đây là một phiên brainstorming có điều phối, nạp các phương pháp phát ý tưởng đã được kiểm chứng từ thư viện kỹ thuật và dẫn bạn đến 100+ ý tưởng trước khi bắt đầu sắp xếp.
|
||||
**Tạo ra nhiều ý tưởng đa dạng bằng các kỹ thuật sáng tạo có tương tác.** Đây là một phiên động não có điều phối, nạp các phương pháp phát ý tưởng đã được kiểm chứng từ thư viện kỹ thuật và dẫn bạn đến 100+ ý tưởng trước khi bắt đầu sắp xếp.
|
||||
|
||||
**Dùng khi:**
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
---
|
||||
title: "Workflow Map"
|
||||
description: Tài liệu trực quan về các phase workflow và output của BMad Method
|
||||
title: "Sơ đồ workflow"
|
||||
description: Tài liệu trực quan về các giai đoạn, quy trình và đầu ra của BMad Method
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
BMad Method (BMM) là một module trong hệ sinh thái BMad, tập trung vào các thực hành tốt nhất của context engineering và lập kế hoạch. AI agent hoạt động hiệu quả nhất khi có ngữ cảnh rõ ràng và có cấu trúc. Hệ thống BMM xây dựng ngữ cảnh đó theo tiến trình qua 4 phase riêng biệt. Mỗi phase, cùng với nhiều workflow tùy chọn bên trong phase đó, tạo ra các tài liệu làm đầu vào cho phase kế tiếp, nhờ vậy agent luôn biết phải xây gì và vì sao.
|
||||
BMad Method (BMM) là một module trong hệ sinh thái BMad, tập trung vào các thực hành tốt nhất của kỹ nghệ ngữ cảnh và lập kế hoạch. AI agent hoạt động hiệu quả nhất khi có ngữ cảnh rõ ràng và có cấu trúc. Hệ thống BMM xây dựng ngữ cảnh đó theo tiến trình qua 4 giai đoạn riêng biệt. Mỗi giai đoạn, cùng với nhiều quy trình tùy chọn bên trong nó, tạo ra các tài liệu làm đầu vào cho giai đoạn kế tiếp, nhờ vậy agent luôn biết phải xây gì và vì sao.
|
||||
|
||||
Lý do và các khái niệm nền tảng ở đây đến từ các phương pháp agile đã được áp dụng rất thành công trong toàn ngành như một khung tư duy.
|
||||
Lý do và các khái niệm nền tảng ở đây đến từ các phương pháp Agile đã được áp dụng rất thành công trong toàn ngành như một khung tư duy.
|
||||
|
||||
Nếu có lúc nào bạn không chắc nên làm gì, skill `bmad-help` sẽ giúp bạn giữ đúng hướng hoặc biết bước tiếp theo. Bạn vẫn có thể dùng trang này để tham chiếu, nhưng `bmad-help` mang tính tương tác đầy đủ và nhanh hơn nhiều nếu bạn đã cài BMad Method. Ngoài ra, nếu bạn đang dùng thêm các module mở rộng BMad Method hoặc các module bổ sung khác, `bmad-help` cũng sẽ phát triển theo để biết mọi thứ đang có sẵn và đưa ra lời khuyên tốt nhất tại thời điểm đó.
|
||||
Nếu có lúc nào bạn không chắc nên làm gì, skill `bmad-help` sẽ giúp bạn giữ đúng hướng hoặc biết bước tiếp theo. Bạn vẫn có thể dùng trang này để tham chiếu, nhưng `bmad-help` mang tính tương tác đầy đủ và nhanh hơn nhiều nếu bạn đã cài BMad Method. Ngoài ra, nếu bạn đang dùng thêm các module mở rộng BMad Method hoặc các module bổ sung khác, `bmad-help` cũng sẽ mở rộng theo để biết mọi thứ đang có sẵn và đưa ra lời khuyên tốt nhất tại thời điểm đó.
|
||||
|
||||
Lưu ý quan trọng cuối cùng: mọi workflow dưới đây đều có thể chạy trực tiếp bằng công cụ bạn chọn thông qua skill, hoặc bằng cách nạp agent trước rồi chọn mục tương ứng trong menu agent.
|
||||
Lưu ý quan trọng cuối cùng: mọi quy trình dưới đây đều có thể chạy trực tiếp bằng công cụ bạn chọn thông qua skill, hoặc bằng cách nạp agent trước rồi chọn mục tương ứng trong menu agent.
|
||||
|
||||
<iframe src="/workflow-map-diagram.html" title="Sơ đồ Workflow Map của BMad Method" width="100%" height="100%" style="border-radius: 8px; border: 1px solid #334155; min-height: 900px;"></iframe>
|
||||
|
||||
|
|
@ -19,43 +19,43 @@ Lưu ý quan trọng cuối cùng: mọi workflow dưới đây đều có thể
|
|||
<a href="/workflow-map-diagram.html" target="_blank" rel="noopener noreferrer">Mở sơ đồ trong tab mới ↗</a>
|
||||
</p>
|
||||
|
||||
## Phase 1: Analysis (Tùy chọn)
|
||||
## Giai đoạn 1: Phân tích (tùy chọn)
|
||||
|
||||
Khám phá không gian vấn đề và xác nhận ý tưởng trước khi cam kết đi vào lập kế hoạch. [**Tìm hiểu từng công cụ làm gì và nên dùng khi nào**](../explanation/analysis-phase.md).
|
||||
|
||||
| Workflow | Mục đích | Tạo ra |
|
||||
| Quy trình | Mục đích | Tạo ra |
|
||||
| ------------------------------- | -------------------------------------------------------------------------- | ------------------------- |
|
||||
| `bmad-brainstorming` | Brainstorm ý tưởng dự án với sự điều phối của brainstorming coach | `brainstorming-report.md` |
|
||||
| `bmad-brainstorming` | Động não ý tưởng dự án với sự điều phối của người dẫn dắt brainstorming | `brainstorming-report.md` |
|
||||
| `bmad-domain-research`, `bmad-market-research`, `bmad-technical-research` | Xác thực giả định về thị trường, kỹ thuật hoặc miền nghiệp vụ | Kết quả nghiên cứu |
|
||||
| `bmad-product-brief` | Ghi lại tầm nhìn chiến lược — phù hợp nhất khi concept của bạn đã rõ | `product-brief.md` |
|
||||
| `bmad-prfaq` | Working Backwards — stress-test và rèn sắc concept sản phẩm của bạn | `prfaq-{project}.md` |
|
||||
|
||||
## Phase 2: Planning
|
||||
## Giai đoạn 2: Lập kế hoạch
|
||||
|
||||
Xác định cần xây gì và xây cho ai.
|
||||
|
||||
| Workflow | Mục đích | Tạo ra |
|
||||
| Quy trình | Mục đích | Tạo ra |
|
||||
| --------------------------- | ---------------------------------------- | ------------ |
|
||||
| `bmad-create-prd` | Xác định yêu cầu (FR/NFR) | `PRD.md` |
|
||||
| `bmad-create-ux-design` | Thiết kế trải nghiệm người dùng khi UX là yếu tố quan trọng | `ux-spec.md` |
|
||||
|
||||
## Phase 3: Solutioning
|
||||
## Giai đoạn 3: Định hình giải pháp
|
||||
|
||||
Quyết định cách xây và chia nhỏ công việc thành stories.
|
||||
Quyết định cách xây và chia nhỏ công việc thành các story.
|
||||
|
||||
| Workflow | Mục đích | Tạo ra |
|
||||
| Quy trình | Mục đích | Tạo ra |
|
||||
| ----------------------------------------- | ------------------------------------------ | --------------------------- |
|
||||
| `bmad-create-architecture` | Làm rõ các quyết định kỹ thuật | `architecture.md` kèm ADR |
|
||||
| `bmad-create-epics-and-stories` | Phân rã yêu cầu thành các phần việc có thể triển khai | Các file epic chứa stories |
|
||||
| `bmad-create-epics-and-stories` | Phân rã yêu cầu thành các phần việc có thể triển khai | Các file epic chứa các story |
|
||||
| `bmad-check-implementation-readiness` | Cổng kiểm tra trước khi triển khai | Quyết định PASS/CONCERNS/FAIL |
|
||||
|
||||
## Phase 4: Implementation
|
||||
## Giai đoạn 4: Triển khai
|
||||
|
||||
Xây dựng từng story một. Tự động hóa toàn bộ phase 4 sẽ sớm ra mắt.
|
||||
Xây dựng từng story một. Tự động hóa toàn bộ giai đoạn 4 sẽ sớm ra mắt.
|
||||
|
||||
| Workflow | Mục đích | Tạo ra |
|
||||
| Quy trình | Mục đích | Tạo ra |
|
||||
| -------------------------- | ------------------------------------------------------------------------ | -------------------------------- |
|
||||
| `bmad-sprint-planning` | Khởi tạo theo dõi, thường chạy một lần mỗi dự án để sắp thứ tự chu trình dev | `sprint-status.yaml` |
|
||||
| `bmad-sprint-planning` | Khởi tạo theo dõi, thường chạy một lần mỗi dự án để sắp thứ tự chu trình phát triển | `sprint-status.yaml` |
|
||||
| `bmad-create-story` | Chuẩn bị story tiếp theo cho implementation | `story-[slug].md` |
|
||||
| `bmad-dev-story` | Triển khai story | Code chạy được + tests |
|
||||
| `bmad-code-review` | Kiểm tra chất lượng phần triển khai | Được duyệt hoặc yêu cầu thay đổi |
|
||||
|
|
@ -63,22 +63,22 @@ Xây dựng từng story một. Tự động hóa toàn bộ phase 4 sẽ sớm
|
|||
| `bmad-sprint-status` | Theo dõi tiến độ sprint và trạng thái story | Cập nhật trạng thái sprint |
|
||||
| `bmad-retrospective` | Review sau khi hoàn tất epic | Bài học rút ra |
|
||||
|
||||
## Quick Flow (Nhánh Song Song)
|
||||
## Luồng nhanh (nhánh song song)
|
||||
|
||||
Bỏ qua phase 1-3 đối với những việc nhỏ, rõ và đã hiểu đầy đủ.
|
||||
Bỏ qua giai đoạn 1-3 đối với những việc nhỏ, rõ và đã hiểu đầy đủ.
|
||||
|
||||
| Workflow | Mục đích | Tạo ra |
|
||||
| Quy trình | Mục đích | Tạo ra |
|
||||
| ------------------ | --------------------------------------------------------------------------- | ---------------------- |
|
||||
| `bmad-quick-dev` | Luồng nhanh hợp nhất — làm rõ yêu cầu, lập kế hoạch, triển khai, review và trình bày | `spec-*.md` + mã nguồn |
|
||||
|
||||
## Quản Lý Context
|
||||
## Quản lý ngữ cảnh
|
||||
|
||||
Mỗi tài liệu sẽ trở thành context cho phase tiếp theo. PRD cho architect biết những ràng buộc nào quan trọng. Architecture chỉ cho dev agent những pattern cần tuân theo. File story cung cấp context tập trung và đầy đủ cho việc triển khai. Nếu không có cấu trúc này, agent sẽ đưa ra quyết định thiếu nhất quán.
|
||||
Mỗi tài liệu sẽ trở thành ngữ cảnh cho giai đoạn tiếp theo. PRD cho architect biết những ràng buộc nào quan trọng. Tài liệu kiến trúc chỉ cho dev agent những mẫu cần tuân theo. File story cung cấp ngữ cảnh tập trung và đầy đủ cho việc triển khai. Nếu không có cấu trúc này, agent sẽ đưa ra quyết định thiếu nhất quán.
|
||||
|
||||
### Project Context
|
||||
### Bối cảnh dự án
|
||||
|
||||
:::tip[Khuyến nghị]
|
||||
Hãy tạo `project-context.md` để bảo đảm AI agent tuân theo quy tắc và sở thích của dự án. File này hoạt động như một bản hiến pháp cho dự án của bạn, nó dẫn dắt các quyết định triển khai xuyên suốt mọi workflow. File tùy chọn này có thể được tạo ở cuối bước Architecture Creation, hoặc cũng có thể được sinh trong dự án hiện hữu để ghi lại những điều quan trọng cần giữ đồng bộ với quy ước đang có.
|
||||
Hãy tạo `project-context.md` để bảo đảm AI agent tuân theo quy tắc và sở thích của dự án. File này hoạt động như một bản hiến pháp cho dự án của bạn, nó dẫn dắt các quyết định triển khai xuyên suốt mọi quy trình. File tùy chọn này có thể được tạo ở cuối bước tạo kiến trúc, hoặc cũng có thể được sinh trong dự án hiện hữu để ghi lại những điều quan trọng cần giữ đồng bộ với quy ước đang có.
|
||||
:::
|
||||
|
||||
**Cách tạo:**
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ sidebar:
|
|||
|
||||
| 智能体 | Skill ID | 触发器 | 主要 workflow |
|
||||
| --- | --- | --- | --- |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`、`RS`、`CB`、`DP` | Brainstorm、Research、Create Brief、Document Project |
|
||||
| Analyst (Mary) | `bmad-analyst` | `BP`、`MR`、`DR`、`TR`、`CB`、`WB`、`DP` | Brainstorm、Market Research、Domain Research、Technical Research、Create Brief、PRFAQ Challenge、Document Project |
|
||||
| Product Manager (John) | `bmad-pm` | `CP`、`VP`、`EP`、`CE`、`IR`、`CC` | Create/Validate/Edit PRD、Create Epics and Stories、Implementation Readiness、Correct Course |
|
||||
| Architect (Winston) | `bmad-architect` | `CA`、`IR` | Create Architecture、Implementation Readiness |
|
||||
| Developer (Amelia) | `bmad-agent-dev` | `DS`、`QD`、`QA`、`CR`、`SP`、`CS`、`ER` | Dev Story、Quick Dev、QA Test Generation、Code Review、Sprint Planning、Create Story、Epic Retrospective |
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "bmad-method",
|
||||
"version": "6.2.2",
|
||||
"version": "6.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bmad-method",
|
||||
"version": "6.2.2",
|
||||
"version": "6.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@clack/core": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "bmad-method",
|
||||
"version": "6.2.2",
|
||||
"version": "6.3.0",
|
||||
"description": "Breakthrough Method of Agile AI-driven Development",
|
||||
"keywords": [
|
||||
"agile",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ failed_layers: '' # set at runtime: comma-separated list of layers that failed o
|
|||
- The Blind Hunter subagent receives NO project context — diff only.
|
||||
- The Edge Case Hunter subagent receives diff and project read access.
|
||||
- The Acceptance Auditor subagent receives diff, spec, and context docs.
|
||||
- All review subagents must run at the same model capability as the current session.
|
||||
|
||||
## INSTRUCTIONS
|
||||
|
||||
|
|
|
|||
|
|
@ -46,35 +46,32 @@ If `decision_needed` findings exist, present each one with its detail and the op
|
|||
|
||||
If the user chooses to defer, ask: Quick one-line reason for deferring this item? (helps future reviews): — then append that reason to both the story file bullet and the `{deferred_work_file}` entry.
|
||||
|
||||
**HALT** — I am waiting for your numbered choice. Reply with only the number (or "0" for batch). Do not proceed until you select an option.
|
||||
**HALT** — I am waiting for your numbered choice. Reply with only the number. Do not proceed until you select an option.
|
||||
|
||||
### 5. Handle `patch` findings
|
||||
|
||||
If `patch` findings exist (including any resolved from step 4), HALT. Ask the user:
|
||||
|
||||
If `{spec_file}` is set, present all three options (if >3 `patch` findings exist, also show option 0):
|
||||
If `{spec_file}` is set, present all three options:
|
||||
|
||||
> **How would you like to handle the <Z> `patch` findings?**
|
||||
> 0. **Batch-apply all** — automatically fix every non-controversial patch (recommended when there are many)
|
||||
> 1. **Fix them automatically** — I will apply fixes now
|
||||
> **How would you like to handle the `<P>` `patch` findings?**
|
||||
> 1. **Apply every patch** — fix all of them now, no per-finding confirmation. Defer and decision-needed items are not touched.
|
||||
> 2. **Leave as action items** — they are already in the story file
|
||||
> 3. **Walk through each** — let me show details before deciding
|
||||
> 3. **Walk through each patch** — show details for each before deciding
|
||||
|
||||
If `{spec_file}` is **not** set, present only options 1 and 3 (omit option 2 — findings were not written to a file). If >3 `patch` findings exist, also show option 0:
|
||||
If `{spec_file}` is **not** set, present only options 1 and 2 (omit "Leave as action items" — findings were not written to a file):
|
||||
|
||||
> **How would you like to handle the <Z> `patch` findings?**
|
||||
> 0. **Batch-apply all** — automatically fix every non-controversial patch (recommended when there are many)
|
||||
> 1. **Fix them automatically** — I will apply fixes now
|
||||
> 2. **Walk through each** — let me show details before deciding
|
||||
> **How would you like to handle the `<P>` `patch` findings?**
|
||||
> 1. **Apply every patch** — fix all of them now, no per-finding confirmation. Defer and decision-needed items are not touched.
|
||||
> 2. **Walk through each patch** — show details for each before deciding
|
||||
|
||||
**HALT** — I am waiting for your numbered choice. Reply with only the number (or "0" for batch). Do not proceed until you select an option.
|
||||
**HALT** — I am waiting for your numbered choice. Reply with only the number. Do not proceed until you select an option.
|
||||
|
||||
- **Option 0** (only when >3 findings): Apply all non-controversial patches without per-finding confirmation. Skip any finding that requires judgment. Present a summary of changes made and any skipped findings.
|
||||
- **Option 1**: Apply each fix. After all patches are applied, present a summary of changes made. If `{spec_file}` is set, check off the items in the story file.
|
||||
- **Option 2** (only when `{spec_file}` is set): Done — findings are already written to the story.
|
||||
- **Walk through each**: Present each finding with full detail, diff context, and suggested fix. After walkthrough, re-offer the applicable options above.
|
||||
- **Apply every patch**: Apply every patch finding without per-finding confirmation. Do not modify defer or decision-needed items. After all patches are applied, present a summary of changes made. If `{spec_file}` is set, check off the patch items in the story file (leave defer items as-is).
|
||||
- **Leave as action items** (only when `{spec_file}` is set): Done — findings are already written to the story.
|
||||
- **Walk through each patch**: Present each finding with full detail, diff context, and suggested fix. After walkthrough, re-offer the applicable options above.
|
||||
|
||||
**HALT** — I am waiting for your numbered choice. Reply with only the number (or "0" for batch). Do not proceed until you select an option.
|
||||
**HALT** — I am waiting for your numbered choice. Do not proceed until you select an option.
|
||||
|
||||
**✅ Code review actions complete**
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
||||
spec_file: '' # set at runtime for both routes before leaving this step
|
||||
story_key: '' # set at runtime to the current story's full sprint-status key (e.g. 3-2-digest-delivery) when the intent is an epic story and sprint-status resolution succeeds
|
||||
---
|
||||
|
||||
# Step 1: Clarify and Route
|
||||
|
|
@ -20,7 +21,7 @@ Before listing artifacts or prompting the user, check whether you already know t
|
|||
|
||||
1. Explicit argument
|
||||
Did the user pass a specific file path, spec name, or clear instruction this message?
|
||||
- If it points to a file that matches the spec template (has `status` frontmatter with a recognized value: draft, ready-for-dev, in-progress, in-review, or done) → set `spec_file` and **EARLY EXIT** to the appropriate step (step-02 for draft, step-03 for ready/in-progress, step-04 for review). For `done`, ingest as context and proceed to INSTRUCTIONS — do not resume.
|
||||
- If it points to a file that matches the spec template (has `status` frontmatter with a recognized value: draft, ready-for-dev, in-progress, in-review, or done) → set `spec_file`. Before exiting, run **Story-key resolution** (below). Then **EARLY EXIT** to the appropriate step (step-02 for draft, step-03 for ready/in-progress, step-04 for review). For `done`, ingest as context and proceed to INSTRUCTIONS — do not resume.
|
||||
- Anything else (intent files, external docs, plans, descriptions) → ingest it as starting intent and proceed to INSTRUCTIONS. Do not attempt to infer a workflow state from it.
|
||||
|
||||
2. Recent conversation
|
||||
|
|
@ -29,13 +30,19 @@ Before listing artifacts or prompting the user, check whether you already know t
|
|||
|
||||
3. Otherwise — scan artifacts and ask
|
||||
- Active specs (`draft`, `ready-for-dev`, `in-progress`, `in-review`) in `{implementation_artifacts}`? → List them and HALT. Ask user which to resume (or `[N]` for new).
|
||||
- If `draft` selected: Set `spec_file`. **EARLY EXIT** → `./step-02-plan.md` (resume planning from the draft)
|
||||
- If `ready-for-dev` or `in-progress` selected: Set `spec_file`. **EARLY EXIT** → `./step-03-implement.md`
|
||||
- If `in-review` selected: Set `spec_file`. **EARLY EXIT** → `./step-04-review.md`
|
||||
- If `draft` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-02-plan.md` (resume planning from the draft)
|
||||
- If `ready-for-dev` or `in-progress` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-03-implement.md`
|
||||
- If `in-review` selected: Set `spec_file`. Run **Story-key resolution** (below). **EARLY EXIT** → `./step-04-review.md`
|
||||
- Unformatted spec or intent file lacking `status` frontmatter? → Suggest treating its contents as the starting intent. Do NOT attempt to infer a state and resume it.
|
||||
|
||||
Never ask extra questions if you already understand what the user intends.
|
||||
|
||||
### Story-key resolution
|
||||
|
||||
This runs on ALL paths (early-exit and INSTRUCTIONS) whenever `spec_file` is set. Determine whether the spec is an epic story — use the spec's filename, frontmatter, and any loaded epics file to identify `{epic_num}` and `{story_num}`. If the spec is not an epic story, skip silently and leave `{story_key}` unset.
|
||||
|
||||
If the spec is an epic story and `{sprint_status}` exists: find the `development_status` key matching `{epic_num}-{story_num}` by exact numeric equality on the first two segments (so `1-1` never collides with `1-10`). Exactly one match → set `{story_key}` to that full key. Zero or multiple matches → leave `{story_key}` unset (warn on multiple).
|
||||
|
||||
## INSTRUCTIONS
|
||||
|
||||
1. Load context.
|
||||
|
|
@ -45,7 +52,7 @@ Never ask extra questions if you already understand what the user intends.
|
|||
|
||||
**A) Epic story path** — if the intent is clearly an epic story:
|
||||
|
||||
1. Identify the epic number and (if present) the story number. If you can't identify an epic number, use path B.
|
||||
1. Identify the epic number `{epic_num}` and (if present) the story number `{story_num}`. If you can't identify an epic number, use path B.
|
||||
|
||||
2. **Check for a valid cached epic context.** Look for `{implementation_artifacts}/epic-<N>-context.md` (where `<N>` is the epic number). A file is **valid** when it exists, is non-empty, starts with `# Epic <N> Context:` (with the correct epic number), and no file in `{planning_artifacts}` is newer.
|
||||
- **If valid:** load it as the primary planning context. Do not load raw planning docs (PRD, architecture, UX, etc.). Skip to step 5.
|
||||
|
|
@ -59,6 +66,8 @@ Never ask extra questions if you already understand what the user intends.
|
|||
|
||||
5. **Previous story continuity.** Regardless of which context source succeeded above, scan `{implementation_artifacts}` for specs from the same epic with `status: done` and a lower story number. Load the most recent one (highest story number below current). Extract its **Code Map**, **Design Notes**, **Spec Change Log**, and **task list** as continuity context for step-02 planning. If no `done` spec is found but an `in-review` spec exists for the same epic with a lower story number, note it to the user and ask whether to load it.
|
||||
|
||||
6. **Resolve `{story_key}`.** If not already set by an earlier early-exit path, run **Story-key resolution** (above) now.
|
||||
|
||||
**B) Freeform path** — if the intent is not an epic story:
|
||||
- Planning artifacts are the output of BMAD phases 1-3. Typical files include:
|
||||
- **PRD** (`*prd*`) — product requirements and success criteria
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ Capture `baseline_commit` (current HEAD, or `NO_VCS` if version control is unava
|
|||
|
||||
Change `{spec_file}` status to `in-progress` in the frontmatter before starting implementation.
|
||||
|
||||
Follow `./sync-sprint-status.md` with `{target_status}` = `in-progress`.
|
||||
|
||||
If `{spec_file}` has a non-empty `context:` list in its frontmatter, load those files before implementation begins. When handing to a sub-agent, include them in the sub-agent prompt so it has access to the referenced context.
|
||||
|
||||
Hand `{spec_file}` to a sub-agent/task and let it implement. If no sub-agents are available, implement directly.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ specLoopIteration: 1
|
|||
|
||||
- YOU MUST ALWAYS SPEAK OUTPUT in your Agent communication style with the config `{communication_language}`
|
||||
- Review subagents get NO conversation context.
|
||||
- All review subagents must run at the same model capability as the current session.
|
||||
|
||||
## INSTRUCTIONS
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ Launch three subagents without conversation context. If no sub-agents are availa
|
|||
1. Deduplicate all review findings.
|
||||
2. Classify each finding. The first three categories are **this story's problem** — caused or exposed by the current change. The last two are **not this story's problem**.
|
||||
- **intent_gap** — caused by the change; cannot be resolved from the spec because the captured intent is incomplete. Do not infer intent unless there is exactly one possible reading.
|
||||
- **bad_spec** — caused by the change, including direct deviations from spec. The spec should have been clear enough to prevent it. When in doubt between bad_spec and patch, prefer bad_spec — a spec-level fix is more likely to produce coherent code.
|
||||
- **bad_spec** — caused by the change, including direct deviations from spec. The spec should have been clear enough to prevent it. When in doubt between bad_spec and patch, prefer bad_spec — a spec-level fix is more likely to produce coherent code. Also applies when the story's domain includes data silently dropped or never reaching its destination — the change exposed it.
|
||||
- **patch** — caused by the change; trivially fixable without human input. Just part of the diff.
|
||||
- **defer** — pre-existing issue not caused by this story, surfaced incidentally by the review. Collect for later focused attention.
|
||||
- **reject** — noise. Drop silently. When unsure between defer and reject, prefer reject — only defer findings you are confident are real.
|
||||
|
|
|
|||
|
|
@ -48,16 +48,25 @@ Format each stop as framing first, link on the next indented line:
|
|||
|
||||
When there is only one concern, omit the bold label — just list the stops directly.
|
||||
|
||||
### Commit and Present
|
||||
### Mark Spec Done
|
||||
|
||||
1. Change `{spec_file}` status to `done` in the frontmatter.
|
||||
2. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title.
|
||||
3. Open the spec in the user's editor so they can click through the Suggested Review Order:
|
||||
Change `{spec_file}` status to `done` in the frontmatter.
|
||||
|
||||
Follow `./sync-sprint-status.md` with `{target_status}` = `review`.
|
||||
|
||||
### Commit and Open
|
||||
|
||||
1. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title.
|
||||
2. Open the spec in the user's editor so they can click through the Suggested Review Order:
|
||||
- Resolve two absolute paths: (1) the repository root (`git rev-parse --show-toplevel` — returns the worktree root when in a worktree, project root otherwise; if this fails, fall back to the current working directory), (2) `{spec_file}`. Run `code -r "{absolute-root}" "{absolute-spec-file}"` — the root first so VS Code opens in the right context, then the spec file. Always double-quote paths to handle spaces and special characters.
|
||||
- If `code` is not available (command fails), skip gracefully and tell the user the spec file path instead.
|
||||
4. Display summary of your work to the user, including the commit hash if one was created. Any file paths shown in conversation/terminal output must use CWD-relative format (no leading `/`) with `:line` notation (e.g., `src/path/file.ts:42`) for terminal clickability — the goal is to make paths clickable in terminal emulators. Include:
|
||||
- A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order.
|
||||
- **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
|
||||
- Offer to push and/or create a pull request.
|
||||
|
||||
### Display Summary
|
||||
|
||||
Display summary of your work to the user, including the commit hash if one was created. Any file paths shown in conversation/terminal output must use CWD-relative format (no leading `/`) with `:line` notation (e.g., `src/path/file.ts:42`) for terminal clickability — the goal is to make paths clickable in terminal emulators. Include:
|
||||
|
||||
- A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order.
|
||||
- **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
|
||||
- Offer to push and/or create a pull request.
|
||||
|
||||
Workflow complete.
|
||||
|
|
|
|||
|
|
@ -13,11 +13,13 @@ deferred_work_file: '{implementation_artifacts}/deferred-work.md'
|
|||
|
||||
### Implement
|
||||
|
||||
Follow `./sync-sprint-status.md` with `{target_status}` = `in-progress`.
|
||||
|
||||
Implement the clarified intent directly.
|
||||
|
||||
### Review
|
||||
|
||||
Invoke the `bmad-review-adversarial-general` skill in a subagent with the changed files. The subagent gets NO conversation context — to avoid anchoring bias. If no sub-agents are available, write the changed files to a review prompt file in `{implementation_artifacts}` and HALT. Ask the human to run the review in a separate session and paste back the findings.
|
||||
Invoke the `bmad-review-adversarial-general` skill in a subagent with the changed files. The subagent gets NO conversation context — to avoid anchoring bias. Launch at the same model capability as the current session. If no sub-agents are available, write the changed files to a review prompt file in `{implementation_artifacts}` and HALT. Ask the human to run the review in a separate session and paste back the findings.
|
||||
|
||||
### Classify
|
||||
|
||||
|
|
@ -39,6 +41,8 @@ Write `{spec_file}` using `./spec-template.md`. Fill only these sections — del
|
|||
2. **Title and Intent** — `# {title}` heading and `## Intent` with **Problem** and **Approach** lines. Reuse the summary you already generated for the terminal.
|
||||
3. **Suggested Review Order** — append after Intent. Build using the same convention as `./step-05-present.md` § "Generate Suggested Review Order" (spec-file-relative links, concern-based ordering, ultra-concise framing).
|
||||
|
||||
Follow `./sync-sprint-status.md` with `{target_status}` = `review`.
|
||||
|
||||
### Commit
|
||||
|
||||
If version control is available and the tree is dirty, create a local commit with a conventional message derived from the intent. If VCS is unavailable, skip.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# Sync Sprint Status
|
||||
|
||||
Shared sub-step for updating `sprint-status.yaml` during quick-dev. Called from any route (plan-code-review, one-shot, future routes) with a `{target_status}` parameter.
|
||||
|
||||
## Preconditions
|
||||
|
||||
Skip this entire file (return to caller) if ANY of:
|
||||
- `{story_key}` is unset
|
||||
- `{sprint_status}` does not exist on disk
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Load the FULL `{sprint_status}` file.
|
||||
2. Find the `development_status` entry matching `{story_key}`. If not found, warn the user once (`"{story_key} not found in sprint-status; skipping sprint sync"`) and return to caller.
|
||||
3. **Idempotency check.** If `development_status[{story_key}]` is already at `{target_status}` or a later state (`review` is later than `in-progress`; `done` is later than both), return to caller — no write needed. Never regress a story's status.
|
||||
4. Set `development_status[{story_key}]` to `{target_status}`.
|
||||
5. **Epic lift (only when `{target_status}` = `in-progress`).** Derive the parent epic key as `epic-{N}` from the leading numeric segment of `{story_key}` (e.g., `3-2-digest-delivery` → `epic-3`). If that entry exists and is `backlog`, set it to `in-progress`. Leave it alone otherwise. Skip this sub-step entirely when `{target_status}` is not `in-progress`.
|
||||
6. Refresh `last_updated` to the current date.
|
||||
7. Save the file, preserving ALL comments and structure including STATUS DEFINITIONS and WORKFLOW NOTES.
|
||||
|
|
@ -65,6 +65,7 @@ Load and read full config from `{main_config}` and resolve:
|
|||
- `project_name`, `planning_artifacts`, `implementation_artifacts`, `user_name`
|
||||
- `communication_language`, `document_output_language`, `user_skill_level`
|
||||
- `date` as system-generated current datetime
|
||||
- `sprint_status` = `{implementation_artifacts}/sprint-status.yaml`
|
||||
- `project_context` = `**/project-context.md` (load if exists)
|
||||
- CLAUDE.md / memory files (load if exist)
|
||||
|
||||
|
|
|
|||
|
|
@ -1728,36 +1728,6 @@ async function runTests() {
|
|||
// ============================================================
|
||||
console.log(`${colors.yellow}Test Suite 33: Community & Custom Module Managers${colors.reset}\n`);
|
||||
|
||||
// --- CustomModuleManager.validateGitHubUrl ---
|
||||
{
|
||||
const { CustomModuleManager } = require('../tools/installer/modules/custom-module-manager');
|
||||
const mgr = new CustomModuleManager();
|
||||
|
||||
const https1 = mgr.validateGitHubUrl('https://github.com/owner/repo');
|
||||
assert(https1.isValid === true, 'validateGitHubUrl accepts HTTPS URL');
|
||||
assert(https1.owner === 'owner' && https1.repo === 'repo', 'validateGitHubUrl extracts owner/repo from HTTPS');
|
||||
|
||||
const https2 = mgr.validateGitHubUrl('https://github.com/owner/repo.git');
|
||||
assert(https2.isValid === true, 'validateGitHubUrl accepts HTTPS URL with .git');
|
||||
assert(https2.repo === 'repo', 'validateGitHubUrl strips .git suffix');
|
||||
|
||||
const ssh1 = mgr.validateGitHubUrl('git@github.com:owner/repo.git');
|
||||
assert(ssh1.isValid === true, 'validateGitHubUrl accepts SSH URL');
|
||||
assert(ssh1.owner === 'owner' && ssh1.repo === 'repo', 'validateGitHubUrl extracts owner/repo from SSH');
|
||||
|
||||
const bad1 = mgr.validateGitHubUrl('https://gitlab.com/owner/repo');
|
||||
assert(bad1.isValid === false, 'validateGitHubUrl rejects non-GitHub URL');
|
||||
|
||||
const bad2 = mgr.validateGitHubUrl('');
|
||||
assert(bad2.isValid === false, 'validateGitHubUrl rejects empty string');
|
||||
|
||||
const bad3 = mgr.validateGitHubUrl(null);
|
||||
assert(bad3.isValid === false, 'validateGitHubUrl rejects null');
|
||||
|
||||
const bad4 = mgr.validateGitHubUrl('https://github.com/owner');
|
||||
assert(bad4.isValid === false, 'validateGitHubUrl rejects URL without repo');
|
||||
}
|
||||
|
||||
// --- CustomModuleManager._normalizeCustomModule ---
|
||||
{
|
||||
const { CustomModuleManager } = require('../tools/installer/modules/custom-module-manager');
|
||||
|
|
@ -1954,25 +1924,6 @@ async function runTests() {
|
|||
assert(notFound === null, 'getModuleByCode returns null for unknown code');
|
||||
}
|
||||
|
||||
// --- CustomModuleManager URL edge cases ---
|
||||
{
|
||||
const { CustomModuleManager } = require('../tools/installer/modules/custom-module-manager');
|
||||
const mgr = new CustomModuleManager();
|
||||
|
||||
// HTTP (not HTTPS) should work
|
||||
const http = mgr.validateGitHubUrl('http://github.com/owner/repo');
|
||||
assert(http.isValid === true, 'validateGitHubUrl accepts HTTP URL');
|
||||
|
||||
// Trailing slash should be rejected (strict matching)
|
||||
const trailing = mgr.validateGitHubUrl('https://github.com/owner/repo/');
|
||||
assert(trailing.isValid === false, 'validateGitHubUrl rejects trailing slash');
|
||||
|
||||
// SSH without .git should work
|
||||
const sshNoDotGit = mgr.validateGitHubUrl('git@github.com:owner/repo');
|
||||
assert(sshNoDotGit.isValid === true, 'validateGitHubUrl accepts SSH without .git');
|
||||
assert(sshNoDotGit.repo === 'repo', 'validateGitHubUrl extracts repo from SSH without .git');
|
||||
}
|
||||
|
||||
console.log('');
|
||||
|
||||
// ============================================================
|
||||
|
|
|
|||
|
|
@ -1,20 +1,6 @@
|
|||
const path = require('node:path');
|
||||
const os = require('node:os');
|
||||
const prompts = require('./prompts');
|
||||
|
||||
const CLIUtils = {
|
||||
/**
|
||||
* Get version from package.json
|
||||
*/
|
||||
getVersion() {
|
||||
try {
|
||||
const packageJson = require(path.join(__dirname, '..', '..', 'package.json'));
|
||||
return packageJson.version || 'Unknown';
|
||||
} catch {
|
||||
return 'Unknown';
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Display BMAD logo and version using @clack intro + box
|
||||
*/
|
||||
|
|
@ -52,37 +38,6 @@ const CLIUtils = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Display section header
|
||||
* @param {string} title - Section title
|
||||
* @param {string} subtitle - Optional subtitle
|
||||
*/
|
||||
async displaySection(title, subtitle = null) {
|
||||
await prompts.note(subtitle || '', title);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display info box
|
||||
* @param {string|Array} content - Content to display
|
||||
* @param {Object} options - Box options
|
||||
*/
|
||||
async displayBox(content, options = {}) {
|
||||
let text = content;
|
||||
if (Array.isArray(content)) {
|
||||
text = content.join('\n\n');
|
||||
}
|
||||
|
||||
const color = await prompts.getColor();
|
||||
const borderColor = options.borderColor || 'cyan';
|
||||
const colorMap = { green: color.green, red: color.red, yellow: color.yellow, cyan: color.cyan, blue: color.blue };
|
||||
const formatBorder = colorMap[borderColor] || color.cyan;
|
||||
|
||||
await prompts.box(text, options.title, {
|
||||
rounded: options.borderStyle === 'round' || options.borderStyle === undefined,
|
||||
formatBorder,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Display module configuration header
|
||||
* @param {string} moduleName - Module name (fallback if no custom header)
|
||||
|
|
@ -93,98 +48,6 @@ const CLIUtils = {
|
|||
const title = header || `Configuring ${moduleName.toUpperCase()} Module`;
|
||||
await prompts.note(subheader || '', title);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display module with no custom configuration
|
||||
* @param {string} moduleName - Module name (fallback if no custom header)
|
||||
* @param {string} header - Custom header from module.yaml
|
||||
* @param {string} subheader - Custom subheader from module.yaml
|
||||
*/
|
||||
async displayModuleNoConfig(moduleName, header = null, subheader = null) {
|
||||
const title = header || `${moduleName.toUpperCase()} Module - No Custom Configuration`;
|
||||
await prompts.note(subheader || '', title);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display step indicator
|
||||
* @param {number} current - Current step
|
||||
* @param {number} total - Total steps
|
||||
* @param {string} description - Step description
|
||||
*/
|
||||
async displayStep(current, total, description) {
|
||||
const progress = `[${current}/${total}]`;
|
||||
await prompts.log.step(`${progress} ${description}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Display completion message
|
||||
* @param {string} message - Completion message
|
||||
*/
|
||||
async displayComplete(message) {
|
||||
const color = await prompts.getColor();
|
||||
await prompts.box(`\u2728 ${message}`, 'Complete', {
|
||||
rounded: true,
|
||||
formatBorder: color.green,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Display error message
|
||||
* @param {string} message - Error message
|
||||
*/
|
||||
async displayError(message) {
|
||||
const color = await prompts.getColor();
|
||||
await prompts.box(`\u2717 ${message}`, 'Error', {
|
||||
rounded: true,
|
||||
formatBorder: color.red,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Format list for display
|
||||
* @param {Array} items - Items to display
|
||||
* @param {string} prefix - Item prefix
|
||||
*/
|
||||
formatList(items, prefix = '\u2022') {
|
||||
return items.map((item) => ` ${prefix} ${item}`).join('\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear previous lines
|
||||
* @param {number} lines - Number of lines to clear
|
||||
*/
|
||||
clearLines(lines) {
|
||||
for (let i = 0; i < lines; i++) {
|
||||
process.stdout.moveCursor(0, -1);
|
||||
process.stdout.clearLine(1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Display module completion message
|
||||
* @param {string} moduleName - Name of the completed module
|
||||
* @param {boolean} clearScreen - Whether to clear the screen first (deprecated, always false now)
|
||||
*/
|
||||
displayModuleComplete(moduleName, clearScreen = false) {
|
||||
// No longer clear screen or show boxes - just a simple completion message
|
||||
// This is deprecated but kept for backwards compatibility
|
||||
},
|
||||
|
||||
/**
|
||||
* Expand path with ~ expansion
|
||||
* @param {string} inputPath - Path to expand
|
||||
* @returns {string} Expanded path
|
||||
*/
|
||||
expandPath(inputPath) {
|
||||
if (!inputPath) return inputPath;
|
||||
|
||||
// Expand ~ to home directory
|
||||
if (inputPath.startsWith('~')) {
|
||||
return path.join(os.homedir(), inputPath.slice(1));
|
||||
}
|
||||
|
||||
return inputPath;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { CLIUtils };
|
||||
|
|
|
|||
|
|
@ -107,117 +107,6 @@ class Manifest {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update existing manifest
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
* @param {Object} updates - Fields to update
|
||||
* @param {Array} installedFiles - Updated list of installed files
|
||||
*/
|
||||
async update(bmadDir, updates, installedFiles = null) {
|
||||
const yaml = require('yaml');
|
||||
const manifest = (await this._readRaw(bmadDir)) || {
|
||||
installation: {},
|
||||
modules: [],
|
||||
ides: [],
|
||||
};
|
||||
|
||||
// Handle module updates
|
||||
if (updates.modules) {
|
||||
// If modules is being updated, we need to preserve detailed module info
|
||||
const existingDetailed = manifest.modules || [];
|
||||
const incomingNames = updates.modules;
|
||||
|
||||
// Build updated modules array
|
||||
const updatedModules = [];
|
||||
for (const name of incomingNames) {
|
||||
const existing = existingDetailed.find((m) => m.name === name);
|
||||
if (existing) {
|
||||
// Preserve existing details, update lastUpdated if this module is being updated
|
||||
updatedModules.push({
|
||||
...existing,
|
||||
lastUpdated: new Date().toISOString(),
|
||||
});
|
||||
} else {
|
||||
// New module - add with minimal details
|
||||
updatedModules.push({
|
||||
name,
|
||||
version: null,
|
||||
installDate: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
source: 'unknown',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
manifest.modules = updatedModules;
|
||||
}
|
||||
|
||||
// Merge other updates
|
||||
if (updates.version) {
|
||||
manifest.installation.version = updates.version;
|
||||
}
|
||||
if (updates.installDate) {
|
||||
manifest.installation.installDate = updates.installDate;
|
||||
}
|
||||
manifest.installation.lastUpdated = new Date().toISOString();
|
||||
|
||||
if (updates.ides) {
|
||||
manifest.ides = updates.ides;
|
||||
}
|
||||
|
||||
// Handle per-module version updates
|
||||
if (updates.moduleVersions) {
|
||||
for (const [moduleName, versionInfo] of Object.entries(updates.moduleVersions)) {
|
||||
const moduleIndex = manifest.modules.findIndex((m) => m.name === moduleName);
|
||||
if (moduleIndex !== -1) {
|
||||
manifest.modules[moduleIndex] = {
|
||||
...manifest.modules[moduleIndex],
|
||||
...versionInfo,
|
||||
lastUpdated: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle adding a new module with version info
|
||||
if (updates.addModule) {
|
||||
const { name, version, source, npmPackage, repoUrl, localPath } = updates.addModule;
|
||||
const existing = manifest.modules.find((m) => m.name === name);
|
||||
if (!existing) {
|
||||
const entry = {
|
||||
name,
|
||||
version: version || null,
|
||||
installDate: new Date().toISOString(),
|
||||
lastUpdated: new Date().toISOString(),
|
||||
source: source || 'external',
|
||||
npmPackage: npmPackage || null,
|
||||
repoUrl: repoUrl || null,
|
||||
};
|
||||
if (localPath) entry.localPath = localPath;
|
||||
manifest.modules.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||
await fs.ensureDir(path.dirname(manifestPath));
|
||||
|
||||
// Clean the manifest data to remove any non-serializable values
|
||||
const cleanManifestData = structuredClone(manifest);
|
||||
|
||||
const yamlContent = yaml.stringify(cleanManifestData, {
|
||||
indent: 2,
|
||||
lineWidth: 0,
|
||||
sortKeys: false,
|
||||
});
|
||||
|
||||
// Ensure POSIX-compliant final newline
|
||||
const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
|
||||
await fs.writeFile(manifestPath, content, 'utf8');
|
||||
|
||||
// Return the flattened format for compatibility
|
||||
return this._flattenManifest(manifest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read raw manifest data without flattening
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
|
|
@ -310,62 +199,6 @@ class Manifest {
|
|||
await this._writeRaw(bmadDir, manifest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a module from the manifest
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
* @param {string} moduleName - Module name to remove
|
||||
*/
|
||||
async removeModule(bmadDir, moduleName) {
|
||||
const manifest = await this._readRaw(bmadDir);
|
||||
if (!manifest || !manifest.modules) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = manifest.modules.findIndex((m) => m.name === moduleName);
|
||||
if (index !== -1) {
|
||||
manifest.modules.splice(index, 1);
|
||||
await this._writeRaw(bmadDir, manifest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single module's version info
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
* @param {string} moduleName - Module name
|
||||
* @param {Object} versionInfo - Version info to update
|
||||
*/
|
||||
async updateModuleVersion(bmadDir, moduleName, versionInfo) {
|
||||
const manifest = await this._readRaw(bmadDir);
|
||||
if (!manifest || !manifest.modules) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = manifest.modules.findIndex((m) => m.name === moduleName);
|
||||
if (index !== -1) {
|
||||
manifest.modules[index] = {
|
||||
...manifest.modules[index],
|
||||
...versionInfo,
|
||||
lastUpdated: new Date().toISOString(),
|
||||
};
|
||||
await this._writeRaw(bmadDir, manifest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get version info for a specific module
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
* @param {string} moduleName - Module name
|
||||
* @returns {Object|null} Module version info or null
|
||||
*/
|
||||
async getModuleVersion(bmadDir, moduleName) {
|
||||
const manifest = await this._readRaw(bmadDir);
|
||||
if (!manifest || !manifest.modules) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return manifest.modules.find((m) => m.name === moduleName) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all modules with their version info
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
|
|
@ -403,27 +236,6 @@ class Manifest {
|
|||
await fs.writeFile(manifestPath, content, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an IDE configuration to the manifest
|
||||
* @param {string} bmadDir - Path to bmad directory
|
||||
* @param {string} ideName - IDE name to add
|
||||
*/
|
||||
async addIde(bmadDir, ideName) {
|
||||
const manifest = await this.read(bmadDir);
|
||||
if (!manifest) {
|
||||
throw new Error('No manifest found');
|
||||
}
|
||||
|
||||
if (!manifest.ides) {
|
||||
manifest.ides = [];
|
||||
}
|
||||
|
||||
if (!manifest.ides.includes(ideName)) {
|
||||
manifest.ides.push(ideName);
|
||||
await this.update(bmadDir, { ides: manifest.ides });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate SHA256 hash of a file
|
||||
* @param {string} filePath - Path to file
|
||||
|
|
@ -438,354 +250,6 @@ class Manifest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse installed files to extract metadata
|
||||
* @param {Array} installedFiles - List of installed file paths
|
||||
* @param {string} bmadDir - Path to bmad directory for relative paths
|
||||
* @returns {Array} Array of file metadata objects
|
||||
*/
|
||||
async parseInstalledFiles(installedFiles, bmadDir) {
|
||||
const fileMetadata = [];
|
||||
|
||||
for (const filePath of installedFiles) {
|
||||
const fileExt = path.extname(filePath).toLowerCase();
|
||||
// Make path relative to parent of bmad directory, starting with 'bmad/'
|
||||
const relativePath = 'bmad' + filePath.replace(bmadDir, '').replaceAll('\\', '/');
|
||||
|
||||
// Calculate file hash
|
||||
const hash = await this.calculateFileHash(filePath);
|
||||
|
||||
// Handle markdown files - extract XML metadata if present
|
||||
if (fileExt === '.md') {
|
||||
try {
|
||||
if (await fs.pathExists(filePath)) {
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
const metadata = this.extractXmlNodeAttributes(content, filePath, relativePath);
|
||||
|
||||
if (metadata) {
|
||||
// Has XML metadata
|
||||
metadata.hash = hash;
|
||||
fileMetadata.push(metadata);
|
||||
} else {
|
||||
// No XML metadata - still track the file
|
||||
fileMetadata.push({
|
||||
file: relativePath,
|
||||
type: 'md',
|
||||
name: path.basename(filePath, fileExt),
|
||||
title: null,
|
||||
hash: hash,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
await prompts.log.warn(`Could not parse ${filePath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
// Handle other file types (CSV, JSON, YAML, etc.)
|
||||
else {
|
||||
fileMetadata.push({
|
||||
file: relativePath,
|
||||
type: fileExt.slice(1), // Remove the dot
|
||||
name: path.basename(filePath, fileExt),
|
||||
title: null,
|
||||
hash: hash,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return fileMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract XML node attributes from MD file content
|
||||
* @param {string} content - File content
|
||||
* @param {string} filePath - File path for context
|
||||
* @param {string} relativePath - Relative path starting with 'bmad/'
|
||||
* @returns {Object|null} Extracted metadata or null
|
||||
*/
|
||||
extractXmlNodeAttributes(content, filePath, relativePath) {
|
||||
// Look for XML blocks in code fences
|
||||
const xmlBlockMatch = content.match(/```xml\s*([\s\S]*?)```/);
|
||||
if (!xmlBlockMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const xmlContent = xmlBlockMatch[1];
|
||||
|
||||
// Extract root XML node (agent, task, template, etc.)
|
||||
const rootNodeMatch = xmlContent.match(/<(\w+)([^>]*)>/);
|
||||
if (!rootNodeMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodeType = rootNodeMatch[1];
|
||||
const attributes = rootNodeMatch[2];
|
||||
|
||||
// Extract name and title attributes (id not needed since we have path)
|
||||
const nameMatch = attributes.match(/name="([^"]*)"/);
|
||||
const titleMatch = attributes.match(/title="([^"]*)"/);
|
||||
|
||||
return {
|
||||
file: relativePath,
|
||||
type: nodeType,
|
||||
name: nameMatch ? nameMatch[1] : null,
|
||||
title: titleMatch ? titleMatch[1] : null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate CSV manifest content
|
||||
* @param {Object} data - Manifest data
|
||||
* @param {Array} fileMetadata - File metadata array
|
||||
* @param {Object} moduleConfigs - Module configuration data
|
||||
* @returns {string} CSV content
|
||||
*/
|
||||
generateManifestCsv(data, fileMetadata, moduleConfigs = {}) {
|
||||
const timestamp = new Date().toISOString();
|
||||
let csv = [];
|
||||
|
||||
// Header section
|
||||
csv.push(
|
||||
'# BMAD Manifest',
|
||||
`# Generated: ${timestamp}`,
|
||||
'',
|
||||
'## Installation Info',
|
||||
'Property,Value',
|
||||
`Version,${data.version}`,
|
||||
`InstallDate,${data.installDate || timestamp}`,
|
||||
`LastUpdated,${data.lastUpdated || timestamp}`,
|
||||
);
|
||||
if (data.language) {
|
||||
csv.push(`Language,${data.language}`);
|
||||
}
|
||||
csv.push('');
|
||||
|
||||
// Modules section
|
||||
if (data.modules && data.modules.length > 0) {
|
||||
csv.push('## Modules', 'Name,Version,ShortTitle');
|
||||
for (const moduleName of data.modules) {
|
||||
const config = moduleConfigs[moduleName] || {};
|
||||
csv.push([moduleName, config.version || '', config['short-title'] || ''].map((v) => this.escapeCsv(v)).join(','));
|
||||
}
|
||||
csv.push('');
|
||||
}
|
||||
|
||||
// IDEs section
|
||||
if (data.ides && data.ides.length > 0) {
|
||||
csv.push('## IDEs', 'IDE');
|
||||
for (const ide of data.ides) {
|
||||
csv.push(this.escapeCsv(ide));
|
||||
}
|
||||
csv.push('');
|
||||
}
|
||||
|
||||
// Files section - NO LONGER USED
|
||||
// Files are now tracked in files-manifest.csv by ManifestGenerator
|
||||
|
||||
return csv.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CSV manifest content back to object
|
||||
* @param {string} csvContent - CSV content to parse
|
||||
* @returns {Object} Parsed manifest data
|
||||
*/
|
||||
parseManifestCsv(csvContent) {
|
||||
const result = {
|
||||
modules: [],
|
||||
ides: [],
|
||||
files: [],
|
||||
};
|
||||
|
||||
const lines = csvContent.split('\n');
|
||||
let section = '';
|
||||
|
||||
for (const line_ of lines) {
|
||||
const line = line_.trim();
|
||||
|
||||
// Skip empty lines and comments
|
||||
if (!line || line.startsWith('#')) {
|
||||
// Check for section headers
|
||||
if (line.startsWith('## ')) {
|
||||
section = line.slice(3).toLowerCase();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse based on current section
|
||||
switch (section) {
|
||||
case 'installation info': {
|
||||
// Skip header row
|
||||
if (line === 'Property,Value') continue;
|
||||
|
||||
const [property, ...valueParts] = line.split(',');
|
||||
const value = this.unescapeCsv(valueParts.join(','));
|
||||
|
||||
switch (property) {
|
||||
// Path no longer stored in manifest
|
||||
case 'Version': {
|
||||
result.version = value;
|
||||
break;
|
||||
}
|
||||
case 'InstallDate': {
|
||||
result.installDate = value;
|
||||
break;
|
||||
}
|
||||
case 'LastUpdated': {
|
||||
result.lastUpdated = value;
|
||||
break;
|
||||
}
|
||||
case 'Language': {
|
||||
result.language = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'modules': {
|
||||
// Skip header row
|
||||
if (line === 'Name,Version,ShortTitle') continue;
|
||||
|
||||
const parts = this.parseCsvLine(line);
|
||||
if (parts[0]) {
|
||||
result.modules.push(parts[0]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'ides': {
|
||||
// Skip header row
|
||||
if (line === 'IDE') continue;
|
||||
|
||||
result.ides.push(this.unescapeCsv(line));
|
||||
|
||||
break;
|
||||
}
|
||||
case 'files': {
|
||||
// Skip header rows (support both old and new format)
|
||||
if (line === 'Type,Path,Name,Title' || line === 'Type,Path,Name,Title,Hash') continue;
|
||||
|
||||
const parts = this.parseCsvLine(line);
|
||||
if (parts.length >= 2) {
|
||||
result.files.push({
|
||||
type: parts[0] || '',
|
||||
file: parts[1] || '',
|
||||
name: parts[2] || null,
|
||||
title: parts[3] || null,
|
||||
hash: parts[4] || null, // Hash column (may not exist in old manifests)
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
// No default
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a CSV line handling quotes and commas
|
||||
* @param {string} line - CSV line to parse
|
||||
* @returns {Array} Array of values
|
||||
*/
|
||||
parseCsvLine(line) {
|
||||
const result = [];
|
||||
let current = '';
|
||||
let inQuotes = false;
|
||||
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
const char = line[i];
|
||||
|
||||
if (char === '"') {
|
||||
if (inQuotes && line[i + 1] === '"') {
|
||||
// Escaped quote
|
||||
current += '"';
|
||||
i++;
|
||||
} else {
|
||||
// Toggle quote state
|
||||
inQuotes = !inQuotes;
|
||||
}
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
// Field separator
|
||||
result.push(this.unescapeCsv(current));
|
||||
current = '';
|
||||
} else {
|
||||
current += char;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last field
|
||||
result.push(this.unescapeCsv(current));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape CSV special characters
|
||||
* @param {string} text - Text to escape
|
||||
* @returns {string} Escaped text
|
||||
*/
|
||||
escapeCsv(text) {
|
||||
if (!text) return '';
|
||||
const str = String(text);
|
||||
|
||||
// If contains comma, newline, or quote, wrap in quotes and escape quotes
|
||||
if (str.includes(',') || str.includes('\n') || str.includes('"')) {
|
||||
return '"' + str.replaceAll('"', '""') + '"';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescape CSV field
|
||||
* @param {string} text - Text to unescape
|
||||
* @returns {string} Unescaped text
|
||||
*/
|
||||
unescapeCsv(text) {
|
||||
if (!text) return '';
|
||||
|
||||
// Remove surrounding quotes if present
|
||||
if (text.startsWith('"') && text.endsWith('"')) {
|
||||
text = text.slice(1, -1);
|
||||
// Unescape doubled quotes
|
||||
text = text.replaceAll('""', '"');
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load module configuration files
|
||||
* @param {Array} modules - List of module names
|
||||
* @returns {Object} Module configurations indexed by name
|
||||
*/
|
||||
async loadModuleConfigs(modules) {
|
||||
const configs = {};
|
||||
|
||||
for (const moduleName of modules) {
|
||||
// Handle core module differently - it's in src/core-skills not src/modules/core
|
||||
const configPath =
|
||||
moduleName === 'core'
|
||||
? path.join(process.cwd(), 'src', 'core-skills', 'config.yaml')
|
||||
: path.join(process.cwd(), 'src', 'modules', moduleName, 'config.yaml');
|
||||
|
||||
try {
|
||||
if (await fs.pathExists(configPath)) {
|
||||
const yaml = require('yaml');
|
||||
const content = await fs.readFile(configPath, 'utf8');
|
||||
configs[moduleName] = yaml.parse(content);
|
||||
}
|
||||
} catch (error) {
|
||||
await prompts.log.warn(`Could not load config for module ${moduleName}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return configs;
|
||||
}
|
||||
/**
|
||||
* Get module version info from source
|
||||
* @param {string} moduleName - Module name/code
|
||||
|
|
@ -986,47 +450,6 @@ class Manifest {
|
|||
|
||||
return updates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two semantic versions
|
||||
* @param {string} v1 - First version
|
||||
* @param {string} v2 - Second version
|
||||
* @returns {number} -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
|
||||
*/
|
||||
compareVersions(v1, v2) {
|
||||
if (!v1 || !v2) return 0;
|
||||
|
||||
const normalize = (v) => {
|
||||
// Remove leading 'v' if present
|
||||
v = v.replace(/^v/, '');
|
||||
// Handle prerelease tags
|
||||
const parts = v.split('-');
|
||||
const main = parts[0].split('.');
|
||||
const prerelease = parts[1];
|
||||
return { main, prerelease };
|
||||
};
|
||||
|
||||
const n1 = normalize(v1);
|
||||
const n2 = normalize(v2);
|
||||
|
||||
// Compare main version parts
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const num1 = parseInt(n1.main[i] || '0', 10);
|
||||
const num2 = parseInt(n2.main[i] || '0', 10);
|
||||
if (num1 !== num2) {
|
||||
return num1 < num2 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If main versions are equal, compare prerelease
|
||||
if (n1.prerelease && n2.prerelease) {
|
||||
return n1.prerelease < n2.prerelease ? -1 : n1.prerelease > n2.prerelease ? 1 : 0;
|
||||
}
|
||||
if (n1.prerelease) return -1; // Prerelease is older than stable
|
||||
if (n2.prerelease) return 1; // Stable is newer than prerelease
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { Manifest };
|
||||
|
|
|
|||
|
|
@ -1,180 +0,0 @@
|
|||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils');
|
||||
|
||||
/**
|
||||
* Generates launcher command files for each agent
|
||||
*/
|
||||
class AgentCommandGenerator {
|
||||
constructor(bmadFolderName = BMAD_FOLDER_NAME) {
|
||||
this.templatePath = path.join(__dirname, '../templates/agent-command-template.md');
|
||||
this.bmadFolderName = bmadFolderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect agent artifacts for IDE installation
|
||||
* @param {string} bmadDir - BMAD installation directory
|
||||
* @param {Array} selectedModules - Modules to include
|
||||
* @returns {Object} Artifacts array with metadata
|
||||
*/
|
||||
async collectAgentArtifacts(bmadDir, selectedModules = []) {
|
||||
const { getAgentsFromBmad } = require('./bmad-artifacts');
|
||||
|
||||
// Get agents from INSTALLED bmad/ directory
|
||||
const agents = await getAgentsFromBmad(bmadDir, selectedModules);
|
||||
|
||||
const artifacts = [];
|
||||
|
||||
for (const agent of agents) {
|
||||
const launcherContent = await this.generateLauncherContent(agent);
|
||||
// Use relativePath if available (for nested agents), otherwise just name with .md
|
||||
const agentPathInModule = agent.relativePath || `${agent.name}.md`;
|
||||
// Calculate the relative agent path (e.g., bmm/agents/pm.md)
|
||||
let agentRelPath = agent.path || '';
|
||||
// Normalize path separators for cross-platform compatibility
|
||||
agentRelPath = agentRelPath.replaceAll('\\', '/');
|
||||
// Remove _bmad/ prefix if present to get relative path from project root
|
||||
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
|
||||
if (agentRelPath.includes('_bmad/')) {
|
||||
const parts = agentRelPath.split(/_bmad\//);
|
||||
if (parts.length > 1) {
|
||||
agentRelPath = parts.slice(1).join('/');
|
||||
}
|
||||
}
|
||||
artifacts.push({
|
||||
type: 'agent-launcher',
|
||||
name: agent.name,
|
||||
description: agent.description || `${agent.name} agent`,
|
||||
module: agent.module,
|
||||
canonicalId: agent.canonicalId || '',
|
||||
relativePath: path.join(agent.module, 'agents', agentPathInModule), // For command filename
|
||||
agentPath: agentRelPath, // Relative path to actual agent file
|
||||
content: launcherContent,
|
||||
sourcePath: agent.path,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
artifacts,
|
||||
counts: {
|
||||
agents: agents.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate launcher content for an agent
|
||||
* @param {Object} agent - Agent metadata
|
||||
* @returns {string} Launcher file content
|
||||
*/
|
||||
async generateLauncherContent(agent) {
|
||||
// Load the template
|
||||
const template = await fs.readFile(this.templatePath, 'utf8');
|
||||
|
||||
// Replace template variables
|
||||
// Use relativePath if available (for nested agents), otherwise just name with .md
|
||||
const agentPathInModule = agent.relativePath || `${agent.name}.md`;
|
||||
return template
|
||||
.replaceAll('{{name}}', agent.name)
|
||||
.replaceAll('{{module}}', agent.module)
|
||||
.replaceAll('{{path}}', agentPathInModule)
|
||||
.replaceAll('{{description}}', agent.description || `${agent.name} agent`)
|
||||
.replaceAll('_bmad', this.bmadFolderName)
|
||||
.replaceAll('_bmad', '_bmad');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write agent launcher artifacts to IDE commands directory
|
||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||
* @param {Array} artifacts - Agent launcher artifacts
|
||||
* @returns {number} Count of launchers written
|
||||
*/
|
||||
async writeAgentLaunchers(baseCommandsDir, artifacts) {
|
||||
let writtenCount = 0;
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
if (artifact.type === 'agent-launcher') {
|
||||
const moduleAgentsDir = path.join(baseCommandsDir, artifact.module, 'agents');
|
||||
await fs.ensureDir(moduleAgentsDir);
|
||||
|
||||
const launcherPath = path.join(moduleAgentsDir, `${artifact.name}.md`);
|
||||
await fs.writeFile(launcherPath, artifact.content);
|
||||
writtenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return writtenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write agent launcher artifacts using underscore format (Windows-compatible)
|
||||
* Creates flat files like: bmad_bmm_pm.md
|
||||
*
|
||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||
* @param {Array} artifacts - Agent launcher artifacts
|
||||
* @returns {number} Count of launchers written
|
||||
*/
|
||||
async writeColonArtifacts(baseCommandsDir, artifacts) {
|
||||
let writtenCount = 0;
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
if (artifact.type === 'agent-launcher') {
|
||||
// Convert relativePath to underscore format: bmm/agents/pm.md → bmad_bmm_pm.md
|
||||
const flatName = toColonPath(artifact.relativePath);
|
||||
const launcherPath = path.join(baseCommandsDir, flatName);
|
||||
await fs.ensureDir(path.dirname(launcherPath));
|
||||
await fs.writeFile(launcherPath, artifact.content);
|
||||
writtenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return writtenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write agent launcher artifacts using dash format (NEW STANDARD)
|
||||
* Creates flat files like: bmad-agent-bmm-pm.md
|
||||
*
|
||||
* The bmad-agent- prefix distinguishes agents from workflows/tasks/tools.
|
||||
*
|
||||
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
||||
* @param {Array} artifacts - Agent launcher artifacts
|
||||
* @returns {number} Count of launchers written
|
||||
*/
|
||||
async writeDashArtifacts(baseCommandsDir, artifacts) {
|
||||
let writtenCount = 0;
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
if (artifact.type === 'agent-launcher') {
|
||||
// Convert relativePath to dash format: bmm/agents/pm.md → bmad-agent-bmm-pm.md
|
||||
const flatName = toDashPath(artifact.relativePath);
|
||||
const launcherPath = path.join(baseCommandsDir, flatName);
|
||||
await fs.ensureDir(path.dirname(launcherPath));
|
||||
await fs.writeFile(launcherPath, artifact.content);
|
||||
writtenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return writtenCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom agent name in underscore format (Windows-compatible)
|
||||
* @param {string} agentName - Custom agent name
|
||||
* @returns {string} Underscore-formatted filename
|
||||
*/
|
||||
getCustomAgentColonName(agentName) {
|
||||
return customAgentColonName(agentName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom agent name in underscore format (Windows-compatible)
|
||||
* @param {string} agentName - Custom agent name
|
||||
* @returns {string} Underscore-formatted filename
|
||||
*/
|
||||
getCustomAgentDashName(agentName) {
|
||||
return customAgentDashName(agentName);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { AgentCommandGenerator };
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const { loadSkillManifest, getCanonicalId } = require('./skill-manifest');
|
||||
|
||||
/**
|
||||
* Helpers for gathering BMAD agents/tasks from the installed tree.
|
||||
* Shared by installers that need Claude-style exports.
|
||||
*
|
||||
* TODO: Dead code cleanup — compiled XML agents are retired.
|
||||
*
|
||||
* All agents now use the SKILL.md directory format with bmad-skill-manifest.yaml
|
||||
* (type: agent). The legacy pipeline below only discovers compiled .md files
|
||||
* containing <agent> XML tags, which no longer exist. The following are dead:
|
||||
*
|
||||
* - getAgentsFromBmad() — scans {module}/agents/ for .md files with <agent> tags
|
||||
* - getAgentsFromDir() — recursive helper for the above
|
||||
* - AgentCommandGenerator — (agent-command-generator.js) generates launcher .md files
|
||||
* that tell the LLM to load a compiled agent .md file
|
||||
* - agent-command-template.md — (templates/) the launcher template with hardcoded
|
||||
* {module}/agents/{{path}} reference
|
||||
*
|
||||
* Agent metadata for agent-manifest.csv is now handled entirely by
|
||||
* ManifestGenerator.getAgentsFromDirRecursive() in manifest-generator.js,
|
||||
* which walks the full module tree and finds type:agent directories.
|
||||
*
|
||||
* IDE installation of agents is handled by the native skill pipeline —
|
||||
* each agent's SKILL.md directory is installed directly to the IDE's
|
||||
* skills path, so no launcher intermediary is needed.
|
||||
*
|
||||
* Cleanup: remove getAgentsFromBmad, getAgentsFromDir, their exports,
|
||||
* AgentCommandGenerator, agent-command-template.md, and all call sites
|
||||
* in IDE installers that invoke collectAgentArtifacts / writeAgentLaunchers /
|
||||
* writeColonArtifacts / writeDashArtifacts.
|
||||
* getTasksFromBmad and getTasksFromDir may still be live — verify before removing.
|
||||
*/
|
||||
async function getAgentsFromBmad(bmadDir, selectedModules = []) {
|
||||
const agents = [];
|
||||
|
||||
// Get core agents
|
||||
if (await fs.pathExists(path.join(bmadDir, 'core', 'agents'))) {
|
||||
const coreAgents = await getAgentsFromDir(path.join(bmadDir, 'core', 'agents'), 'core');
|
||||
agents.push(...coreAgents);
|
||||
}
|
||||
|
||||
// Get module agents
|
||||
for (const moduleName of selectedModules) {
|
||||
const agentsPath = path.join(bmadDir, moduleName, 'agents');
|
||||
|
||||
if (await fs.pathExists(agentsPath)) {
|
||||
const moduleAgents = await getAgentsFromDir(agentsPath, moduleName);
|
||||
agents.push(...moduleAgents);
|
||||
}
|
||||
}
|
||||
|
||||
// Get standalone agents from bmad/agents/ directory
|
||||
const standaloneAgentsDir = path.join(bmadDir, 'agents');
|
||||
if (await fs.pathExists(standaloneAgentsDir)) {
|
||||
const agentDirs = await fs.readdir(standaloneAgentsDir, { withFileTypes: true });
|
||||
|
||||
for (const agentDir of agentDirs) {
|
||||
if (!agentDir.isDirectory()) continue;
|
||||
|
||||
const agentDirPath = path.join(standaloneAgentsDir, agentDir.name);
|
||||
const agentFiles = await fs.readdir(agentDirPath);
|
||||
const skillManifest = await loadSkillManifest(agentDirPath);
|
||||
|
||||
for (const file of agentFiles) {
|
||||
if (!file.endsWith('.md')) continue;
|
||||
if (file.includes('.customize.')) continue;
|
||||
|
||||
const filePath = path.join(agentDirPath, file);
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
if (content.includes('localskip="true"')) continue;
|
||||
|
||||
agents.push({
|
||||
path: filePath,
|
||||
name: file.replace('.md', ''),
|
||||
module: 'standalone', // Mark as standalone agent
|
||||
canonicalId: getCanonicalId(skillManifest, file),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return agents;
|
||||
}
|
||||
|
||||
async function getTasksFromBmad(bmadDir, selectedModules = []) {
|
||||
const tasks = [];
|
||||
|
||||
if (await fs.pathExists(path.join(bmadDir, 'core', 'tasks'))) {
|
||||
const coreTasks = await getTasksFromDir(path.join(bmadDir, 'core', 'tasks'), 'core');
|
||||
tasks.push(...coreTasks);
|
||||
}
|
||||
|
||||
for (const moduleName of selectedModules) {
|
||||
const tasksPath = path.join(bmadDir, moduleName, 'tasks');
|
||||
|
||||
if (await fs.pathExists(tasksPath)) {
|
||||
const moduleTasks = await getTasksFromDir(tasksPath, moduleName);
|
||||
tasks.push(...moduleTasks);
|
||||
}
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
async function getAgentsFromDir(dirPath, moduleName, relativePath = '') {
|
||||
const agents = [];
|
||||
|
||||
if (!(await fs.pathExists(dirPath))) {
|
||||
return agents;
|
||||
}
|
||||
|
||||
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
||||
const skillManifest = await loadSkillManifest(dirPath);
|
||||
|
||||
for (const entry of entries) {
|
||||
// Skip if entry.name is undefined or not a string
|
||||
if (!entry.name || typeof entry.name !== 'string') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fullPath = path.join(dirPath, entry.name);
|
||||
const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Recurse into subdirectories
|
||||
const subDirAgents = await getAgentsFromDir(fullPath, moduleName, newRelativePath);
|
||||
agents.push(...subDirAgents);
|
||||
} else if (entry.name.endsWith('.md')) {
|
||||
// Skip README files and other non-agent files
|
||||
if (entry.name.toLowerCase() === 'readme.md' || entry.name.toLowerCase().startsWith('readme-')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.name.includes('.customize.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = await fs.readFile(fullPath, 'utf8');
|
||||
|
||||
if (content.includes('localskip="true"')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only include files that have agent-specific content (compiled agents have <agent> tag)
|
||||
if (!content.includes('<agent')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
agents.push({
|
||||
path: fullPath,
|
||||
name: entry.name.replace('.md', ''),
|
||||
module: moduleName,
|
||||
relativePath: newRelativePath, // Keep the .md extension for the full path
|
||||
canonicalId: getCanonicalId(skillManifest, entry.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return agents;
|
||||
}
|
||||
|
||||
async function getTasksFromDir(dirPath, moduleName) {
|
||||
const tasks = [];
|
||||
|
||||
if (!(await fs.pathExists(dirPath))) {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
const files = await fs.readdir(dirPath);
|
||||
const skillManifest = await loadSkillManifest(dirPath);
|
||||
|
||||
for (const file of files) {
|
||||
// Include both .md and .xml task files
|
||||
if (!file.endsWith('.md') && !file.endsWith('.xml')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const filePath = path.join(dirPath, file);
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
// Skip internal/engine files (not user-facing tasks)
|
||||
if (content.includes('internal="true"')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove extension to get task name
|
||||
const ext = file.endsWith('.xml') ? '.xml' : '.md';
|
||||
tasks.push({
|
||||
path: filePath,
|
||||
name: file.replace(ext, ''),
|
||||
module: moduleName,
|
||||
canonicalId: getCanonicalId(skillManifest, file),
|
||||
});
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAgentsFromBmad,
|
||||
getTasksFromBmad,
|
||||
getAgentsFromDir,
|
||||
getTasksFromDir,
|
||||
};
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
const path = require('node:path');
|
||||
const fs = require('fs-extra');
|
||||
const yaml = require('yaml');
|
||||
const { glob } = require('glob');
|
||||
const { getSourcePath } = require('../../project-root');
|
||||
|
||||
async function loadModuleInjectionConfig(handler, moduleName) {
|
||||
const sourceModulesPath = getSourcePath('modules');
|
||||
const handlerBaseDir = path.join(sourceModulesPath, moduleName, 'sub-modules', handler);
|
||||
const configPath = path.join(handlerBaseDir, 'injections.yaml');
|
||||
|
||||
if (!(await fs.pathExists(configPath))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const configContent = await fs.readFile(configPath, 'utf8');
|
||||
const config = yaml.parse(configContent) || {};
|
||||
|
||||
return {
|
||||
config,
|
||||
handlerBaseDir,
|
||||
configPath,
|
||||
};
|
||||
}
|
||||
|
||||
function shouldApplyInjection(injection, subagentChoices) {
|
||||
if (!subagentChoices || subagentChoices.install === 'none') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (subagentChoices.install === 'all') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (subagentChoices.install === 'selective') {
|
||||
const selected = subagentChoices.selected || [];
|
||||
|
||||
if (injection.requires === 'any' && selected.length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (injection.requires) {
|
||||
const required = `${injection.requires}.md`;
|
||||
return selected.includes(required);
|
||||
}
|
||||
|
||||
if (injection.point) {
|
||||
const selectedNames = selected.map((file) => file.replace('.md', ''));
|
||||
return selectedNames.some((name) => injection.point.includes(name));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function filterAgentInstructions(content, selectedFiles) {
|
||||
if (!selectedFiles || selectedFiles.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const selectedAgents = selectedFiles.map((file) => file.replace('.md', ''));
|
||||
const lines = content.split('\n');
|
||||
const filteredLines = [];
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.includes('<llm') || line.includes('</llm>')) {
|
||||
filteredLines.push(line);
|
||||
} else if (line.includes('subagent')) {
|
||||
let shouldInclude = false;
|
||||
for (const agent of selectedAgents) {
|
||||
if (line.includes(agent)) {
|
||||
shouldInclude = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldInclude) {
|
||||
filteredLines.push(line);
|
||||
}
|
||||
} else if (line.includes('When creating PRDs') || line.includes('ACTIVELY delegate')) {
|
||||
filteredLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredLines.length > 2) {
|
||||
return filteredLines.join('\n');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
async function resolveSubagentFiles(handlerBaseDir, subagentConfig, subagentChoices) {
|
||||
if (!subagentConfig || !subagentConfig.files) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!subagentChoices || subagentChoices.install === 'none') {
|
||||
return [];
|
||||
}
|
||||
|
||||
let filesToCopy = subagentConfig.files;
|
||||
|
||||
if (subagentChoices.install === 'selective') {
|
||||
filesToCopy = subagentChoices.selected || [];
|
||||
}
|
||||
|
||||
const sourceDir = path.join(handlerBaseDir, subagentConfig.source || '');
|
||||
const resolved = [];
|
||||
|
||||
for (const file of filesToCopy) {
|
||||
// Use forward slashes for glob pattern (works on both Windows and Unix)
|
||||
// Convert backslashes to forward slashes for glob compatibility
|
||||
const normalizedSourceDir = sourceDir.replaceAll('\\', '/');
|
||||
const pattern = `${normalizedSourceDir}/**/${file}`;
|
||||
const matches = await glob(pattern);
|
||||
|
||||
if (matches.length > 0) {
|
||||
const absolutePath = matches[0];
|
||||
resolved.push({
|
||||
file,
|
||||
absolutePath,
|
||||
relativePath: path.relative(sourceDir, absolutePath),
|
||||
sourceDir,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loadModuleInjectionConfig,
|
||||
shouldApplyInjection,
|
||||
filterAgentInstructions,
|
||||
resolveSubagentFiles,
|
||||
};
|
||||
|
|
@ -15,8 +15,6 @@
|
|||
* - standalone/agents/fred.md → bmad-agent-standalone-fred.md
|
||||
*/
|
||||
|
||||
// Type segments - agents are included in naming, others are filtered out
|
||||
const TYPE_SEGMENTS = ['workflows', 'tasks', 'tools'];
|
||||
const AGENT_SEGMENT = 'agents';
|
||||
|
||||
// BMAD installation folder name - centralized constant for all installers
|
||||
|
|
@ -194,125 +192,6 @@ function parseDashName(filename) {
|
|||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LEGACY FUNCTIONS (underscore format) - kept for backward compatibility
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Convert hierarchical path to flat underscore-separated name (LEGACY)
|
||||
* @deprecated Use toDashName instead
|
||||
*/
|
||||
function toUnderscoreName(module, type, name) {
|
||||
const isAgent = type === AGENT_SEGMENT;
|
||||
if (module === 'core') {
|
||||
return isAgent ? `bmad_agent_${name}.md` : `bmad_${name}.md`;
|
||||
}
|
||||
if (module === 'standalone') {
|
||||
return isAgent ? `bmad_agent_standalone_${name}.md` : `bmad_standalone_${name}.md`;
|
||||
}
|
||||
return isAgent ? `bmad_${module}_agent_${name}.md` : `bmad_${module}_${name}.md`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert relative path to flat underscore-separated name (LEGACY)
|
||||
* @deprecated Use toDashPath instead
|
||||
*/
|
||||
function toUnderscorePath(relativePath) {
|
||||
// Strip common file extensions (same as toDashPath for consistency)
|
||||
const withoutExt = relativePath.replace(/\.(md|yaml|yml|json|xml|toml)$/i, '');
|
||||
const parts = withoutExt.split(/[/\\]/);
|
||||
|
||||
const module = parts[0];
|
||||
const type = parts[1];
|
||||
const name = parts.slice(2).join('_');
|
||||
|
||||
return toUnderscoreName(module, type, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create custom agent underscore name (LEGACY)
|
||||
* @deprecated Use customAgentDashName instead
|
||||
*/
|
||||
function customAgentUnderscoreName(agentName) {
|
||||
return `bmad_custom_${agentName}.md`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a filename uses underscore format (LEGACY)
|
||||
* @deprecated Use isDashFormat instead
|
||||
*/
|
||||
function isUnderscoreFormat(filename) {
|
||||
return filename.startsWith('bmad_') && filename.includes('_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract parts from an underscore-formatted filename (LEGACY)
|
||||
* @deprecated Use parseDashName instead
|
||||
*/
|
||||
function parseUnderscoreName(filename) {
|
||||
const withoutExt = filename.replace('.md', '');
|
||||
const parts = withoutExt.split('_');
|
||||
|
||||
if (parts.length < 2 || parts[0] !== 'bmad') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const agentIndex = parts.indexOf('agent');
|
||||
|
||||
if (agentIndex !== -1) {
|
||||
if (agentIndex === 1) {
|
||||
// bmad_agent_... - check for standalone
|
||||
if (parts.length >= 4 && parts[2] === 'standalone') {
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: 'standalone',
|
||||
type: 'agents',
|
||||
name: parts.slice(3).join('_'),
|
||||
};
|
||||
}
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: 'core',
|
||||
type: 'agents',
|
||||
name: parts.slice(agentIndex + 1).join('_'),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: parts[1],
|
||||
type: 'agents',
|
||||
name: parts.slice(agentIndex + 1).join('_'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (parts.length === 2) {
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: 'core',
|
||||
type: 'workflows',
|
||||
name: parts[1],
|
||||
};
|
||||
}
|
||||
|
||||
// Check for standalone non-agent: bmad_standalone_name
|
||||
if (parts[1] === 'standalone') {
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: 'standalone',
|
||||
type: 'workflows',
|
||||
name: parts.slice(2).join('_'),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
prefix: parts[0],
|
||||
module: parts[1],
|
||||
type: 'workflows',
|
||||
name: parts.slice(2).join('_'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the skill name for an artifact.
|
||||
* Prefers canonicalId from a bmad-skill-manifest.yaml sidecar when available,
|
||||
|
|
@ -328,37 +207,13 @@ function resolveSkillName(artifact) {
|
|||
return toDashPath(artifact.relativePath);
|
||||
}
|
||||
|
||||
// Backward compatibility aliases (colon format was same as underscore)
|
||||
const toColonName = toUnderscoreName;
|
||||
const toColonPath = toUnderscorePath;
|
||||
const customAgentColonName = customAgentUnderscoreName;
|
||||
const isColonFormat = isUnderscoreFormat;
|
||||
const parseColonName = parseUnderscoreName;
|
||||
|
||||
module.exports = {
|
||||
// New standard (dash-based)
|
||||
toDashName,
|
||||
toDashPath,
|
||||
resolveSkillName,
|
||||
customAgentDashName,
|
||||
isDashFormat,
|
||||
parseDashName,
|
||||
|
||||
// Legacy (underscore-based) - kept for backward compatibility
|
||||
toUnderscoreName,
|
||||
toUnderscorePath,
|
||||
customAgentUnderscoreName,
|
||||
isUnderscoreFormat,
|
||||
parseUnderscoreName,
|
||||
|
||||
// Backward compatibility aliases
|
||||
toColonName,
|
||||
toColonPath,
|
||||
customAgentColonName,
|
||||
isColonFormat,
|
||||
parseColonName,
|
||||
|
||||
TYPE_SEGMENTS,
|
||||
AGENT_SEGMENT,
|
||||
BMAD_FOLDER_NAME,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
||||
|
||||
<agent-activation CRITICAL="TRUE">
|
||||
1. LOAD the FULL agent file from {project-root}/_bmad/{{module}}/agents/{{path}}
|
||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
||||
3. Execute ALL activation steps exactly as written in the agent file
|
||||
4. Follow the agent's persona and menu system precisely
|
||||
5. Stay in character throughout the session
|
||||
</agent-activation>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
@ -1 +0,0 @@
|
|||
default-agent.md
|
||||
|
|
@ -1 +0,0 @@
|
|||
default-workflow.md
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
||||
|
||||
<agent-activation CRITICAL="TRUE">
|
||||
1. LOAD the FULL agent file from {project-root}/_bmad/{{path}}
|
||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
||||
3. FOLLOW every step in the <activation> section precisely
|
||||
4. DISPLAY the welcome/greeting as instructed
|
||||
5. PRESENT the numbered menu
|
||||
6. WAIT for user input before proceeding
|
||||
</agent-activation>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
Read the entire task file at: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
||||
Follow all instructions in the task file exactly as written.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
Read the entire tool file at: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
||||
Follow all instructions in the tool file exactly as written.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
name: '{{name}}'
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL {project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
description = "Activates the {{name}} agent from the BMad Method."
|
||||
prompt = """
|
||||
CRITICAL: You are now the BMad '{{name}}' agent.
|
||||
|
||||
PRE-FLIGHT CHECKLIST:
|
||||
1. [ ] IMMEDIATE ACTION: Load and parse {project-root}/{{bmadFolderName}}/{{module}}/config.yaml - store ALL config values in memory for use throughout the session.
|
||||
2. [ ] IMMEDIATE ACTION: Read and internalize the full agent definition at {project-root}/{{bmadFolderName}}/{{path}}.
|
||||
3. [ ] CONFIRM: The user's name from config is {user_name}.
|
||||
|
||||
Only after all checks are complete, greet the user by name and display the menu.
|
||||
Acknowledge this checklist is complete in your first response.
|
||||
|
||||
AGENT DEFINITION: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
"""
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
description = "Executes the {{name}} task from the BMAD Method."
|
||||
prompt = """
|
||||
Execute the BMAD '{{name}}' task.
|
||||
|
||||
TASK INSTRUCTIONS:
|
||||
1. LOAD the task file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every instruction precisely as specified
|
||||
|
||||
TASK FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
"""
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
description = "Executes the {{name}} tool from the BMAD Method."
|
||||
prompt = """
|
||||
Execute the BMAD '{{name}}' tool.
|
||||
|
||||
TOOL INSTRUCTIONS:
|
||||
1. LOAD the tool file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every instruction precisely as specified
|
||||
|
||||
TOOL FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
"""
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
description = '{{description}}'
|
||||
prompt = """
|
||||
Execute the BMAD '{{name}}' workflow.
|
||||
|
||||
CRITICAL: This is a structured YAML workflow. Follow these steps precisely:
|
||||
|
||||
1. LOAD the workflow definition from {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||
2. PARSE the YAML structure to understand:
|
||||
- Workflow phases and steps
|
||||
- Required inputs and outputs
|
||||
- Dependencies between steps
|
||||
3. EXECUTE each step in order
|
||||
4. VALIDATE outputs before proceeding to next step
|
||||
|
||||
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||
"""
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
description = '{{description}}'
|
||||
prompt = """
|
||||
Execute the BMAD '{{name}}' workflow.
|
||||
|
||||
CRITICAL: You must load and follow the workflow definition exactly.
|
||||
|
||||
WORKFLOW INSTRUCTIONS:
|
||||
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every step precisely as specified
|
||||
4. DO NOT skip or modify any steps
|
||||
|
||||
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
|
||||
"""
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
inclusion: manual
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
||||
|
||||
<agent-activation CRITICAL="TRUE">
|
||||
1. LOAD the FULL agent file from #[[file:{{bmadFolderName}}/{{path}}]]
|
||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
||||
3. FOLLOW every step in the <activation> section precisely
|
||||
4. DISPLAY the welcome/greeting as instructed
|
||||
5. PRESENT the numbered menu
|
||||
6. WAIT for user input before proceeding
|
||||
</agent-activation>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
inclusion: manual
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
Read the entire task file at: #[[file:{{bmadFolderName}}/{{path}}]]
|
||||
|
||||
Follow all instructions in the task file exactly as written.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
inclusion: manual
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
Read the entire tool file at: #[[file:{{bmadFolderName}}/{{path}}]]
|
||||
|
||||
Follow all instructions in the tool file exactly as written.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
inclusion: manual
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL #[[file:{{bmadFolderName}}/{{path}}]], READ its entire contents and follow its directions exactly!
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
mode: all
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
||||
|
||||
<agent-activation CRITICAL="TRUE">
|
||||
1. LOAD the FULL agent file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
||||
3. FOLLOW every step in the <activation> section precisely
|
||||
4. DISPLAY the welcome/greeting as instructed
|
||||
5. PRESENT the numbered menu
|
||||
6. WAIT for user input before proceeding
|
||||
</agent-activation>
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
Execute the BMAD '{{name}}' task.
|
||||
|
||||
TASK INSTRUCTIONS:
|
||||
|
||||
1. LOAD the task file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every instruction precisely as specified
|
||||
|
||||
TASK FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
Execute the BMAD '{{name}}' tool.
|
||||
|
||||
TOOL INSTRUCTIONS:
|
||||
|
||||
1. LOAD the tool file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every instruction precisely as specified
|
||||
|
||||
TOOL FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
Execute the BMAD '{{name}}' workflow.
|
||||
|
||||
CRITICAL: You must load and follow the workflow definition exactly.
|
||||
|
||||
WORKFLOW INSTRUCTIONS:
|
||||
|
||||
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every step precisely as specified
|
||||
4. DO NOT skip or modify any steps
|
||||
|
||||
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
description: '{{description}}'
|
||||
---
|
||||
|
||||
Execute the BMAD '{{name}}' workflow.
|
||||
|
||||
CRITICAL: You must load and follow the workflow definition exactly.
|
||||
|
||||
WORKFLOW INSTRUCTIONS:
|
||||
|
||||
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{path}}
|
||||
2. READ its entire contents
|
||||
3. FOLLOW every step precisely as specified
|
||||
4. DO NOT skip or modify any steps
|
||||
|
||||
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# {{name}}
|
||||
|
||||
{{description}}
|
||||
|
||||
---
|
||||
|
||||
Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# {{name}}
|
||||
|
||||
{{description}}
|
||||
|
||||
## Instructions
|
||||
|
||||
Read the entire workflow file at: {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
description: '{{description}}'
|
||||
auto_execution_mode: "iterate"
|
||||
---
|
||||
|
||||
# {{name}}
|
||||
|
||||
Read the entire workflow file at {project-root}/_bmad/{{workflow_path}}
|
||||
|
||||
Follow all instructions in the workflow file exactly as written.
|
||||
|
|
@ -155,33 +155,6 @@ class CustomModuleManager {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use parseSource() instead. Kept for backward compatibility.
|
||||
* Parse and validate a GitHub repository URL.
|
||||
* @param {string} url - GitHub URL to validate
|
||||
* @returns {Object} { owner, repo, isValid, error }
|
||||
*/
|
||||
validateGitHubUrl(url) {
|
||||
if (!url || typeof url !== 'string') {
|
||||
return { owner: null, repo: null, isValid: false, error: 'URL is required' };
|
||||
}
|
||||
const trimmed = url.trim();
|
||||
|
||||
// HTTPS format: https://github.com/owner/repo[.git] (strict, no trailing path)
|
||||
const httpsMatch = trimmed.match(/^https?:\/\/github\.com\/([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
||||
if (httpsMatch) {
|
||||
return { owner: httpsMatch[1], repo: httpsMatch[2], isValid: true, error: null };
|
||||
}
|
||||
|
||||
// SSH format: git@github.com:owner/repo[.git]
|
||||
const sshMatch = trimmed.match(/^git@github\.com:([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
||||
if (sshMatch) {
|
||||
return { owner: sshMatch[1], repo: sshMatch[2], isValid: true, error: null };
|
||||
}
|
||||
|
||||
return { owner: null, repo: null, isValid: false, error: 'Not a valid GitHub URL (expected https://github.com/owner/repo)' };
|
||||
}
|
||||
|
||||
// ─── Marketplace JSON ─────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -109,46 +109,6 @@ class ExternalModuleManager {
|
|||
return modules.find((m) => m.code === code) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module info by key
|
||||
* @param {string} key - The module key (e.g., 'bmad-creative-intelligence-suite')
|
||||
* @returns {Object|null} Module info or null if not found
|
||||
*/
|
||||
async getModuleByKey(key) {
|
||||
const modules = await this.listAvailable();
|
||||
return modules.find((m) => m.key === key) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a module code exists in external modules
|
||||
* @param {string} code - The module code to check
|
||||
* @returns {boolean} True if the module exists
|
||||
*/
|
||||
async hasModule(code) {
|
||||
const module = await this.getModuleByCode(code);
|
||||
return module !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for a module by code
|
||||
* @param {string} code - The module code
|
||||
* @returns {string|null} The URL or null if not found
|
||||
*/
|
||||
async getModuleUrl(code) {
|
||||
const module = await this.getModuleByCode(code);
|
||||
return module ? module.url : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module definition path for a module by code
|
||||
* @param {string} code - The module code
|
||||
* @returns {string|null} The module definition path or null if not found
|
||||
*/
|
||||
async getModuleDefinition(code) {
|
||||
const module = await this.getModuleByCode(code);
|
||||
return module ? module.moduleDefinition : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache directory for external modules
|
||||
* @returns {string} Path to the external modules cache directory
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ class OfficialModules {
|
|||
// Config collection state (merged from ConfigCollector)
|
||||
this.collectedConfig = {};
|
||||
this._existingConfig = null;
|
||||
// Tracked during interactive config collection so {directory_name}
|
||||
// placeholder defaults can be resolved in buildQuestion().
|
||||
this.currentProjectDir = null;
|
||||
}
|
||||
|
||||
|
|
@ -500,32 +502,6 @@ class OfficialModules {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all .md agent files recursively in a directory
|
||||
* @param {string} dir - Directory to search
|
||||
* @returns {Array} List of .md agent file paths
|
||||
*/
|
||||
async findAgentMdFiles(dir) {
|
||||
const agentFiles = [];
|
||||
|
||||
async function searchDirectory(searchDir) {
|
||||
const entries = await fs.readdir(searchDir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(searchDir, entry.name);
|
||||
|
||||
if (entry.isFile() && entry.name.endsWith('.md')) {
|
||||
agentFiles.push(fullPath);
|
||||
} else if (entry.isDirectory()) {
|
||||
await searchDirectory(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await searchDirectory(dir);
|
||||
return agentFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create directories declared in module.yaml's `directories` key
|
||||
* This replaces the security-risky module installer pattern with declarative config
|
||||
|
|
@ -699,29 +675,6 @@ class OfficialModules {
|
|||
return { createdDirs, movedDirs, createdWdsFolders };
|
||||
}
|
||||
|
||||
/**
|
||||
* Private: Process module configuration
|
||||
* @param {string} modulePath - Path to installed module
|
||||
* @param {string} moduleName - Module name
|
||||
*/
|
||||
async processModuleConfig(modulePath, moduleName) {
|
||||
const configPath = path.join(modulePath, 'config.yaml');
|
||||
|
||||
if (await fs.pathExists(configPath)) {
|
||||
try {
|
||||
let configContent = await fs.readFile(configPath, 'utf8');
|
||||
|
||||
// Replace path placeholders
|
||||
configContent = configContent.replaceAll('{project-root}', `bmad/${moduleName}`);
|
||||
configContent = configContent.replaceAll('{module}', moduleName);
|
||||
|
||||
await fs.writeFile(configPath, configContent, 'utf8');
|
||||
} catch (error) {
|
||||
await prompts.log.warn(`Failed to process module config: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Private: Sync module files (preserving user modifications)
|
||||
* @param {string} sourcePath - Source module path
|
||||
|
|
@ -1091,7 +1044,6 @@ class OfficialModules {
|
|||
*/
|
||||
async collectModuleConfigQuick(moduleName, projectDir, silentMode = true) {
|
||||
this.currentProjectDir = projectDir;
|
||||
|
||||
// Load existing config if not already loaded
|
||||
if (!this._existingConfig) {
|
||||
await this.loadExistingConfig(projectDir);
|
||||
|
|
|
|||
|
|
@ -50,17 +50,6 @@ class RegistryClient {
|
|||
const content = await this.fetch(url, timeout);
|
||||
return yaml.parse(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a URL and parse the response as JSON.
|
||||
* @param {string} url - URL to fetch
|
||||
* @param {number} [timeout] - Timeout in ms
|
||||
* @returns {Promise<Object>} Parsed JSON content
|
||||
*/
|
||||
async fetchJson(url, timeout) {
|
||||
const content = await this.fetch(url, timeout);
|
||||
return JSON.parse(content);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { RegistryClient };
|
||||
|
|
|
|||
|
|
@ -498,26 +498,6 @@ async function password(options) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group multiple prompts together
|
||||
* @param {Object} prompts - Object of prompt functions
|
||||
* @param {Object} [options] - Group options
|
||||
* @returns {Promise<Object>} Object with all answers
|
||||
*/
|
||||
async function group(prompts, options = {}) {
|
||||
const clack = await getClack();
|
||||
|
||||
const result = await clack.group(prompts, {
|
||||
onCancel: () => {
|
||||
clack.cancel('Operation cancelled');
|
||||
process.exit(0);
|
||||
},
|
||||
...options,
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run tasks with spinner feedback
|
||||
* @param {Array} tasks - Array of task objects [{title, task, enabled?}]
|
||||
|
|
@ -578,42 +558,6 @@ async function box(content, title, options) {
|
|||
clack.box(content, title, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a progress bar for visualizing task completion
|
||||
* @param {Object} [options] - Progress options (max, style, etc.)
|
||||
* @returns {Promise<Object>} Progress controller with start, advance, stop methods
|
||||
*/
|
||||
async function progress(options) {
|
||||
const clack = await getClack();
|
||||
return clack.progress(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task log for displaying scrolling subprocess output
|
||||
* @param {Object} options - TaskLog options (title, limit, retainLog)
|
||||
* @returns {Promise<Object>} TaskLog controller with message, success, error methods
|
||||
*/
|
||||
async function taskLog(options) {
|
||||
const clack = await getClack();
|
||||
return clack.taskLog(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* File system path prompt with autocomplete
|
||||
* @param {Object} options - Path options
|
||||
* @param {string} options.message - The prompt message
|
||||
* @param {string} [options.initialValue] - Initial path value
|
||||
* @param {boolean} [options.directory=false] - Only allow directories
|
||||
* @param {Function} [options.validate] - Validation function
|
||||
* @returns {Promise<string>} Selected path
|
||||
*/
|
||||
async function pathPrompt(options) {
|
||||
const clack = await getClack();
|
||||
const result = await clack.path(options);
|
||||
await handleCancel(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autocomplete single-select prompt with type-ahead filtering
|
||||
* @param {Object} options - Autocomplete options
|
||||
|
|
@ -631,50 +575,6 @@ async function autocomplete(options) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key-based instant selection prompt
|
||||
* @param {Object} options - SelectKey options
|
||||
* @param {string} options.message - The prompt message
|
||||
* @param {Array} options.options - Array of choices [{value, label, hint?}]
|
||||
* @returns {Promise<any>} Selected value
|
||||
*/
|
||||
async function selectKey(options) {
|
||||
const clack = await getClack();
|
||||
const result = await clack.selectKey(options);
|
||||
await handleCancel(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream messages with dynamic content (for LLMs, generators, etc.)
|
||||
*/
|
||||
const stream = {
|
||||
async info(generator) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.info(generator);
|
||||
},
|
||||
async success(generator) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.success(generator);
|
||||
},
|
||||
async step(generator) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.step(generator);
|
||||
},
|
||||
async warn(generator) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.warn(generator);
|
||||
},
|
||||
async error(generator) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.error(generator);
|
||||
},
|
||||
async message(generator, options) {
|
||||
const clack = await getClack();
|
||||
return clack.stream.message(generator, options);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the color utility (picocolors instance from @clack/prompts)
|
||||
* @returns {Promise<Object>} The color utility (picocolors)
|
||||
|
|
@ -790,20 +690,14 @@ module.exports = {
|
|||
note,
|
||||
box,
|
||||
spinner,
|
||||
progress,
|
||||
taskLog,
|
||||
select,
|
||||
multiselect,
|
||||
autocompleteMultiselect,
|
||||
autocomplete,
|
||||
selectKey,
|
||||
confirm,
|
||||
text,
|
||||
path: pathPrompt,
|
||||
password,
|
||||
group,
|
||||
tasks,
|
||||
log,
|
||||
stream,
|
||||
prompt,
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Loading…
Reference in New Issue