ma-agents 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/skills/.ma-agents.json +99 -99
- package/.roo/rules/00-ma-agents.md +13 -0
- package/.roo/skills/.ma-agents.json +241 -0
- package/.roo/skills/MANIFEST.yaml +254 -0
- package/.roo/skills/ai-audit-trail/SKILL.md +23 -0
- package/.roo/skills/auto-bug-detection/SKILL.md +169 -0
- package/.roo/skills/cmake-best-practices/SKILL.md +64 -0
- package/.roo/skills/cmake-best-practices/examples/cmake.md +59 -0
- package/.roo/skills/code-documentation/SKILL.md +57 -0
- package/.roo/skills/code-documentation/examples/cpp.md +29 -0
- package/.roo/skills/code-documentation/examples/csharp.md +28 -0
- package/.roo/skills/code-documentation/examples/javascript_typescript.md +28 -0
- package/.roo/skills/code-documentation/examples/python.md +57 -0
- package/.roo/skills/code-review/SKILL.md +43 -0
- package/.roo/skills/commit-message/SKILL.md +79 -0
- package/.roo/skills/cpp-best-practices/SKILL.md +234 -0
- package/.roo/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
- package/.roo/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
- package/.roo/skills/cpp-concurrency-safety/SKILL.md +60 -0
- package/.roo/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
- package/.roo/skills/cpp-const-correctness/SKILL.md +63 -0
- package/.roo/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
- package/.roo/skills/cpp-memory-handling/SKILL.md +42 -0
- package/.roo/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
- package/.roo/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
- package/.roo/skills/cpp-modern-composition/SKILL.md +64 -0
- package/.roo/skills/cpp-modern-composition/examples/composition.md +51 -0
- package/.roo/skills/cpp-robust-interfaces/SKILL.md +55 -0
- package/.roo/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
- package/.roo/skills/create-hardened-docker-skill/SKILL.md +637 -0
- package/.roo/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
- package/.roo/skills/csharp-best-practices/SKILL.md +278 -0
- package/.roo/skills/docker-hardening-verification/SKILL.md +28 -0
- package/.roo/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
- package/.roo/skills/docker-image-signing/SKILL.md +28 -0
- package/.roo/skills/docker-image-signing/scripts/sign-image.sh +33 -0
- package/.roo/skills/document-revision-history/SKILL.md +104 -0
- package/.roo/skills/git-workflow-skill/SKILL.md +194 -0
- package/.roo/skills/git-workflow-skill/hooks/commit-msg +61 -0
- package/.roo/skills/git-workflow-skill/hooks/pre-commit +38 -0
- package/.roo/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
- package/.roo/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
- package/.roo/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
- package/.roo/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
- package/.roo/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
- package/.roo/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
- package/.roo/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
- package/.roo/skills/js-ts-security-skill/SKILL.md +64 -0
- package/.roo/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
- package/.roo/skills/logging-best-practices/SKILL.md +50 -0
- package/.roo/skills/logging-best-practices/examples/cpp.md +36 -0
- package/.roo/skills/logging-best-practices/examples/csharp.md +49 -0
- package/.roo/skills/logging-best-practices/examples/javascript.md +77 -0
- package/.roo/skills/logging-best-practices/examples/python.md +57 -0
- package/.roo/skills/logging-best-practices/references/logging-standards.md +29 -0
- package/.roo/skills/open-presentation/SKILL.md +35 -0
- package/.roo/skills/opentelemetry-best-practices/SKILL.md +34 -0
- package/.roo/skills/opentelemetry-best-practices/examples/go.md +32 -0
- package/.roo/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
- package/.roo/skills/opentelemetry-best-practices/examples/python.md +37 -0
- package/.roo/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
- package/.roo/skills/python-best-practices/SKILL.md +385 -0
- package/.roo/skills/python-dependency-mgmt/SKILL.md +42 -0
- package/.roo/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
- package/.roo/skills/python-security-skill/SKILL.md +56 -0
- package/.roo/skills/python-security-skill/examples/security.md +56 -0
- package/.roo/skills/self-signed-cert/SKILL.md +42 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
- package/.roo/skills/skill-creator/SKILL.md +196 -0
- package/.roo/skills/skill-creator/references/output-patterns.md +82 -0
- package/.roo/skills/skill-creator/references/workflows.md +28 -0
- package/.roo/skills/skill-creator/scripts/init_skill.py +208 -0
- package/.roo/skills/skill-creator/scripts/package_skill.py +99 -0
- package/.roo/skills/skill-creator/scripts/quick_validate.py +113 -0
- package/.roo/skills/story-status-lookup/SKILL.md +78 -0
- package/.roo/skills/test-accompanied-development/SKILL.md +50 -0
- package/.roo/skills/test-generator/SKILL.md +65 -0
- package/.roo/skills/vercel-react-best-practices/SKILL.md +109 -0
- package/.roo/skills/verify-hardened-docker-skill/SKILL.md +442 -0
- package/.roo/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
- package/README.md +50 -3
- package/lib/agents.js +23 -0
- package/lib/bmad-extension/module-help.csv +8 -4
- package/lib/bmad-extension/skills/add-sprint/SKILL.md +126 -40
- package/lib/bmad-extension/skills/add-to-sprint/SKILL.md +116 -142
- package/lib/bmad-extension/skills/cleanup-done/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cleanup-done/SKILL.md +159 -0
- package/lib/bmad-extension/skills/cleanup-done/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/create-bug-story/SKILL.md +75 -7
- package/lib/bmad-extension/skills/generate-backlog/SKILL.md +183 -0
- package/lib/bmad-extension/skills/generate-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/modify-sprint/SKILL.md +63 -0
- package/lib/bmad-extension/skills/prioritize-backlog/.gitkeep +0 -0
- package/lib/bmad-extension/skills/prioritize-backlog/SKILL.md +195 -0
- package/lib/bmad-extension/skills/prioritize-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/remove-from-sprint/.gitkeep +0 -0
- package/lib/bmad-extension/skills/remove-from-sprint/SKILL.md +163 -0
- package/lib/bmad-extension/skills/remove-from-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sprint-status-view/SKILL.md +199 -138
- package/lib/bmad-extension/workflows/add-sprint/workflow.md +129 -39
- package/lib/bmad-extension/workflows/add-to-sprint/workflow.md +3 -205
- package/lib/bmad-extension/workflows/modify-sprint/workflow.md +5 -0
- package/lib/bmad-extension/workflows/sprint-status-view/workflow.md +3 -192
- package/package.json +4 -3
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -1,206 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- This workflow has been superseded by lib/bmad-extension/skills/add-to-sprint/SKILL.md -->
|
|
2
|
+
<!-- Resolved via skill:add-to-sprint in module-help.csv -->
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<workflow>
|
|
6
|
-
|
|
7
|
-
<step n="1a" goal="Discover user story backlog items from sprint-status.yaml">
|
|
8
|
-
<action>Read `_bmad-output/implementation-artifacts/sprint-status.yaml` — authoritative source for user story execution status</action>
|
|
9
|
-
<action>Parse the development_status section. For each entry:
|
|
10
|
-
- Skip epic keys (keys matching `epic-*`)
|
|
11
|
-
- Skip retrospective keys (keys ending with `-retrospective`)
|
|
12
|
-
- Collect story keys and their current status (backlog, ready-for-dev, in-progress, review, done)
|
|
13
|
-
</action>
|
|
14
|
-
<action>Store as {{user_stories}} — list of objects with: key, status</action>
|
|
15
|
-
<action>Infer story title from key (e.g., `12-1-add-sprint-workflow` → "Add Sprint Workflow")</action>
|
|
16
|
-
</step>
|
|
17
|
-
|
|
18
|
-
<step n="1b" goal="Discover bug story backlog items">
|
|
19
|
-
<action>Glob `_bmad-output/implementation-artifacts/bug-*.md` to discover all bug story files</action>
|
|
20
|
-
<check if="no bug files found">
|
|
21
|
-
<action>Set {{bug_stories}} = [] (empty list)</action>
|
|
22
|
-
</check>
|
|
23
|
-
<check if="bug files found">
|
|
24
|
-
<action>For each bug file, parse YAML frontmatter to extract: `type`, `severity`, `title`</action>
|
|
25
|
-
<action>Store as {{bug_stories}} — list of objects with: file, type (bug), severity, title</action>
|
|
26
|
-
</check>
|
|
27
|
-
</step>
|
|
28
|
-
|
|
29
|
-
<step n="1c" goal="Filter out items already assigned to any sprint">
|
|
30
|
-
<action>Glob `_bmad-output/implementation-artifacts/sprint-plan-*.yaml` to discover all existing sprint artifact files</action>
|
|
31
|
-
<action>For each sprint file found, read its assigned_items list</action>
|
|
32
|
-
<action>Build {{all_assigned_items}} = flat set of every item identifier (story keys and bug basenames) across ALL sprint plans</action>
|
|
33
|
-
<action>Filter {{user_stories}}: remove any story whose key is present in {{all_assigned_items}}</action>
|
|
34
|
-
<action>Filter {{bug_stories}}: remove any bug whose file basename is present in {{all_assigned_items}}</action>
|
|
35
|
-
<action>Items already assigned to any sprint will NOT appear in the backlog — this prevents duplicate assignment</action>
|
|
36
|
-
<check if="no sprint files found">
|
|
37
|
-
<action>Set {{all_assigned_items}} = [] — no filtering needed when no sprints exist yet</action>
|
|
38
|
-
</check>
|
|
39
|
-
</step>
|
|
40
|
-
|
|
41
|
-
<step n="2" goal="Present flat backlog combining stories and bugs">
|
|
42
|
-
<action>Combine {{user_stories}} and {{bug_stories}} into a flat backlog list</action>
|
|
43
|
-
<action>Stories and bugs are peers — no epic grouping (FR65)</action>
|
|
44
|
-
<output>
|
|
45
|
-
## 📋 Backlog Items
|
|
46
|
-
|
|
47
|
-
| # | ID / File | Title | Type | Status/Severity |
|
|
48
|
-
|---|---|---|---|---|
|
|
49
|
-
{{#each backlog_items}}
|
|
50
|
-
| {{@index+1}} | {{id}} | {{title}} | {{type}} | {{status_or_severity}} |
|
|
51
|
-
{{/each}}
|
|
52
|
-
|
|
53
|
-
*Total: {{story_count}} stories, {{bug_count}} bugs*
|
|
54
|
-
</output>
|
|
55
|
-
</step>
|
|
56
|
-
|
|
57
|
-
<step n="3" goal="List available sprints and select target sprint">
|
|
58
|
-
<action>Glob `_bmad-output/implementation-artifacts/sprint-plan-*.yaml` to discover all sprint artifact files</action>
|
|
59
|
-
<check if="no sprint files found">
|
|
60
|
-
<output>❌ No sprint plans found. Run `/add-sprint` first to create a sprint before assigning items.</output>
|
|
61
|
-
<action>Exit workflow</action>
|
|
62
|
-
</check>
|
|
63
|
-
<action>For each sprint file found, read and extract: sprint_number, sprint_name, capacity, assigned_items count, status</action>
|
|
64
|
-
<output>
|
|
65
|
-
## 🏃 Available Sprints
|
|
66
|
-
|
|
67
|
-
| # | Sprint | Status | Capacity | Assigned | Remaining |
|
|
68
|
-
|---|---|---|---|---|---|
|
|
69
|
-
{{#each sprints}}
|
|
70
|
-
| {{@index+1}} | {{sprint_name}} | {{status}} | {{capacity}} | {{assigned_count}} | {{remaining}} |
|
|
71
|
-
{{/each}}
|
|
72
|
-
</output>
|
|
73
|
-
<ask>Select target sprint (enter number):</ask>
|
|
74
|
-
<action>Store selected sprint data as {{target_sprint}}</action>
|
|
75
|
-
</step>
|
|
76
|
-
|
|
77
|
-
<step n="4" goal="Display current sprint capacity usage">
|
|
78
|
-
<action>Calculate: {{assigned_count}} = length of {{target_sprint.assigned_items}}</action>
|
|
79
|
-
<action>Calculate: {{remaining_capacity}} = {{target_sprint.capacity}} - {{assigned_count}}</action>
|
|
80
|
-
<output>
|
|
81
|
-
## Sprint Capacity: {{target_sprint.sprint_name}}
|
|
82
|
-
|
|
83
|
-
- **Capacity:** {{target_sprint.capacity}} items
|
|
84
|
-
- **Assigned:** {{assigned_count}} items
|
|
85
|
-
- **Remaining:** {{remaining_capacity}} slots
|
|
86
|
-
|
|
87
|
-
{{#if remaining_capacity <= 0}}
|
|
88
|
-
⚠️ This sprint is **at or over capacity**. Adding items will exceed the limit.
|
|
89
|
-
{{/if}}
|
|
90
|
-
</output>
|
|
91
|
-
</step>
|
|
92
|
-
|
|
93
|
-
<step n="5" goal="Select candidate items for this sprint">
|
|
94
|
-
<ask>Which backlog items do you want to consider for this sprint? Enter item numbers (comma-separated), or "all" to evaluate the full backlog:</ask>
|
|
95
|
-
<check if="user enters 'all'">
|
|
96
|
-
<action>Set {{candidate_items}} = all items in {{backlog_items}} (the full filtered backlog list from step 2)</action>
|
|
97
|
-
</check>
|
|
98
|
-
<check if="user enters item numbers">
|
|
99
|
-
<action>Resolve the entered numbers against the backlog table from step 2 and set {{candidate_items}} = those specific items</action>
|
|
100
|
-
</check>
|
|
101
|
-
</step>
|
|
102
|
-
|
|
103
|
-
<step n="6" goal="Multi-criteria prioritization guidance">
|
|
104
|
-
<action>For each item in {{candidate_items}}, evaluate and score across criteria:
|
|
105
|
-
- **Business value:** High (H) / Medium (M) / Low (L) — impact on users or project goals
|
|
106
|
-
- **Dependency status:** Blocked (blocked by another item) / Blocking (blocks other items) / Independent
|
|
107
|
-
- **Severity** (bugs only): Critical / High / Medium / Low — N/A for stories
|
|
108
|
-
- **Effort estimation:** Small (S ≤ 1 day) / Medium (M 2–3 days) / Large (L 4+ days)
|
|
109
|
-
</action>
|
|
110
|
-
<action>Generate a ranked ordering recommendation, factoring in:
|
|
111
|
-
1. Blocking dependencies first (items that unlock others)
|
|
112
|
-
2. High business value + low/medium effort (quick wins)
|
|
113
|
-
3. Critical/High bugs ahead of Medium/Low bugs
|
|
114
|
-
4. Avoid blocked items unless capacity allows waiting
|
|
115
|
-
</action>
|
|
116
|
-
<output>
|
|
117
|
-
## 🎯 Prioritization Analysis
|
|
118
|
-
|
|
119
|
-
| Rank | ID / File | Title | Type | Business Value | Dependencies | Severity | Effort | Rationale |
|
|
120
|
-
|---|---|---|---|---|---|---|---|---|
|
|
121
|
-
{{#each ranked_items}}
|
|
122
|
-
| {{rank}} | {{id}} | {{title}} | {{type}} | {{business_value}} | {{dependency_status}} | {{severity}} | {{effort}} | {{rationale}} |
|
|
123
|
-
{{/each}}
|
|
124
|
-
|
|
125
|
-
**Recommended selection** (up to {{remaining_capacity}} items to stay within capacity): {{recommended_selection}}
|
|
126
|
-
</output>
|
|
127
|
-
</step>
|
|
128
|
-
|
|
129
|
-
<step n="7" goal="User confirms or adjusts ranking">
|
|
130
|
-
<ask>Review the ranking above. Options:
|
|
131
|
-
- [c] Confirm recommended selection as-is
|
|
132
|
-
- [m] Modify selection (specify item numbers to include)
|
|
133
|
-
- [r] Re-rank items (provide new priority order)
|
|
134
|
-
- [x] Cancel without assigning
|
|
135
|
-
|
|
136
|
-
Choice:</ask>
|
|
137
|
-
<check if="user selects 'x'">
|
|
138
|
-
<output>❌ Assignment cancelled — no changes made.</output>
|
|
139
|
-
<action>Exit workflow</action>
|
|
140
|
-
</check>
|
|
141
|
-
<check if="user selects 'm'">
|
|
142
|
-
<ask>Enter item numbers to assign (comma-separated):</ask>
|
|
143
|
-
<action>Update {{confirmed_items}} with user selection</action>
|
|
144
|
-
</check>
|
|
145
|
-
<check if="user selects 'r'">
|
|
146
|
-
<ask>Enter item numbers in your preferred priority order (comma-separated). Only items you include will be assigned — items not listed will be excluded from this session and remain in the unassigned backlog:</ask>
|
|
147
|
-
<action>Set {{confirmed_items}} = only the items matching the user-provided numbers, in the order provided. Items from {{candidate_items}} NOT mentioned are excluded from assignment in this session (they remain available in the backlog for future sprints).</action>
|
|
148
|
-
</check>
|
|
149
|
-
<check if="user selects 'c'">
|
|
150
|
-
<action>Set {{confirmed_items}} = recommended selection</action>
|
|
151
|
-
</check>
|
|
152
|
-
<action>Store confirmed ranking in {{confirmed_ranking}} for auditability (included in workflow output)</action>
|
|
153
|
-
</step>
|
|
154
|
-
|
|
155
|
-
<step n="8" goal="Assign selected items to sprint with capacity enforcement">
|
|
156
|
-
<action>For each item in {{confirmed_items}}, in confirmed ranking order:</action>
|
|
157
|
-
<action>Re-calculate current assigned count (in case multiple items are being added)</action>
|
|
158
|
-
<check if="assigning this item would exceed capacity">
|
|
159
|
-
<output>⚠️ **Capacity Warning:** Adding "{{item.title}}" would bring assigned items to {{new_count}}/{{target_sprint.capacity}} — exceeding sprint capacity by {{overage}}.</output>
|
|
160
|
-
<ask>Options:
|
|
161
|
-
- [a] Add anyway (over-capacity acknowledged)
|
|
162
|
-
- [s] Skip this item
|
|
163
|
-
- [m] Modify sprint capacity first via `/modify-sprint`
|
|
164
|
-
|
|
165
|
-
Choice:</ask>
|
|
166
|
-
<check if="user selects 's'">
|
|
167
|
-
<action>Skip this item — do not add to sprint. Continue to next item in the {{confirmed_items}} loop.</action>
|
|
168
|
-
</check>
|
|
169
|
-
<check if="user selects 'm'">
|
|
170
|
-
<output>💡 Run `/modify-sprint` to increase capacity for {{target_sprint.sprint_name}}, then re-run `/add-to-sprint`.</output>
|
|
171
|
-
<action>Exit workflow</action>
|
|
172
|
-
</check>
|
|
173
|
-
</check>
|
|
174
|
-
<action>Add item identifier to {{target_sprint.assigned_items}} list in the sprint-plan-{{target_sprint.sprint_number}}.yaml artifact</action>
|
|
175
|
-
<action>Item identifier format: story key for user stories (e.g., `12-1-add-sprint-workflow`), file basename for bugs (e.g., `bug-login-crash`)</action>
|
|
176
|
-
</step>
|
|
177
|
-
|
|
178
|
-
<step n="9" goal="Persist changes and display confirmed ranking for auditability">
|
|
179
|
-
<action>Update `_bmad-output/implementation-artifacts/sprint-plan-{{target_sprint.sprint_number}}.yaml`:
|
|
180
|
-
- Update `assigned_items` list with all newly assigned item identifiers
|
|
181
|
-
- Update `last_modified` to current ISO timestamp
|
|
182
|
-
</action>
|
|
183
|
-
<action>**Do NOT modify sprint-status.yaml** — sprint membership is exclusively tracked in sprint-plan-{n}.yaml</action>
|
|
184
|
-
<output>
|
|
185
|
-
## ✅ Assignment Complete
|
|
186
|
-
|
|
187
|
-
**Sprint:** {{target_sprint.sprint_name}}
|
|
188
|
-
**Items assigned this session:** {{assigned_this_session}}
|
|
189
|
-
|
|
190
|
-
### Confirmed Ranking (Audit Record)
|
|
191
|
-
|
|
192
|
-
| Rank | ID | Title | Type | Business Value | Dependencies | Severity | Effort |
|
|
193
|
-
|---|---|---|---|---|---|---|---|
|
|
194
|
-
{{#each confirmed_ranking}}
|
|
195
|
-
| {{rank}} | {{id}} | {{title}} | {{type}} | {{business_value}} | {{dependency_status}} | {{severity}} | {{effort}} |
|
|
196
|
-
{{/each}}
|
|
197
|
-
|
|
198
|
-
**Updated Capacity:** {{new_assigned_count}}/{{target_sprint.capacity}} items used ({{new_remaining}} remaining)
|
|
199
|
-
|
|
200
|
-
**Next Steps:**
|
|
201
|
-
- Use `/modify-sprint` to adjust capacity or remove items
|
|
202
|
-
- Use `/sprint-status-view` to view the full sprint with all assigned items
|
|
203
|
-
</output>
|
|
204
|
-
</step>
|
|
205
|
-
|
|
206
|
-
</workflow>
|
|
4
|
+
See `lib/bmad-extension/skills/add-to-sprint/SKILL.md` for the current workflow.
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
<!-- DEPRECATED: This workflow references the old sprint-plan-{n}.yaml format.
|
|
2
|
+
It will be reworked in Story 17.4. Use /add-sprint to create sprints in the new format. -->
|
|
3
|
+
|
|
4
|
+
> **DEPRECATED:** This workflow references the old `sprint-plan-{n}.yaml` format. It will be reworked in Story 17.4. Use `/add-sprint` to create sprints in the new format.
|
|
5
|
+
|
|
1
6
|
# Modify Sprint Workflow
|
|
2
7
|
|
|
3
8
|
Guided workflow to modify an existing sprint — add/remove items, change capacity, update metadata.
|
|
@@ -1,193 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- This workflow has been superseded by lib/bmad-extension/skills/sprint-status-view/SKILL.md -->
|
|
2
|
+
<!-- Resolved via skill:sprint-status-view in module-help.csv -->
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> **Architecture mandate:** This workflow is a NEW extension at `lib/bmad-extension/workflows/sprint-status-view/`. It does NOT modify any files under `_bmad/bmm/workflows/`.
|
|
6
|
-
|
|
7
|
-
<workflow>
|
|
8
|
-
|
|
9
|
-
<step n="1" goal="Discover all sprint artifact files">
|
|
10
|
-
<action>Glob `_bmad-output/implementation-artifacts/sprint-plan-*.yaml` to discover all sprint artifact files</action>
|
|
11
|
-
<check if="no sprint files found">
|
|
12
|
-
<output>
|
|
13
|
-
ℹ️ **No Sprints Found**
|
|
14
|
-
|
|
15
|
-
No sprint plan files exist yet (`sprint-plan-*.yaml`).
|
|
16
|
-
|
|
17
|
-
**To get started:**
|
|
18
|
-
- Run `/add-sprint` to create your first sprint
|
|
19
|
-
- Run `/add-to-sprint` to assign backlog items to it
|
|
20
|
-
</output>
|
|
21
|
-
<action>Exit workflow</action>
|
|
22
|
-
</check>
|
|
23
|
-
<action>For each sprint file found, read the full YAML content and store as {{sprint_plans}} list</action>
|
|
24
|
-
<action>Sort {{sprint_plans}} by sprint_number ascending</action>
|
|
25
|
-
</step>
|
|
26
|
-
|
|
27
|
-
<step n="2" goal="Load sprint-status.yaml for user story execution statuses">
|
|
28
|
-
<action>Read `_bmad-output/implementation-artifacts/sprint-status.yaml`</action>
|
|
29
|
-
<check if="file not found">
|
|
30
|
-
<output>⚠️ `sprint-status.yaml` not found. User story execution statuses will not be available. Run `/sprint-planning` to initialize.</output>
|
|
31
|
-
<action>Set {{story_status_map}} = {} (empty — will show data integrity warnings per missing item)</action>
|
|
32
|
-
</check>
|
|
33
|
-
<check if="file found">
|
|
34
|
-
<action>Parse development_status section into {{story_status_map}} — key: story key, value: status</action>
|
|
35
|
-
<action>Exclude epic-* keys and *-retrospective keys from the map</action>
|
|
36
|
-
</check>
|
|
37
|
-
</step>
|
|
38
|
-
|
|
39
|
-
<step n="3" goal="Discover bug stories for type/severity data">
|
|
40
|
-
<action>Glob `_bmad-output/implementation-artifacts/bug-*.md` to discover all bug story files</action>
|
|
41
|
-
<check if="no bug files found">
|
|
42
|
-
<action>Set {{bug_metadata_map}} = {} (empty)</action>
|
|
43
|
-
</check>
|
|
44
|
-
<check if="bug files found">
|
|
45
|
-
<action>For each bug file, parse YAML frontmatter to extract: type, severity, title</action>
|
|
46
|
-
<action>Build {{bug_metadata_map}} — key: file basename (e.g., `bug-login-crash`), value: {severity, title}</action>
|
|
47
|
-
</check>
|
|
48
|
-
</step>
|
|
49
|
-
|
|
50
|
-
<step n="4" goal="Display sprint status for each sprint">
|
|
51
|
-
<action>For each sprint in {{sprint_plans}} (in order):</action>
|
|
52
|
-
<action>Calculate: {{assigned_count}} = length(sprint.assigned_items)</action>
|
|
53
|
-
<action>Calculate: {{remaining_capacity}} = sprint.capacity - {{assigned_count}}</action>
|
|
54
|
-
|
|
55
|
-
<action>For each item identifier in sprint.assigned_items, resolve item details:
|
|
56
|
-
|
|
57
|
-
**If item is a story (key matches regex `^\d+-\d+-.+`):**
|
|
58
|
-
- Look up status in {{story_status_map}}[item_key]
|
|
59
|
-
- If NOT found in {{story_status_map}}:
|
|
60
|
-
→ Record as DATA INTEGRITY WARNING: "Item {item_key} has no status entry in sprint-status.yaml — run /sprint-planning to initialize status tracking for this item."
|
|
61
|
-
→ Display item with marker: ⚠️ [status unknown]
|
|
62
|
-
- If found: display with current status label
|
|
63
|
-
|
|
64
|
-
**If item is a bug (key matches regex `^bug-.+`):**
|
|
65
|
-
- Look up in {{bug_metadata_map}}[item_key]
|
|
66
|
-
- If NOT found: display with title as item_key, severity as "unknown"
|
|
67
|
-
- If found: display with title and severity from frontmatter
|
|
68
|
-
- Bug execution status: use `status` from bug file frontmatter if present; otherwise "not-started"
|
|
69
|
-
|
|
70
|
-
**If item matches neither pattern:** display as type "Unknown" with raw identifier as title
|
|
71
|
-
</action>
|
|
72
|
-
|
|
73
|
-
<output>
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## 🏃 {{sprint.sprint_name}} (Sprint {{sprint.sprint_number}})
|
|
77
|
-
|
|
78
|
-
**Status:** {{sprint.status}} | **Capacity:** {{sprint.capacity}} items | **Assigned:** {{assigned_count}} | **Remaining:** {{remaining_capacity}}
|
|
79
|
-
{{#if sprint.start_context}}**Start:** {{sprint.start_context}}{{/if}} {{#if sprint.end_context}}| **End:** {{sprint.end_context}}{{/if}}
|
|
80
|
-
|
|
81
|
-
{{#if over_capacity}}
|
|
82
|
-
⚠️ **Over capacity by {{overage}} item(s)**
|
|
83
|
-
{{/if}}
|
|
84
|
-
|
|
85
|
-
### Assigned Items
|
|
86
|
-
|
|
87
|
-
| Item | Title | Type | Status / Severity |
|
|
88
|
-
|---|---|---|---|
|
|
89
|
-
{{#each resolved_items}}
|
|
90
|
-
{{#if is_story}}
|
|
91
|
-
| {{item_key}} | {{title}} | 📋 Story | {{status}} |
|
|
92
|
-
{{/if}}
|
|
93
|
-
{{#if is_bug}}
|
|
94
|
-
| {{item_key}} | {{title}} | 🐛 Bug | Severity: {{severity}} / {{bug_status}} |
|
|
95
|
-
{{/if}}
|
|
96
|
-
{{/each}}
|
|
97
|
-
|
|
98
|
-
{{#if data_integrity_warnings}}
|
|
99
|
-
**⚠️ Data Integrity Warnings:**
|
|
100
|
-
{{#each data_integrity_warnings}}
|
|
101
|
-
- {{this}}
|
|
102
|
-
{{/each}}
|
|
103
|
-
{{/if}}
|
|
104
|
-
|
|
105
|
-
{{#if assigned_items_empty}}
|
|
106
|
-
*(No items assigned to this sprint)*
|
|
107
|
-
{{/if}}
|
|
108
|
-
</output>
|
|
109
|
-
</step>
|
|
110
|
-
|
|
111
|
-
<step n="5" goal="Display unassigned backlog summary">
|
|
112
|
-
<action>Collect all item keys from {{story_status_map}} that are NOT in any sprint's assigned_items list — these are unassigned user stories</action>
|
|
113
|
-
<action>Collect all bug basenames from {{bug_metadata_map}} that are NOT in any sprint's assigned_items list — these are unassigned bugs</action>
|
|
114
|
-
<action>Count unassigned stories by status: {{unassigned_by_status}}</action>
|
|
115
|
-
<output>
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## 📦 Unassigned Backlog
|
|
119
|
-
|
|
120
|
-
### 📋 Unassigned Stories
|
|
121
|
-
|
|
122
|
-
| Status | Count |
|
|
123
|
-
|---|---|
|
|
124
|
-
| backlog | {{count_backlog}} |
|
|
125
|
-
| ready-for-dev | {{count_ready}} |
|
|
126
|
-
| in-progress | {{count_in_progress}} |
|
|
127
|
-
| review | {{count_review}} |
|
|
128
|
-
| done | {{count_done}} |
|
|
129
|
-
|
|
130
|
-
*Total unassigned stories: {{total_unassigned}}*
|
|
131
|
-
|
|
132
|
-
### 🐛 Unassigned Bugs
|
|
133
|
-
|
|
134
|
-
{{#if unassigned_bugs}}
|
|
135
|
-
| ID / File | Title | Severity |
|
|
136
|
-
|---|---|---|
|
|
137
|
-
{{#each unassigned_bugs}}
|
|
138
|
-
| {{id}} | {{title}} | {{severity}} |
|
|
139
|
-
{{/each}}
|
|
140
|
-
{{else}}
|
|
141
|
-
*(No unassigned bugs)*
|
|
142
|
-
{{/if}}
|
|
143
|
-
|
|
144
|
-
**Tip:** Use `/add-to-sprint` to assign unassigned items to a sprint.
|
|
145
|
-
</output>
|
|
146
|
-
</step>
|
|
147
|
-
|
|
148
|
-
<step n="6" goal="Offer next actions">
|
|
149
|
-
<ask>Options:
|
|
150
|
-
1. Show full unassigned backlog item list (IDs + titles + statuses)
|
|
151
|
-
2. Add items to a sprint — run `/add-to-sprint`
|
|
152
|
-
3. Modify a sprint — run `/modify-sprint`
|
|
153
|
-
4. Create a new sprint — run `/add-sprint`
|
|
154
|
-
5. Exit
|
|
155
|
-
|
|
156
|
-
Choice:</ask>
|
|
157
|
-
<check if="choice == 1">
|
|
158
|
-
<action>For each unassigned story key in {{story_status_map}} not assigned to any sprint, display: key, inferred title, status</action>
|
|
159
|
-
<action>For each unassigned bug in {{bug_metadata_map}} not assigned to any sprint, display: id, title, severity</action>
|
|
160
|
-
<output>
|
|
161
|
-
### Full Unassigned Backlog
|
|
162
|
-
|
|
163
|
-
**Stories:**
|
|
164
|
-
| Key | Title | Status |
|
|
165
|
-
|---|---|---|
|
|
166
|
-
{{#each unassigned_story_items}}
|
|
167
|
-
| {{key}} | {{title}} | {{status}} |
|
|
168
|
-
{{/each}}
|
|
169
|
-
|
|
170
|
-
**Bugs:**
|
|
171
|
-
| ID | Title | Severity |
|
|
172
|
-
|---|---|---|
|
|
173
|
-
{{#each unassigned_bugs}}
|
|
174
|
-
| {{id}} | {{title}} | {{severity}} |
|
|
175
|
-
{{/each}}
|
|
176
|
-
</output>
|
|
177
|
-
<goto step="6" />
|
|
178
|
-
</check>
|
|
179
|
-
<check if="choice == 2">
|
|
180
|
-
<output>▶️ Run `/add-to-sprint` to assign backlog items to a sprint.</output>
|
|
181
|
-
</check>
|
|
182
|
-
<check if="choice == 3">
|
|
183
|
-
<output>▶️ Run `/modify-sprint` to add/remove items or change sprint settings.</output>
|
|
184
|
-
</check>
|
|
185
|
-
<check if="choice == 4">
|
|
186
|
-
<output>▶️ Run `/add-sprint` to create a new sprint.</output>
|
|
187
|
-
</check>
|
|
188
|
-
<check if="choice == 5">
|
|
189
|
-
<action>Exit workflow</action>
|
|
190
|
-
</check>
|
|
191
|
-
</step>
|
|
192
|
-
|
|
193
|
-
</workflow>
|
|
4
|
+
See `lib/bmad-extension/skills/sprint-status-view/SKILL.md` for the current workflow.
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ma-agents",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "NPX tool to install skills for AI coding agents (Claude Code, Gemini, Copilot, Kilocode, Cline, Cursor)",
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "NPX tool to install skills for AI coding agents (Claude Code, Gemini, Copilot, Kilocode, Cline, Cursor, Roo Code)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"ma-agents": "bin/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node bin/cli.js",
|
|
11
|
-
"test": "node test/yes-flag.test.js && node test/skill-authoring.test.js && node test/skill-validation.test.js && node test/skill-mandatory.test.js && node test/skill-customize-agent.test.js && node test/create-agent.test.js && node test/generate-project-context.test.js && node test/build-bmad-args.test.js && node test/bmad-version-bump.test.js && node test/extension-module-restructure.test.js && node test/convert-agents-to-skills.test.js && node test/migration.test.js && node test/migration-validation.test.js && node test/story-15-5-workflow-skills.test.js && node test/repo-layout.test.js && node test/config-storage.test.js && node test/cross-repo-validation.test.js && node test/config-lost-on-update.test.js && node test/portable-paths.test.js && node test/cicd-remote-mode.test.js && node test/config-layout.test.js",
|
|
11
|
+
"test": "node test/yes-flag.test.js && node test/skill-authoring.test.js && node test/skill-validation.test.js && node test/skill-mandatory.test.js && node test/skill-customize-agent.test.js && node test/create-agent.test.js && node test/generate-project-context.test.js && node test/build-bmad-args.test.js && node test/bmad-version-bump.test.js && node test/extension-module-restructure.test.js && node test/convert-agents-to-skills.test.js && node test/migration.test.js && node test/migration-validation.test.js && node test/story-15-5-workflow-skills.test.js && node test/repo-layout.test.js && node test/config-storage.test.js && node test/cross-repo-validation.test.js && node test/config-lost-on-update.test.js && node test/portable-paths.test.js && node test/cicd-remote-mode.test.js && node test/config-layout.test.js && node test/roo-code-agent.test.js && node test/roo-code-injection.test.js",
|
|
12
12
|
"build:bmad-cache": "node scripts/build-bmad-cache.js"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"kilocode",
|
|
22
22
|
"cline",
|
|
23
23
|
"cursor",
|
|
24
|
+
"roo-code",
|
|
24
25
|
"npx"
|
|
25
26
|
],
|
|
26
27
|
"author": "",
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Tests for Story 18.1: Register Roo Code Agent in Registry
|
|
4
|
+
*
|
|
5
|
+
* Validates that the roo-code agent entry conforms to the required schema
|
|
6
|
+
* and resolves correctly through the existing config-driven registry pattern.
|
|
7
|
+
*/
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const assert = require('assert');
|
|
11
|
+
|
|
12
|
+
let passed = 0;
|
|
13
|
+
let failed = 0;
|
|
14
|
+
const errors = [];
|
|
15
|
+
|
|
16
|
+
function test(name, fn) {
|
|
17
|
+
try {
|
|
18
|
+
fn();
|
|
19
|
+
console.log(` \u2713 ${name}`);
|
|
20
|
+
passed++;
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error(` \u2717 ${name}: ${err.message}`);
|
|
23
|
+
failed++;
|
|
24
|
+
errors.push({ name, error: err.message });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { getAllAgents, getAgent, getAgentsByCategory } = require('../lib/agents');
|
|
29
|
+
const allAgents = getAllAgents();
|
|
30
|
+
const rooCode = getAgent('roo-code');
|
|
31
|
+
|
|
32
|
+
// --- Schema validation ---
|
|
33
|
+
|
|
34
|
+
console.log('\nRoo Code agent schema validation');
|
|
35
|
+
|
|
36
|
+
test('roo-code agent exists in registry', () => {
|
|
37
|
+
assert.ok(rooCode, 'roo-code agent should exist in the registry');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('id is "roo-code"', () => {
|
|
41
|
+
assert.strictEqual(rooCode.id, 'roo-code');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('name is "Roo Code"', () => {
|
|
45
|
+
assert.strictEqual(rooCode.name, 'Roo Code');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('category is "ide"', () => {
|
|
49
|
+
assert.strictEqual(rooCode.category, 'ide');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('getProjectPath is a function', () => {
|
|
53
|
+
assert.strictEqual(typeof rooCode.getProjectPath, 'function',
|
|
54
|
+
'getProjectPath should be a function');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('getGlobalPath is a function', () => {
|
|
58
|
+
assert.strictEqual(typeof rooCode.getGlobalPath, 'function',
|
|
59
|
+
'getGlobalPath should be a function');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('getProjectPath returns path ending in .roo/skills', () => {
|
|
63
|
+
const projectPath = rooCode.getProjectPath();
|
|
64
|
+
assert.ok(
|
|
65
|
+
projectPath.endsWith('.roo/skills') || projectPath.endsWith('.roo\\skills'),
|
|
66
|
+
`Expected path ending in .roo/skills, got: ${projectPath}`
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('getGlobalPath returns a non-empty string', () => {
|
|
71
|
+
const globalPath = rooCode.getGlobalPath();
|
|
72
|
+
assert.strictEqual(typeof globalPath, 'string');
|
|
73
|
+
assert.ok(globalPath.length > 0, 'getGlobalPath should return a non-empty string');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('getGlobalPath contains roo-cline (VS Code extension storage convention)', () => {
|
|
77
|
+
const globalPath = rooCode.getGlobalPath();
|
|
78
|
+
assert.ok(
|
|
79
|
+
globalPath.includes('roo-cline'),
|
|
80
|
+
`Expected global path to contain 'roo-cline', got: ${globalPath}`
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('fileExtension is ".md"', () => {
|
|
85
|
+
assert.strictEqual(rooCode.fileExtension, '.md');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('description is a non-empty string', () => {
|
|
89
|
+
assert.strictEqual(typeof rooCode.description, 'string',
|
|
90
|
+
'description should be a string');
|
|
91
|
+
assert.ok(rooCode.description.length > 0, 'description should not be empty');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('description mentions Cline fork lineage', () => {
|
|
95
|
+
assert.ok(rooCode.description.includes('Cline'),
|
|
96
|
+
`description should mention Cline fork lineage, got: ${rooCode.description}`);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('template is "generic"', () => {
|
|
100
|
+
assert.strictEqual(rooCode.template, 'generic');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('skillsDir is ".roo/skills"', () => {
|
|
104
|
+
assert.strictEqual(rooCode.skillsDir, '.roo/skills');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('instructionFiles is a non-empty array', () => {
|
|
108
|
+
assert.ok(Array.isArray(rooCode.instructionFiles),
|
|
109
|
+
'instructionFiles should be an array');
|
|
110
|
+
assert.ok(rooCode.instructionFiles.length > 0,
|
|
111
|
+
'instructionFiles should not be empty');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('instructionFiles targets .roo/rules/ directory', () => {
|
|
115
|
+
const hasRooRules = rooCode.instructionFiles.some(f =>
|
|
116
|
+
f.includes('.roo/rules/') || f.includes('.roo\\rules\\')
|
|
117
|
+
);
|
|
118
|
+
assert.ok(hasRooRules,
|
|
119
|
+
`instructionFiles should target .roo/rules/ directory, got: ${rooCode.instructionFiles}`);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('injectionStrategy is an object', () => {
|
|
123
|
+
assert.ok(rooCode.injectionStrategy && typeof rooCode.injectionStrategy === 'object',
|
|
124
|
+
'injectionStrategy should be an object');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('injectionStrategy.position is "top"', () => {
|
|
128
|
+
assert.strictEqual(rooCode.injectionStrategy.position, 'top');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// --- Registry resolution ---
|
|
132
|
+
|
|
133
|
+
console.log('\nRoo Code agent resolution');
|
|
134
|
+
|
|
135
|
+
test('getAgent("roo-code") returns the agent', () => {
|
|
136
|
+
const resolved = getAgent('roo-code');
|
|
137
|
+
assert.ok(resolved, 'getAgent("roo-code") should return an agent object');
|
|
138
|
+
assert.strictEqual(resolved.id, 'roo-code');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('roo-code appears in getAllAgents()', () => {
|
|
142
|
+
const ids = allAgents.map(a => a.id);
|
|
143
|
+
assert.ok(ids.includes('roo-code'), 'roo-code should appear in getAllAgents()');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('roo-code is in the ide category', () => {
|
|
147
|
+
const ideAgents = getAgentsByCategory('ide');
|
|
148
|
+
const ids = ideAgents.map(a => a.id);
|
|
149
|
+
assert.ok(ids.includes('roo-code'), 'roo-code should be in ide category');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('roo-code is distinct from cline', () => {
|
|
153
|
+
const cline = getAgent('cline');
|
|
154
|
+
assert.ok(cline, 'cline agent should still exist');
|
|
155
|
+
assert.notStrictEqual(cline.id, rooCode.id, 'roo-code and cline should be different agents');
|
|
156
|
+
assert.notStrictEqual(cline.skillsDir, rooCode.skillsDir,
|
|
157
|
+
'roo-code and cline should use different skills directories');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Print summary
|
|
161
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
162
|
+
if (errors.length > 0) {
|
|
163
|
+
console.log('\nFailed tests:');
|
|
164
|
+
errors.forEach(e => console.log(` - ${e.name}: ${e.error}`));
|
|
165
|
+
}
|
|
166
|
+
if (failed > 0) process.exit(1);
|