ma-agents 3.2.0 → 3.4.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 +21 -2
- package/bin/cli.js +55 -0
- package/lib/agents.js +46 -0
- package/lib/bmad-cache/cache-manifest.json +1 -1
- package/lib/bmad-customizations/bmm-demerzel.customize.yaml +36 -0
- package/lib/bmad-customizations/demerzel.md +32 -0
- package/lib/bmad-extension/module-help.csv +13 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/SKILL.md +59 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/generate-backlog/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-advise/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-advise/SKILL.md +76 -0
- package/lib/bmad-extension/skills/ml-advise/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-advise/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-analysis/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-analysis/SKILL.md +60 -0
- package/lib/bmad-extension/skills/ml-analysis/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-analysis/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-architecture/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-architecture/SKILL.md +55 -0
- package/lib/bmad-extension/skills/ml-architecture/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-architecture/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-detailed-design/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-detailed-design/SKILL.md +67 -0
- package/lib/bmad-extension/skills/ml-detailed-design/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-detailed-design/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-eda/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-eda/SKILL.md +56 -0
- package/lib/bmad-extension/skills/ml-eda/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/baseline_classifier.py +522 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/class_weights_calculator.py +295 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/clustering_explorer.py +383 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/eda_analyzer.py +654 -0
- package/lib/bmad-extension/skills/ml-eda/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-experiment/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-experiment/SKILL.md +74 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/advanced_trainer_configs.py +430 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/quick_trainer_setup.py +233 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_datamodule.py +219 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_gnn_module.py +341 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_lightning_module.py +158 -0
- package/lib/bmad-extension/skills/ml-experiment/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-experiment/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-hparam/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-hparam/SKILL.md +81 -0
- package/lib/bmad-extension/skills/ml-hparam/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-hparam/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-ideation/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-ideation/SKILL.md +50 -0
- package/lib/bmad-extension/skills/ml-ideation/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-ideation/scripts/validate_ml_prd.py +287 -0
- package/lib/bmad-extension/skills/ml-ideation/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-infra/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-infra/SKILL.md +58 -0
- package/lib/bmad-extension/skills/ml-infra/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-infra/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-retrospective/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-retrospective/SKILL.md +63 -0
- package/lib/bmad-extension/skills/ml-retrospective/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-retrospective/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-revision/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-revision/SKILL.md +82 -0
- package/lib/bmad-extension/skills/ml-revision/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-revision/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-techspec/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-techspec/SKILL.md +80 -0
- package/lib/bmad-extension/skills/ml-techspec/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-techspec/skill.json +7 -0
- package/lib/bmad.js +85 -8
- package/lib/skill-authoring.js +1 -1
- package/package.json +5 -4
- package/test/agent-injection-strategy.test.js +4 -4
- package/test/bmad-version-bump.test.js +34 -34
- package/test/build-bmad-args.test.js +13 -6
- package/test/convert-agents-to-skills.test.js +11 -1
- package/test/extension-module-restructure.test.js +31 -7
- package/test/migration-validation.test.js +14 -11
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# verify-docker-hardening.sh
|
|
4
|
+
# Comprehensive Docker security verification script
|
|
5
|
+
# Checks Dockerfile, docker-compose.yml, and running containers
|
|
6
|
+
# against CIS, OWASP, and NIST standards
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
# Colors for output
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
BLUE='\033[0;34m'
|
|
16
|
+
NC='\033[0m' # No Color
|
|
17
|
+
|
|
18
|
+
# Configuration
|
|
19
|
+
IMAGE_NAME="${1:-contacts-app}"
|
|
20
|
+
CONTAINER_NAME="${2:-contacts-app}"
|
|
21
|
+
EXIT_CODE=0
|
|
22
|
+
|
|
23
|
+
# Counters
|
|
24
|
+
TOTAL_CHECKS=0
|
|
25
|
+
PASSED_CHECKS=0
|
|
26
|
+
FAILED_CHECKS=0
|
|
27
|
+
WARNING_CHECKS=0
|
|
28
|
+
|
|
29
|
+
# Helper functions
|
|
30
|
+
print_header() {
|
|
31
|
+
echo ""
|
|
32
|
+
echo -e "${BLUE}========================================${NC}"
|
|
33
|
+
echo -e "${BLUE}$1${NC}"
|
|
34
|
+
echo -e "${BLUE}========================================${NC}"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
print_check() {
|
|
38
|
+
TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
|
|
39
|
+
echo -ne " [$TOTAL_CHECKS] $1... "
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pass() {
|
|
43
|
+
PASSED_CHECKS=$((PASSED_CHECKS + 1))
|
|
44
|
+
echo -e "${GREEN}✅ PASS${NC}"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fail() {
|
|
48
|
+
FAILED_CHECKS=$((FAILED_CHECKS + 1))
|
|
49
|
+
EXIT_CODE=2
|
|
50
|
+
echo -e "${RED}❌ FAIL${NC}"
|
|
51
|
+
[ -n "$1" ] && echo -e " ${RED}→ $1${NC}"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
warn() {
|
|
55
|
+
WARNING_CHECKS=$((WARNING_CHECKS + 1))
|
|
56
|
+
echo -e "${YELLOW}⚠️ WARN${NC}"
|
|
57
|
+
[ -n "$1" ] && echo -e " ${YELLOW}→ $1${NC}"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
critical() {
|
|
61
|
+
FAILED_CHECKS=$((FAILED_CHECKS + 1))
|
|
62
|
+
EXIT_CODE=1
|
|
63
|
+
echo -e "${RED}🚨 CRITICAL${NC}"
|
|
64
|
+
[ -n "$1" ] && echo -e " ${RED}→ $1${NC}"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Start verification
|
|
68
|
+
echo -e "${BLUE}🔍 Docker Security Verification${NC}"
|
|
69
|
+
echo -e "${BLUE}================================${NC}"
|
|
70
|
+
echo "Image: $IMAGE_NAME"
|
|
71
|
+
echo "Container: $CONTAINER_NAME"
|
|
72
|
+
|
|
73
|
+
# ============================================================================
|
|
74
|
+
# 1. Dockerfile Verification
|
|
75
|
+
# ============================================================================
|
|
76
|
+
print_header "1. Dockerfile Security"
|
|
77
|
+
|
|
78
|
+
if [ ! -f "Dockerfile" ]; then
|
|
79
|
+
print_check "Dockerfile exists"
|
|
80
|
+
critical "Dockerfile not found in current directory"
|
|
81
|
+
EXIT_CODE=5
|
|
82
|
+
exit $EXIT_CODE
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Check for specific version tags
|
|
86
|
+
print_check "Specific version tags (no :latest)"
|
|
87
|
+
if grep -qE "^FROM.*:(latest|alpine)$" Dockerfile; then
|
|
88
|
+
fail "Using :latest or unversioned :alpine tag"
|
|
89
|
+
else
|
|
90
|
+
pass
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Check for non-root user
|
|
94
|
+
print_check "Non-root user configured"
|
|
95
|
+
if grep -qE "^USER (root|[0-9]+)" Dockerfile; then
|
|
96
|
+
if grep -qE "^USER root" Dockerfile; then
|
|
97
|
+
fail "Running as root user"
|
|
98
|
+
else
|
|
99
|
+
pass
|
|
100
|
+
fi
|
|
101
|
+
elif grep -qE "^USER [a-zA-Z]" Dockerfile; then
|
|
102
|
+
pass
|
|
103
|
+
else
|
|
104
|
+
fail "No USER directive found"
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Check for HEALTHCHECK
|
|
108
|
+
print_check "HEALTHCHECK instruction"
|
|
109
|
+
if grep -q "^HEALTHCHECK" Dockerfile; then
|
|
110
|
+
pass
|
|
111
|
+
else
|
|
112
|
+
warn "Missing HEALTHCHECK instruction"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Check for hardcoded secrets
|
|
116
|
+
print_check "No hardcoded secrets in ENV/ARG"
|
|
117
|
+
if grep -iE "^(ENV|ARG).*(SECRET|PASSWORD|KEY|TOKEN|CLIENT_ID)=" Dockerfile | grep -v "REACT_APP_API_BASE_URL" > /dev/null; then
|
|
118
|
+
fail "Potential hardcoded secrets found"
|
|
119
|
+
else
|
|
120
|
+
pass
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Check for multi-stage build
|
|
124
|
+
print_check "Multi-stage build pattern"
|
|
125
|
+
if [ $(grep -c "^FROM" Dockerfile) -ge 2 ]; then
|
|
126
|
+
pass
|
|
127
|
+
else
|
|
128
|
+
warn "Not using multi-stage build"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# Check for Alpine base images
|
|
132
|
+
print_check "Minimal Alpine base images"
|
|
133
|
+
if grep -qE "^FROM.*alpine" Dockerfile; then
|
|
134
|
+
pass
|
|
135
|
+
else
|
|
136
|
+
warn "Not using Alpine base images"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# ============================================================================
|
|
140
|
+
# 2. docker-compose.yml Verification
|
|
141
|
+
# ============================================================================
|
|
142
|
+
print_header "2. docker-compose.yml Security"
|
|
143
|
+
|
|
144
|
+
if [ ! -f "docker-compose.yml" ]; then
|
|
145
|
+
print_check "docker-compose.yml exists"
|
|
146
|
+
warn "docker-compose.yml not found (optional)"
|
|
147
|
+
else
|
|
148
|
+
# Check for read-only filesystem
|
|
149
|
+
print_check "Read-only root filesystem"
|
|
150
|
+
if grep -q "read_only: true" docker-compose.yml; then
|
|
151
|
+
pass
|
|
152
|
+
else
|
|
153
|
+
fail "Missing read_only: true"
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# Check for no-new-privileges
|
|
157
|
+
print_check "No new privileges"
|
|
158
|
+
if grep -q "no-new-privileges:true" docker-compose.yml; then
|
|
159
|
+
pass
|
|
160
|
+
else
|
|
161
|
+
fail "Missing security_opt: no-new-privileges:true"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# Check for capability dropping
|
|
165
|
+
print_check "Capabilities dropped"
|
|
166
|
+
if grep -q "cap_drop:" docker-compose.yml; then
|
|
167
|
+
pass
|
|
168
|
+
else
|
|
169
|
+
fail "Missing cap_drop configuration"
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Check for tmpfs mounts
|
|
173
|
+
print_check "Tmpfs mounts for writable dirs"
|
|
174
|
+
if grep -q "tmpfs:" docker-compose.yml; then
|
|
175
|
+
pass
|
|
176
|
+
else
|
|
177
|
+
fail "Missing tmpfs mounts"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# Check for resource limits
|
|
181
|
+
print_check "Memory limits configured"
|
|
182
|
+
if grep -q "memory:" docker-compose.yml; then
|
|
183
|
+
pass
|
|
184
|
+
else
|
|
185
|
+
warn "Missing memory limits"
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
print_check "CPU limits configured"
|
|
189
|
+
if grep -q "cpus:" docker-compose.yml; then
|
|
190
|
+
pass
|
|
191
|
+
else
|
|
192
|
+
warn "Missing CPU limits"
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Check for health check
|
|
196
|
+
print_check "Healthcheck configured"
|
|
197
|
+
if grep -q "healthcheck:" docker-compose.yml; then
|
|
198
|
+
pass
|
|
199
|
+
else
|
|
200
|
+
warn "Missing healthcheck configuration"
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# Check for privileged mode
|
|
204
|
+
print_check "Not running in privileged mode"
|
|
205
|
+
if grep -q "privileged: true" docker-compose.yml; then
|
|
206
|
+
critical "Running in privileged mode"
|
|
207
|
+
else
|
|
208
|
+
pass
|
|
209
|
+
fi
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
# ============================================================================
|
|
213
|
+
# 3. .dockerignore Verification
|
|
214
|
+
# ============================================================================
|
|
215
|
+
print_header "3. .dockerignore Configuration"
|
|
216
|
+
|
|
217
|
+
if [ ! -f ".dockerignore" ]; then
|
|
218
|
+
print_check ".dockerignore exists"
|
|
219
|
+
warn ".dockerignore not found"
|
|
220
|
+
else
|
|
221
|
+
print_check ".env excluded from Docker context"
|
|
222
|
+
if grep -qE "^\.env$" .dockerignore; then
|
|
223
|
+
pass
|
|
224
|
+
else
|
|
225
|
+
critical ".env not in .dockerignore - secret leakage risk!"
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
print_check "node_modules excluded"
|
|
229
|
+
if grep -q "node_modules" .dockerignore; then
|
|
230
|
+
pass
|
|
231
|
+
else
|
|
232
|
+
warn "node_modules not excluded"
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
print_check ".git excluded"
|
|
236
|
+
if grep -qE "^\.git" .dockerignore; then
|
|
237
|
+
pass
|
|
238
|
+
else
|
|
239
|
+
warn ".git not excluded"
|
|
240
|
+
fi
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
# ============================================================================
|
|
244
|
+
# 4. Image Security Scanning
|
|
245
|
+
# ============================================================================
|
|
246
|
+
print_header "4. Image Vulnerability Scanning"
|
|
247
|
+
|
|
248
|
+
# Check if image exists
|
|
249
|
+
if ! docker images --format "{{.Repository}}" | grep -q "^${IMAGE_NAME}$"; then
|
|
250
|
+
print_check "Docker image exists"
|
|
251
|
+
warn "Image '$IMAGE_NAME' not found locally. Skipping image scans."
|
|
252
|
+
echo " Run 'docker build -t $IMAGE_NAME .' to build the image."
|
|
253
|
+
else
|
|
254
|
+
# Check if trivy is installed
|
|
255
|
+
if ! command -v trivy &> /dev/null; then
|
|
256
|
+
print_check "Trivy scanner installed"
|
|
257
|
+
warn "Trivy not installed. Skipping vulnerability scans."
|
|
258
|
+
echo " Install: brew install aquasecurity/trivy/trivy (macOS)"
|
|
259
|
+
echo " : apt-get install trivy (Linux)"
|
|
260
|
+
else
|
|
261
|
+
# Scan for CRITICAL vulnerabilities
|
|
262
|
+
print_check "No CRITICAL vulnerabilities"
|
|
263
|
+
if trivy image --quiet --severity CRITICAL --exit-code 1 "$IMAGE_NAME" > /dev/null 2>&1; then
|
|
264
|
+
pass
|
|
265
|
+
else
|
|
266
|
+
critical "CRITICAL vulnerabilities found. Run: trivy image --severity CRITICAL $IMAGE_NAME"
|
|
267
|
+
fi
|
|
268
|
+
|
|
269
|
+
# Scan for HIGH vulnerabilities
|
|
270
|
+
print_check "No HIGH vulnerabilities"
|
|
271
|
+
if trivy image --quiet --severity HIGH --exit-code 1 "$IMAGE_NAME" > /dev/null 2>&1; then
|
|
272
|
+
pass
|
|
273
|
+
else
|
|
274
|
+
fail "HIGH vulnerabilities found. Run: trivy image --severity HIGH $IMAGE_NAME"
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Scan for leaked secrets
|
|
278
|
+
print_check "No leaked secrets in image"
|
|
279
|
+
if trivy image --quiet --scanners secret --exit-code 1 "$IMAGE_NAME" > /dev/null 2>&1; then
|
|
280
|
+
pass
|
|
281
|
+
else
|
|
282
|
+
critical "Secrets detected in image! Run: trivy image --scanners secret $IMAGE_NAME"
|
|
283
|
+
fi
|
|
284
|
+
fi
|
|
285
|
+
|
|
286
|
+
# Check image size
|
|
287
|
+
print_check "Optimized image size (< 100MB)"
|
|
288
|
+
IMAGE_SIZE=$(docker images --format "{{.Size}}" "$IMAGE_NAME" | head -1 | sed 's/MB//' | sed 's/GB/*1024/' | bc 2>/dev/null || echo "0")
|
|
289
|
+
if [ -n "$IMAGE_SIZE" ] && [ "$IMAGE_SIZE" != "0" ]; then
|
|
290
|
+
if (( $(echo "$IMAGE_SIZE < 100" | bc -l) )); then
|
|
291
|
+
pass
|
|
292
|
+
else
|
|
293
|
+
warn "Image size is ${IMAGE_SIZE}MB (recommended < 100MB)"
|
|
294
|
+
fi
|
|
295
|
+
else
|
|
296
|
+
warn "Could not determine image size"
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
# Check for .env in image
|
|
300
|
+
print_check ".env file not baked into image"
|
|
301
|
+
if docker run --rm "$IMAGE_NAME" sh -c "ls -la / 2>/dev/null | grep -q .env"; then
|
|
302
|
+
critical ".env file found in image! Secrets leaked!"
|
|
303
|
+
else
|
|
304
|
+
pass
|
|
305
|
+
fi
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
# ============================================================================
|
|
309
|
+
# 5. Runtime Security (if container is running)
|
|
310
|
+
# ============================================================================
|
|
311
|
+
print_header "5. Runtime Security Verification"
|
|
312
|
+
|
|
313
|
+
if ! docker ps --filter "name=$CONTAINER_NAME" --format "{{.Names}}" | grep -q "^$CONTAINER_NAME$"; then
|
|
314
|
+
echo -e "${YELLOW} Container '$CONTAINER_NAME' is not running.${NC}"
|
|
315
|
+
echo -e "${YELLOW} Run 'docker-compose up -d' to enable runtime checks.${NC}"
|
|
316
|
+
else
|
|
317
|
+
# Check container runs as non-root
|
|
318
|
+
print_check "Container runs as non-root"
|
|
319
|
+
CONTAINER_USER=$(docker exec "$CONTAINER_NAME" whoami 2>/dev/null || echo "root")
|
|
320
|
+
if [ "$CONTAINER_USER" != "root" ]; then
|
|
321
|
+
pass
|
|
322
|
+
else
|
|
323
|
+
critical "Container running as root user!"
|
|
324
|
+
fi
|
|
325
|
+
|
|
326
|
+
# Check user ID is not 0
|
|
327
|
+
print_check "User ID is not 0 (root)"
|
|
328
|
+
USER_ID=$(docker exec "$CONTAINER_NAME" id -u 2>/dev/null || echo "0")
|
|
329
|
+
if [ "$USER_ID" != "0" ]; then
|
|
330
|
+
pass
|
|
331
|
+
else
|
|
332
|
+
critical "Container running with UID 0 (root)!"
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
# Check read-only filesystem
|
|
336
|
+
print_check "Root filesystem is read-only"
|
|
337
|
+
if docker exec "$CONTAINER_NAME" sh -c "touch /test 2>/dev/null"; then
|
|
338
|
+
fail "Root filesystem is writable"
|
|
339
|
+
docker exec "$CONTAINER_NAME" sh -c "rm /test 2>/dev/null" || true
|
|
340
|
+
else
|
|
341
|
+
pass
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
# Check tmpfs is writable
|
|
345
|
+
print_check "Tmpfs mount is writable"
|
|
346
|
+
if docker exec "$CONTAINER_NAME" sh -c "touch /tmp/test 2>/dev/null && rm /tmp/test 2>/dev/null"; then
|
|
347
|
+
pass
|
|
348
|
+
else
|
|
349
|
+
warn "Tmpfs mount /tmp is not writable"
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
# Check health status
|
|
353
|
+
print_check "Container is healthy"
|
|
354
|
+
HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$CONTAINER_NAME" 2>/dev/null || echo "none")
|
|
355
|
+
if [ "$HEALTH_STATUS" = "healthy" ]; then
|
|
356
|
+
pass
|
|
357
|
+
elif [ "$HEALTH_STATUS" = "none" ]; then
|
|
358
|
+
warn "No health check configured"
|
|
359
|
+
else
|
|
360
|
+
fail "Container health status: $HEALTH_STATUS"
|
|
361
|
+
fi
|
|
362
|
+
|
|
363
|
+
# Check capabilities
|
|
364
|
+
print_check "Capabilities dropped"
|
|
365
|
+
CAPS_DROPPED=$(docker inspect --format='{{.HostConfig.CapDrop}}' "$CONTAINER_NAME" 2>/dev/null || echo "[]")
|
|
366
|
+
if echo "$CAPS_DROPPED" | grep -q "ALL"; then
|
|
367
|
+
pass
|
|
368
|
+
else
|
|
369
|
+
warn "Not all capabilities dropped"
|
|
370
|
+
fi
|
|
371
|
+
|
|
372
|
+
# Check memory limit
|
|
373
|
+
print_check "Memory limit enforced"
|
|
374
|
+
MEMORY_LIMIT=$(docker inspect --format='{{.HostConfig.Memory}}' "$CONTAINER_NAME" 2>/dev/null || echo "0")
|
|
375
|
+
if [ "$MEMORY_LIMIT" != "0" ]; then
|
|
376
|
+
pass
|
|
377
|
+
else
|
|
378
|
+
warn "No memory limit set"
|
|
379
|
+
fi
|
|
380
|
+
fi
|
|
381
|
+
|
|
382
|
+
# ============================================================================
|
|
383
|
+
# 6. Git Secret Protection
|
|
384
|
+
# ============================================================================
|
|
385
|
+
print_header "6. Git Secret Protection"
|
|
386
|
+
|
|
387
|
+
if [ -d ".git" ]; then
|
|
388
|
+
# Check .env in .gitignore
|
|
389
|
+
print_check ".env in .gitignore"
|
|
390
|
+
if [ -f ".gitignore" ] && grep -qE "^\.env$" .gitignore; then
|
|
391
|
+
pass
|
|
392
|
+
else
|
|
393
|
+
critical ".env not in .gitignore! Secrets may be committed!"
|
|
394
|
+
fi
|
|
395
|
+
|
|
396
|
+
# Check .env.example exists
|
|
397
|
+
print_check ".env.example exists (template)"
|
|
398
|
+
if [ -f ".env.example" ]; then
|
|
399
|
+
pass
|
|
400
|
+
else
|
|
401
|
+
warn ".env.example not found"
|
|
402
|
+
fi
|
|
403
|
+
|
|
404
|
+
# Check if .env is committed
|
|
405
|
+
print_check ".env not committed to git"
|
|
406
|
+
if git ls-files --error-unmatch .env > /dev/null 2>&1; then
|
|
407
|
+
critical ".env is tracked by git! Remove immediately!"
|
|
408
|
+
else
|
|
409
|
+
pass
|
|
410
|
+
fi
|
|
411
|
+
else
|
|
412
|
+
echo -e "${YELLOW} Not a git repository. Skipping git checks.${NC}"
|
|
413
|
+
fi
|
|
414
|
+
|
|
415
|
+
# ============================================================================
|
|
416
|
+
# Summary
|
|
417
|
+
# ============================================================================
|
|
418
|
+
print_header "Verification Summary"
|
|
419
|
+
|
|
420
|
+
echo ""
|
|
421
|
+
echo " Total checks: $TOTAL_CHECKS"
|
|
422
|
+
echo -e " ${GREEN}Passed: $PASSED_CHECKS${NC}"
|
|
423
|
+
echo -e " ${YELLOW}Warnings: $WARNING_CHECKS${NC}"
|
|
424
|
+
echo -e " ${RED}Failed: $FAILED_CHECKS${NC}"
|
|
425
|
+
echo ""
|
|
426
|
+
|
|
427
|
+
if [ $FAILED_CHECKS -eq 0 ]; then
|
|
428
|
+
echo -e "${GREEN}✅ All critical security checks passed!${NC}"
|
|
429
|
+
if [ $WARNING_CHECKS -gt 0 ]; then
|
|
430
|
+
echo -e "${YELLOW}⚠️ $WARNING_CHECKS warning(s) - consider addressing these.${NC}"
|
|
431
|
+
fi
|
|
432
|
+
else
|
|
433
|
+
echo -e "${RED}❌ $FAILED_CHECKS security check(s) failed!${NC}"
|
|
434
|
+
echo -e "${RED} Please fix the issues above before deploying.${NC}"
|
|
435
|
+
fi
|
|
436
|
+
|
|
437
|
+
echo ""
|
|
438
|
+
|
|
439
|
+
exit $EXIT_CODE
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ma-agents
|
|
2
2
|
|
|
3
|
-
A universal NPX tool to install AI coding agent skills. Write skills once, install them across Claude Code, Gemini, Copilot, Cline, Cursor, and
|
|
3
|
+
A universal NPX tool to install AI coding agent skills. Write skills once, install them across Claude Code, Gemini, Copilot, Cline, Cursor, Kilocode, and Roo Code.
|
|
4
4
|
|
|
5
5
|
## Installation & Usage
|
|
6
6
|
|
|
@@ -115,13 +115,15 @@ The file is version-controlled as part of `_bmad-output/` project knowledge. Com
|
|
|
115
115
|
| Cursor | `.cursor/skills/` | `generic` | `.cursor/cursor.md` |
|
|
116
116
|
| Kilocode | `.kilocode/skills/` | `generic` | `.kilocode/kilocode.md` |
|
|
117
117
|
| Cline | `.cline/skills/` | `cline` | `.cline/clinerules.md` |
|
|
118
|
+
| Roo Code | `.roo/skills/` | `generic` | `.roo/rules/00-ma-agents.md` |
|
|
118
119
|
| SRE Agent (Alex) | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/sre.md` |
|
|
119
120
|
| DevOps Agent (Amit) | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/devops.md` |
|
|
120
121
|
| Cyber Analyst (Yael) | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/cyber.md` |
|
|
121
122
|
| Joseph (MIL-STD-498) | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/mil498.md` |
|
|
123
|
+
| Demerzel (ML Scientist) | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/demerzel.md` |
|
|
122
124
|
| Antigravity | `_bmad/skills/` | `generic` | `_bmad/bmm/agents/antigravity.md` |
|
|
123
125
|
|
|
124
|
-
## Available Skills (
|
|
126
|
+
## Available Skills (46)
|
|
125
127
|
|
|
126
128
|
| Skill ID | Domain | Description |
|
|
127
129
|
| :--- | :--- | :--- |
|
|
@@ -158,6 +160,19 @@ The file is version-controlled as part of `_bmad-output/` project knowledge. Com
|
|
|
158
160
|
| `self-signed-cert` | Security | Automated Root CA and self-signed certificate generation |
|
|
159
161
|
| `docker-image-signing` | Security | Automated cryptographic signing for Docker images |
|
|
160
162
|
| `docker-hardening-verification` | Security | Audits images for least-privilege and OpenShift compatibility |
|
|
163
|
+
| **Machine Learning** | | |
|
|
164
|
+
| `ml-ideation` | Research | Frame ML research problem, define requirements, produce Research Thesis and PRD |
|
|
165
|
+
| `ml-eda` | Data Science | Exploratory Data Analysis, establish baselines, produce EDA report |
|
|
166
|
+
| `ml-architecture` | Design | Model architecture, stack, and experiment tracking strategy |
|
|
167
|
+
| `ml-detailed-design` | Tech Lead | Implementation task breakdown (INF-* and EXP-* namespaces) |
|
|
168
|
+
| `ml-techspec` | Contract | Lock experiment parameters and performance tiers before training |
|
|
169
|
+
| `ml-infra` | MLOps | Build ML infrastructure, manage dependencies, run smoke tests |
|
|
170
|
+
| `ml-experiment` | Developer | Execute training experiments against locked TechSpec, log metrics |
|
|
171
|
+
| `ml-analysis` | Evaluation | Evaluate experiment outcomes against TechSpec success tiers |
|
|
172
|
+
| `ml-hparam` | Tuning | Automated hyperparameter optimization (Optuna, W&B Sweeps, Ray Tune) |
|
|
173
|
+
| `ml-revision` | Iterative | Amend hypothesis and requirements based on experiment findings |
|
|
174
|
+
| `ml-advise` | Advisory | Search past experiments, surface findings and failure warnings |
|
|
175
|
+
| `ml-retrospective` | Meta | Capture session learnings and update project context |
|
|
161
176
|
| **Sprint Management** | | |
|
|
162
177
|
| `add-sprint` | Agile | Create sprint entities with capacity, ISO dates, and structured YAML schema |
|
|
163
178
|
| `generate-backlog` | Agile | Generate or refresh a flat prioritized backlog from epics and bug stories |
|
|
@@ -245,6 +260,10 @@ npx ma-agents install --yes # fully offline BMAD install — no network neede
|
|
|
245
260
|
- **Focus**: Technical standards compliance and military document generation.
|
|
246
261
|
- **Capabilities**: Document Data Descriptions (DIDs), requirements traceability, and complex specification writing.
|
|
247
262
|
- **Workflows**: SRS, SSS, and SSDD generation with strict structural validation.
|
|
263
|
+
5. **Demerzel (ML Scientist)**:
|
|
264
|
+
- **Focus**: Hypothesis-driven machine learning lifecycle with scientific rigor.
|
|
265
|
+
- **Capabilities**: EDA, architecture design, locked TechSpec contracts, experiment execution, failure-cost analysis.
|
|
266
|
+
- **Workflows**: 12-stage ML lifecycle from ideation through retrospective, with mandatory review gates.
|
|
248
267
|
|
|
249
268
|
#### Operational Workflows
|
|
250
269
|
The integration includes a suite of specialized playbooks:
|
package/bin/cli.js
CHANGED
|
@@ -13,6 +13,46 @@ const PKG = require('../package.json');
|
|
|
13
13
|
const NAME = PKG.name;
|
|
14
14
|
const VERSION = PKG.version;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Set up logging to tee all stdout/stderr output to a file.
|
|
18
|
+
* Returns a cleanup function to close the file descriptor.
|
|
19
|
+
*
|
|
20
|
+
* @param {string} logFilePath - Path to the log file
|
|
21
|
+
* @returns {Function} cleanup function
|
|
22
|
+
*/
|
|
23
|
+
function setupLogging(logFilePath) {
|
|
24
|
+
const logFd = fs.openSync(logFilePath, 'w');
|
|
25
|
+
const header = `[${new Date().toISOString()}] ${NAME} v${VERSION} — log started\n`;
|
|
26
|
+
fs.writeSync(logFd, header);
|
|
27
|
+
|
|
28
|
+
const origStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
29
|
+
const origStderrWrite = process.stderr.write.bind(process.stderr);
|
|
30
|
+
|
|
31
|
+
process.stdout.write = function (chunk, encoding, callback) {
|
|
32
|
+
const str = typeof chunk === 'string' ? chunk : chunk.toString();
|
|
33
|
+
try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
|
|
34
|
+
return origStdoutWrite(chunk, encoding, callback);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
process.stderr.write = function (chunk, encoding, callback) {
|
|
38
|
+
const str = typeof chunk === 'string' ? chunk : chunk.toString();
|
|
39
|
+
try { fs.writeSync(logFd, str); } catch { /* ignore write errors */ }
|
|
40
|
+
return origStderrWrite(chunk, encoding, callback);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Store log fd globally so bmad.js can use pipe mode
|
|
44
|
+
process.env.MA_AGENTS_LOG_ACTIVE = '1';
|
|
45
|
+
|
|
46
|
+
return function cleanup() {
|
|
47
|
+
process.stdout.write = origStdoutWrite;
|
|
48
|
+
process.stderr.write = origStderrWrite;
|
|
49
|
+
const footer = `\n[${new Date().toISOString()}] log ended\n`;
|
|
50
|
+
try { fs.writeSync(logFd, footer); } catch { /* ignore */ }
|
|
51
|
+
try { fs.closeSync(logFd); } catch { /* ignore */ }
|
|
52
|
+
delete process.env.MA_AGENTS_LOG_ACTIVE;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
16
56
|
function showHelp() {
|
|
17
57
|
console.log(`
|
|
18
58
|
${chalk.bold.cyan(NAME)} ${chalk.gray(`v${VERSION}`)}
|
|
@@ -40,6 +80,7 @@ ${chalk.bold('Install options:')}
|
|
|
40
80
|
${chalk.cyan('--force')} Skip upgrade prompts, always overwrite
|
|
41
81
|
${chalk.cyan('--yes')} Skip all prompts, use defaults (for CI/CD)
|
|
42
82
|
${chalk.cyan('--agent <name>')} Target a specific agent (skip agent selection)
|
|
83
|
+
${chalk.cyan('--log')} Log all console output to install_<datetime>.log
|
|
43
84
|
|
|
44
85
|
${chalk.bold('Examples:')}
|
|
45
86
|
npx ${NAME} install
|
|
@@ -1164,6 +1205,18 @@ async function interactiveMode() {
|
|
|
1164
1205
|
|
|
1165
1206
|
async function main() {
|
|
1166
1207
|
const args = process.argv.slice(2);
|
|
1208
|
+
|
|
1209
|
+
// Handle --log flag globally (before command routing)
|
|
1210
|
+
let cleanupLog = null;
|
|
1211
|
+
const logIdx = args.indexOf('--log');
|
|
1212
|
+
if (logIdx !== -1) {
|
|
1213
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').replace('Z', '');
|
|
1214
|
+
const logFile = `install_${ts}.log`;
|
|
1215
|
+
cleanupLog = setupLogging(logFile);
|
|
1216
|
+
console.log(chalk.gray(` Logging to ${logFile}`));
|
|
1217
|
+
args.splice(logIdx, 1);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1167
1220
|
const command = args[0];
|
|
1168
1221
|
|
|
1169
1222
|
switch (command) {
|
|
@@ -1223,6 +1276,8 @@ async function main() {
|
|
|
1223
1276
|
await interactiveMode();
|
|
1224
1277
|
break;
|
|
1225
1278
|
}
|
|
1279
|
+
|
|
1280
|
+
if (cleanupLog) cleanupLog();
|
|
1226
1281
|
}
|
|
1227
1282
|
|
|
1228
1283
|
if (require.main === module) {
|
package/lib/agents.js
CHANGED
|
@@ -135,6 +135,29 @@ const agents = [
|
|
|
135
135
|
instructionFiles: ['.cline/clinerules.md', '.clinerules'],
|
|
136
136
|
injectionStrategy: { position: 'top', skipPatterns: ['---'] }
|
|
137
137
|
},
|
|
138
|
+
{
|
|
139
|
+
id: 'roo-code',
|
|
140
|
+
name: 'Roo Code',
|
|
141
|
+
version: '1.0.0',
|
|
142
|
+
category: 'ide',
|
|
143
|
+
description: 'Roo Code AI Assistant (Enhanced Cline fork)',
|
|
144
|
+
skillsDir: '.roo/skills',
|
|
145
|
+
getProjectPath: () => path.join(process.cwd(), '.roo', 'skills'),
|
|
146
|
+
getGlobalPath: () => {
|
|
147
|
+
const platform = os.platform();
|
|
148
|
+
if (platform === 'win32') {
|
|
149
|
+
return path.join(os.homedir(), 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'rooveterinaryinc.roo-cline', 'skills');
|
|
150
|
+
} else if (platform === 'darwin') {
|
|
151
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'rooveterinaryinc.roo-cline', 'skills');
|
|
152
|
+
} else {
|
|
153
|
+
return path.join(os.homedir(), '.config', 'Code', 'User', 'globalStorage', 'rooveterinaryinc.roo-cline', 'skills');
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
fileExtension: '.md',
|
|
157
|
+
template: 'generic',
|
|
158
|
+
instructionFiles: ['.roo/rules/00-ma-agents.md'],
|
|
159
|
+
injectionStrategy: { position: 'top', skipPatterns: ['---'] }
|
|
160
|
+
},
|
|
138
161
|
{
|
|
139
162
|
id: 'cursor',
|
|
140
163
|
name: 'Cursor',
|
|
@@ -295,6 +318,29 @@ const agents = [
|
|
|
295
318
|
template: 'generic',
|
|
296
319
|
instructionFiles: ['_bmad/bmm/agents/mil498.md'],
|
|
297
320
|
injectionStrategy: { position: 'top', skipPatterns: ['---'] }
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
id: 'bmm-demerzel',
|
|
324
|
+
name: 'ML Scientist (Demerzel)',
|
|
325
|
+
version: '1.0.0',
|
|
326
|
+
category: 'bmad',
|
|
327
|
+
description: 'Machine Learning Lifecycle Agent (Demerzel)',
|
|
328
|
+
skillsDir: '_bmad/skills/demerzel',
|
|
329
|
+
getProjectPath: () => path.join(process.cwd(), '_bmad', 'skills', 'demerzel'),
|
|
330
|
+
getGlobalPath: () => {
|
|
331
|
+
const platform = os.platform();
|
|
332
|
+
if (platform === 'win32') {
|
|
333
|
+
return path.join(os.homedir(), 'AppData', 'Roaming', 'Demerzel', 'skills');
|
|
334
|
+
} else if (platform === 'darwin') {
|
|
335
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'Demerzel', 'skills');
|
|
336
|
+
} else {
|
|
337
|
+
return path.join(os.homedir(), '.config', 'demerzel', 'skills');
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
fileExtension: '.md',
|
|
341
|
+
template: 'generic',
|
|
342
|
+
instructionFiles: ['_bmad/bmm/agents/demerzel.md'],
|
|
343
|
+
injectionStrategy: { position: 'top', skipPatterns: ['---'] }
|
|
298
344
|
}
|
|
299
345
|
];
|
|
300
346
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
persona:
|
|
2
|
+
name: Demerzel
|
|
3
|
+
role: Machine Learning Scientist
|
|
4
|
+
alias: ML Scientist
|
|
5
|
+
description: Senior AI/ML Architect and Data Scientist specialized in falsifiable hypothesis validation and failure-cost analysis.
|
|
6
|
+
|
|
7
|
+
memories:
|
|
8
|
+
- "The scientific method: No modeling without EDA. No modeling without a locked TechSpec."
|
|
9
|
+
- "Dependency integrity: Always use uv for project reproducibility."
|
|
10
|
+
- "Failure Costs: A false negative for Class A costs the domain $50K."
|
|
11
|
+
|
|
12
|
+
critical_actions:
|
|
13
|
+
1: "Perform ML Ideation using /ml-ideation"
|
|
14
|
+
2: "Conduct EDA and publish Research Thesis using /ml-eda"
|
|
15
|
+
3: "Design ML Architecture using /ml-architecture"
|
|
16
|
+
4: "Lock experiment parameters in TechSpec using /ml-techspec"
|
|
17
|
+
5: "Build ML Infrastructure using /ml-infra"
|
|
18
|
+
6: "Execute training experiments using /ml-experiment"
|
|
19
|
+
7: "Analyze experiment results against TechSpec using /ml-analysis"
|
|
20
|
+
8: "Iterate hypothesis and documents using /ml-revision"
|
|
21
|
+
9: "Consult previous findings using /ml-advise"
|
|
22
|
+
10: "Capture session learnings with /ml-retrospective"
|
|
23
|
+
|
|
24
|
+
skills:
|
|
25
|
+
- ml-ideation
|
|
26
|
+
- ml-eda
|
|
27
|
+
- ml-architecture
|
|
28
|
+
- ml-detailed-design
|
|
29
|
+
- ml-techspec
|
|
30
|
+
- ml-infra
|
|
31
|
+
- ml-experiment
|
|
32
|
+
- ml-analysis
|
|
33
|
+
- ml-hparam
|
|
34
|
+
- ml-revision
|
|
35
|
+
- ml-advise
|
|
36
|
+
- ml-retrospective
|