@amsterdamdatalabs/enact-extensions 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +94 -20
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/install.d.ts +89 -0
  7. package/dist/install.d.ts.map +1 -1
  8. package/dist/install.js +219 -18
  9. package/dist/install.js.map +1 -1
  10. package/dist/validate/index.d.ts +21 -0
  11. package/dist/validate/index.d.ts.map +1 -1
  12. package/dist/validate/index.js +77 -0
  13. package/dist/validate/index.js.map +1 -1
  14. package/extensions/cmux/.agents/plugin.json +37 -0
  15. package/extensions/cmux/skills/cmux/SKILL.md +82 -0
  16. package/extensions/cmux/skills/cmux/agents/openai.yaml +4 -0
  17. package/extensions/cmux/skills/cmux/references/handles-and-identify.md +35 -0
  18. package/extensions/cmux/skills/cmux/references/panes-surfaces.md +37 -0
  19. package/extensions/cmux/skills/cmux/references/trigger-flash-and-health.md +23 -0
  20. package/extensions/cmux/skills/cmux/references/windows-workspaces.md +31 -0
  21. package/extensions/cmux/skills/cmux-vm-monitor/SKILL.md +122 -0
  22. package/extensions/cmux/skills/cmux-vm-monitor/agents/openai.yaml +4 -0
  23. package/extensions/cmux/skills/cmux-vm-monitor/references/cmux-commands.md +66 -0
  24. package/extensions/cmux/skills/cmux-vm-monitor/scripts/codex_vm_monitor.sh +45 -0
  25. package/extensions/cmux/skills/cmux-workspace/SKILL.md +93 -0
  26. package/extensions/dev-state/.agents/plugin.json +35 -0
  27. package/extensions/dev-state/skills/dev-state-plan-graduation/SKILL.md +194 -0
  28. package/extensions/dev-state/skills/dev-state-plan-graduation/agents/openai.yaml +4 -0
  29. package/extensions/dev-state/skills/dev-state-plan-graduation/references/reference.md +130 -0
  30. package/extensions/devops/.agents/plugin.json +36 -0
  31. package/extensions/devops/skills/azure-devops-cli/SKILL.md +431 -0
  32. package/extensions/devops/skills/azure-devops-cli/agents/openai.yaml +4 -0
  33. package/extensions/devops/skills/ci-pipeline-strategy/SKILL.md +217 -0
  34. package/extensions/devops/skills/ci-pipeline-strategy/agents/openai.yaml +4 -0
  35. package/{plugins/net-revenue-management/.codex-plugin → extensions/net-revenue-management/.agents}/plugin.json +10 -6
  36. package/extensions/plugin-dev/.agents/plugin.json +42 -0
  37. package/extensions/plugin-dev/.mcp.json +3 -0
  38. package/extensions/plugin-dev/agents/agent-creator.md +199 -0
  39. package/extensions/plugin-dev/agents/plugin-validator.md +91 -0
  40. package/extensions/plugin-dev/agents/skill-reviewer.md +212 -0
  41. package/extensions/plugin-dev/commands/_archive/create-marketplace.md +427 -0
  42. package/extensions/plugin-dev/commands/_archive/plugin-dev-guide.md +12 -0
  43. package/extensions/plugin-dev/commands/create-plugin.md +498 -0
  44. package/extensions/plugin-dev/commands/start.md +81 -0
  45. package/extensions/plugin-dev/hooks/hooks.json +3 -0
  46. package/extensions/plugin-dev/skills/agent-development/SKILL.md +641 -0
  47. package/extensions/plugin-dev/skills/agent-development/examples/agent-creation-prompt.md +250 -0
  48. package/extensions/plugin-dev/skills/agent-development/examples/complete-agent-examples.md +461 -0
  49. package/extensions/plugin-dev/skills/agent-development/references/advanced-agent-fields.md +246 -0
  50. package/extensions/plugin-dev/skills/agent-development/references/agent-creation-system-prompt.md +216 -0
  51. package/extensions/plugin-dev/skills/agent-development/references/permission-modes-rules.md +226 -0
  52. package/extensions/plugin-dev/skills/agent-development/references/system-prompt-design.md +464 -0
  53. package/extensions/plugin-dev/skills/agent-development/references/triggering-examples.md +474 -0
  54. package/extensions/plugin-dev/skills/agent-development/scripts/create-agent-skeleton.sh +176 -0
  55. package/extensions/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh +227 -0
  56. package/extensions/plugin-dev/skills/agent-development/scripts/validate-agent.sh +227 -0
  57. package/extensions/plugin-dev/skills/command-development/SKILL.md +763 -0
  58. package/extensions/plugin-dev/skills/command-development/examples/plugin-commands.md +612 -0
  59. package/extensions/plugin-dev/skills/command-development/examples/simple-commands.md +527 -0
  60. package/extensions/plugin-dev/skills/command-development/references/advanced-workflows.md +762 -0
  61. package/extensions/plugin-dev/skills/command-development/references/documentation-patterns.md +769 -0
  62. package/extensions/plugin-dev/skills/command-development/references/frontmatter-reference.md +508 -0
  63. package/extensions/plugin-dev/skills/command-development/references/interactive-commands.md +966 -0
  64. package/extensions/plugin-dev/skills/command-development/references/marketplace-considerations.md +943 -0
  65. package/extensions/plugin-dev/skills/command-development/references/plugin-features-reference.md +637 -0
  66. package/extensions/plugin-dev/skills/command-development/references/plugin-integration.md +191 -0
  67. package/extensions/plugin-dev/skills/command-development/references/skill-tool.md +447 -0
  68. package/extensions/plugin-dev/skills/command-development/references/testing-strategies.md +723 -0
  69. package/extensions/plugin-dev/skills/command-development/scripts/check-frontmatter.sh +234 -0
  70. package/extensions/plugin-dev/skills/command-development/scripts/validate-command.sh +160 -0
  71. package/extensions/plugin-dev/skills/hook-development/SKILL.md +861 -0
  72. package/extensions/plugin-dev/skills/hook-development/examples/load-context.sh +55 -0
  73. package/extensions/plugin-dev/skills/hook-development/examples/validate-bash.sh +57 -0
  74. package/extensions/plugin-dev/skills/hook-development/examples/validate-write.sh +48 -0
  75. package/extensions/plugin-dev/skills/hook-development/references/advanced.md +871 -0
  76. package/extensions/plugin-dev/skills/hook-development/references/hook-input-schemas.md +145 -0
  77. package/extensions/plugin-dev/skills/hook-development/references/migration.md +392 -0
  78. package/extensions/plugin-dev/skills/hook-development/references/patterns.md +430 -0
  79. package/extensions/plugin-dev/skills/hook-development/scripts/README.md +181 -0
  80. package/extensions/plugin-dev/skills/hook-development/scripts/hook-linter.sh +153 -0
  81. package/extensions/plugin-dev/skills/hook-development/scripts/test-hook.sh +276 -0
  82. package/extensions/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh +159 -0
  83. package/extensions/plugin-dev/skills/mcp-integration/SKILL.md +775 -0
  84. package/extensions/plugin-dev/skills/mcp-integration/examples/http-server.json +20 -0
  85. package/extensions/plugin-dev/skills/mcp-integration/examples/sse-server.json +19 -0
  86. package/extensions/plugin-dev/skills/mcp-integration/examples/stdio-server.json +38 -0
  87. package/extensions/plugin-dev/skills/mcp-integration/examples/ws-server.json +26 -0
  88. package/extensions/plugin-dev/skills/mcp-integration/references/authentication.md +601 -0
  89. package/extensions/plugin-dev/skills/mcp-integration/references/server-discovery.md +190 -0
  90. package/extensions/plugin-dev/skills/mcp-integration/references/server-types.md +572 -0
  91. package/extensions/plugin-dev/skills/mcp-integration/references/tool-usage.md +623 -0
  92. package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +222 -0
  93. package/extensions/plugin-dev/skills/plugin-structure/SKILL.md +705 -0
  94. package/extensions/plugin-dev/skills/plugin-structure/examples/advanced-plugin.md +774 -0
  95. package/extensions/plugin-dev/skills/plugin-structure/examples/minimal-plugin.md +83 -0
  96. package/extensions/plugin-dev/skills/plugin-structure/examples/standard-plugin.md +611 -0
  97. package/extensions/plugin-dev/skills/plugin-structure/references/advanced-topics.md +289 -0
  98. package/extensions/plugin-dev/skills/plugin-structure/references/component-patterns.md +592 -0
  99. package/extensions/plugin-dev/skills/plugin-structure/references/github-actions.md +233 -0
  100. package/extensions/plugin-dev/skills/plugin-structure/references/headless-ci-mode.md +193 -0
  101. package/extensions/plugin-dev/skills/plugin-structure/references/manifest-reference.md +625 -0
  102. package/extensions/plugin-dev/skills/plugin-structure/references/output-styles.md +116 -0
  103. package/extensions/plugin-dev/skills/skill-development/SKILL.md +564 -0
  104. package/extensions/plugin-dev/skills/skill-development/examples/complete-skill.md +465 -0
  105. package/extensions/plugin-dev/skills/skill-development/examples/frontmatter-templates.md +167 -0
  106. package/extensions/plugin-dev/skills/skill-development/examples/minimal-skill.md +111 -0
  107. package/extensions/plugin-dev/skills/skill-development/references/advanced-frontmatter.md +225 -0
  108. package/extensions/plugin-dev/skills/skill-development/references/commands-vs-skills.md +39 -0
  109. package/extensions/plugin-dev/skills/skill-development/references/skill-creation-workflow.md +379 -0
  110. package/extensions/plugin-dev/skills/skill-development/references/skill-creator-original.md +210 -0
  111. package/package.json +8 -11
  112. package/scripts/enact-extensions.mjs +751 -16
  113. package/scripts/hooks/session-start-drift-check.mjs +58 -0
  114. package/scripts/lib/build-index.mjs +50 -0
  115. package/scripts/lib/bundle-hash.mjs +137 -0
  116. package/scripts/lib/hooks.mjs +389 -0
  117. package/scripts/lib/ledger.mjs +162 -0
  118. package/scripts/lib/list-bundles.mjs +70 -0
  119. package/scripts/lib/outdated.mjs +144 -0
  120. package/scripts/lib/provision-mcp.mjs +369 -0
  121. package/scripts/lib/resolve-bundle.mjs +121 -0
  122. package/scripts/lib/run-install.mjs +321 -39
  123. package/scripts/lib/run-uninstall.mjs +220 -0
  124. package/scripts/lib/run-update.mjs +152 -0
  125. package/scripts/lib/run-validate.mjs +12 -18
  126. package/scripts/lib/serve.mjs +454 -0
  127. package/scripts/postinstall.mjs +63 -0
  128. package/scripts/setup-enact-context.sh +2 -2
  129. package/spec/index.json +59 -0
  130. package/web/assets/README.md +111 -0
  131. package/web/assets/logo-full.png +0 -0
  132. package/web/assets/logo-slim.png +0 -0
  133. package/web/assets/tokens/base.css +45 -0
  134. package/web/assets/tokens/colors.css +248 -0
  135. package/web/assets/tokens/effects.css +24 -0
  136. package/web/assets/tokens/fonts.css +8 -0
  137. package/web/assets/tokens/index.css +18 -0
  138. package/web/assets/tokens/spacing.css +50 -0
  139. package/web/index.html +1188 -0
  140. package/.agents/plugins/marketplace.json +0 -20
  141. package/catalog/enact-context.json +0 -9
  142. package/catalog/enact-factory.json +0 -7
  143. package/catalog/enact-operator.json +0 -7
  144. package/catalog/enact-wiki.json +0 -7
  145. package/catalog/net-revenue-management.json +0 -8
  146. package/scripts/rename-supervisor-to-operator.pl +0 -66
  147. package/scripts/sync-manifests.mjs +0 -23
  148. package/scripts/validate-catalog.mjs +0 -37
  149. package/scripts/validate-plugin.mjs +0 -10
  150. /package/{plugins → extensions}/net-revenue-management/.mcp.json +0 -0
  151. /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-risks/SKILL.md +0 -0
  152. /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-scenario/SKILL.md +0 -0
@@ -0,0 +1,234 @@
1
+ #!/bin/bash
2
+ # Command Frontmatter Validator
3
+ # Validates YAML frontmatter fields in command files
4
+
5
+ set -euo pipefail
6
+
7
+ # Usage
8
+ if [ $# -eq 0 ]; then
9
+ echo "Usage: $0 <path/to/command.md> [command2.md ...]"
10
+ echo ""
11
+ echo "Validates frontmatter fields for:"
12
+ echo " - 'model' field (sonnet, opus, haiku, or full model ID)"
13
+ echo " - 'description' length (warns if > 60 chars)"
14
+ echo " - 'allowed-tools' format"
15
+ echo " - 'argument-hint' format"
16
+ echo " - 'disable-model-invocation' boolean"
17
+ echo " - Unknown fields (warning)"
18
+ echo ""
19
+ echo "Examples:"
20
+ echo " $0 .claude/commands/review.md"
21
+ echo " $0 commands/*.md"
22
+ exit 1
23
+ fi
24
+
25
+ # Known frontmatter fields for commands
26
+ KNOWN_FIELDS="description model allowed-tools argument-hint disable-model-invocation"
27
+
28
+ total_errors=0
29
+ total_warnings=0
30
+
31
+ check_frontmatter() {
32
+ local COMMAND_FILE="$1"
33
+ local error_count=0
34
+ local warning_count=0
35
+
36
+ echo "🔍 Checking frontmatter: $COMMAND_FILE"
37
+ echo ""
38
+
39
+ # Check file exists
40
+ if [ ! -f "$COMMAND_FILE" ]; then
41
+ echo "❌ Error: File not found: $COMMAND_FILE"
42
+ return 1
43
+ fi
44
+
45
+ # Check for frontmatter
46
+ if ! head -n 1 "$COMMAND_FILE" | grep -q "^---"; then
47
+ echo "â„šī¸ No frontmatter found (frontmatter is optional)"
48
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
49
+ echo "✅ $COMMAND_FILE: No frontmatter to validate"
50
+ echo ""
51
+ return 0
52
+ fi
53
+
54
+ # Extract frontmatter - only the first block between lines 1 and the second ---
55
+ # Use awk to get content between first and second --- markers only
56
+ local frontmatter
57
+ frontmatter=$(awk '
58
+ /^---$/ { count++; if (count == 2) exit; next }
59
+ count == 1 { print }
60
+ ' "$COMMAND_FILE")
61
+
62
+ if [ -z "$frontmatter" ]; then
63
+ echo "âš ī¸ Warning: Empty frontmatter block"
64
+ ((warning_count++))
65
+ total_warnings=$((total_warnings + warning_count))
66
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
67
+ echo "âš ī¸ $COMMAND_FILE: Passed with $warning_count warning(s)"
68
+ echo ""
69
+ return 0
70
+ fi
71
+
72
+ echo "Frontmatter found. Validating fields..."
73
+ echo ""
74
+
75
+ # Check 'model' field
76
+ if echo "$frontmatter" | grep -q "^model:"; then
77
+ local model
78
+ model=$(echo "$frontmatter" | grep "^model:" | cut -d: -f2 | tr -d ' ')
79
+
80
+ # Valid values: sonnet, opus, haiku, or full model ID (claude-*)
81
+ if [[ "$model" =~ ^(sonnet|opus|haiku)$ ]]; then
82
+ echo "✅ model: $model (shorthand)"
83
+ elif [[ "$model" =~ ^claude- ]]; then
84
+ echo "✅ model: $model (full model ID)"
85
+ else
86
+ echo "❌ Error: Invalid model '$model'"
87
+ echo " Valid: sonnet, opus, haiku, or full model ID (e.g., claude-sonnet-4-5-20250929)"
88
+ ((error_count++))
89
+ fi
90
+ fi
91
+
92
+ # Check 'description' field
93
+ if echo "$frontmatter" | grep -q "^description:"; then
94
+ local desc
95
+ desc=$(echo "$frontmatter" | grep "^description:" | cut -d: -f2- | sed 's/^ *//')
96
+ local length=${#desc}
97
+
98
+ if [ "$length" -eq 0 ]; then
99
+ echo "âš ī¸ Warning: Empty description"
100
+ ((warning_count++))
101
+ elif [ "$length" -gt 80 ]; then
102
+ echo "âš ī¸ Warning: Description too long ($length chars, recommend < 60)"
103
+ ((warning_count++))
104
+ elif [ "$length" -gt 60 ]; then
105
+ echo "âš ī¸ Warning: Description length $length (recommend < 60 chars)"
106
+ ((warning_count++))
107
+ else
108
+ echo "✅ description: $length chars"
109
+ fi
110
+ fi
111
+
112
+ # Check 'allowed-tools' field
113
+ if echo "$frontmatter" | grep -q "^allowed-tools:"; then
114
+ local tools
115
+ tools=$(echo "$frontmatter" | grep "^allowed-tools:" | cut -d: -f2- | sed 's/^ *//')
116
+
117
+ if [ -z "$tools" ]; then
118
+ echo "âš ī¸ Warning: Empty allowed-tools field"
119
+ ((warning_count++))
120
+ else
121
+ # Check for common patterns
122
+ if [[ "$tools" == "*" ]]; then
123
+ echo "âš ī¸ Warning: allowed-tools: * grants all tools (consider restricting)"
124
+ ((warning_count++))
125
+ elif [[ "$tools" =~ Bash\(\*\) ]]; then
126
+ echo "âš ī¸ Warning: Bash(*) is very permissive (consider Bash(git:*) or similar)"
127
+ ((warning_count++))
128
+ else
129
+ echo "✅ allowed-tools: $tools"
130
+ fi
131
+ fi
132
+ fi
133
+
134
+ # Check 'argument-hint' field
135
+ if echo "$frontmatter" | grep -q "^argument-hint:"; then
136
+ local hint
137
+ hint=$(echo "$frontmatter" | grep "^argument-hint:" | cut -d: -f2- | sed 's/^ *//')
138
+
139
+ if [ -z "$hint" ]; then
140
+ echo "âš ī¸ Warning: Empty argument-hint field"
141
+ ((warning_count++))
142
+ else
143
+ # Check for bracket convention
144
+ if [[ ! "$hint" =~ \[.*\] ]]; then
145
+ echo "âš ī¸ Warning: argument-hint missing bracket convention (e.g., [arg-name])"
146
+ ((warning_count++))
147
+ else
148
+ echo "✅ argument-hint: $hint"
149
+ fi
150
+ fi
151
+ fi
152
+
153
+ # Check 'disable-model-invocation' field
154
+ if echo "$frontmatter" | grep -q "^disable-model-invocation:"; then
155
+ local value
156
+ value=$(echo "$frontmatter" | grep "^disable-model-invocation:" | cut -d: -f2 | tr -d ' ')
157
+
158
+ if [[ "$value" =~ ^(true|false)$ ]]; then
159
+ echo "✅ disable-model-invocation: $value"
160
+ else
161
+ echo "❌ Error: disable-model-invocation must be true or false (got '$value')"
162
+ ((error_count++))
163
+ fi
164
+ fi
165
+
166
+ # Check for unknown fields
167
+ echo ""
168
+ echo "Checking for unknown fields..."
169
+ local unknown_found=false
170
+
171
+ while IFS= read -r line; do
172
+ # Skip empty lines
173
+ [ -z "$line" ] && continue
174
+
175
+ # Extract field name (everything before the colon)
176
+ local field
177
+ field=$(echo "$line" | grep -oE "^[a-z-]+" || true)
178
+
179
+ if [ -n "$field" ]; then
180
+ local known=false
181
+ for known_field in $KNOWN_FIELDS; do
182
+ if [ "$field" = "$known_field" ]; then
183
+ known=true
184
+ break
185
+ fi
186
+ done
187
+
188
+ if [ "$known" = false ]; then
189
+ echo "âš ī¸ Warning: Unknown field '$field'"
190
+ ((warning_count++))
191
+ unknown_found=true
192
+ fi
193
+ fi
194
+ done <<< "$frontmatter"
195
+
196
+ if [ "$unknown_found" = false ]; then
197
+ echo "✅ No unknown fields"
198
+ fi
199
+
200
+ # Summary
201
+ echo ""
202
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
203
+ if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then
204
+ echo "✅ $COMMAND_FILE: All frontmatter checks passed!"
205
+ elif [ $error_count -eq 0 ]; then
206
+ echo "âš ī¸ $COMMAND_FILE: Passed with $warning_count warning(s)"
207
+ else
208
+ echo "❌ $COMMAND_FILE: Failed with $error_count error(s) and $warning_count warning(s)"
209
+ fi
210
+ echo ""
211
+
212
+ total_errors=$((total_errors + error_count))
213
+ total_warnings=$((total_warnings + warning_count))
214
+
215
+ return $error_count
216
+ }
217
+
218
+ # Process all provided files
219
+ for file in "$@"; do
220
+ check_frontmatter "$file" || true
221
+ done
222
+
223
+ # Final summary for multiple files
224
+ if [ $# -gt 1 ]; then
225
+ echo "═══════════════════════════════════════"
226
+ echo "Total: $# files checked"
227
+ echo "Errors: $total_errors"
228
+ echo "Warnings: $total_warnings"
229
+ fi
230
+
231
+ if [ $total_errors -gt 0 ]; then
232
+ exit 1
233
+ fi
234
+ exit 0
@@ -0,0 +1,160 @@
1
+ #!/bin/bash
2
+ # Command File Validator
3
+ # Validates command file structure and syntax
4
+
5
+ set -euo pipefail
6
+
7
+ # Usage
8
+ if [ $# -eq 0 ]; then
9
+ echo "Usage: $0 <path/to/command.md> [command2.md ...]"
10
+ echo ""
11
+ echo "Validates command file for:"
12
+ echo " - File exists with .md extension"
13
+ echo " - YAML frontmatter syntax (if present)"
14
+ echo " - Non-empty content"
15
+ echo " - Correct location (warning only)"
16
+ echo ""
17
+ echo "Examples:"
18
+ echo " $0 .claude/commands/review.md"
19
+ echo " $0 commands/*.md"
20
+ exit 1
21
+ fi
22
+
23
+ total_errors=0
24
+ total_warnings=0
25
+
26
+ validate_command() {
27
+ local COMMAND_FILE="$1"
28
+ local error_count=0
29
+ local warning_count=0
30
+
31
+ echo "🔍 Validating command: $COMMAND_FILE"
32
+ echo ""
33
+
34
+ # Check 1: File exists
35
+ if [ ! -f "$COMMAND_FILE" ]; then
36
+ echo "❌ Error: File not found: $COMMAND_FILE"
37
+ return 1
38
+ fi
39
+ echo "✅ File exists"
40
+
41
+ # Check 2: .md extension
42
+ if [[ ! "$COMMAND_FILE" =~ \.md$ ]]; then
43
+ echo "❌ Error: File must have .md extension"
44
+ ((error_count++))
45
+ else
46
+ echo "✅ Has .md extension"
47
+ fi
48
+
49
+ # Check 3: Non-empty file
50
+ if [ ! -s "$COMMAND_FILE" ]; then
51
+ echo "❌ Error: File is empty"
52
+ ((error_count++))
53
+ else
54
+ echo "✅ File is not empty"
55
+ fi
56
+
57
+ # Check 4: YAML frontmatter syntax (if present)
58
+ if head -n 1 "$COMMAND_FILE" | grep -q "^---"; then
59
+ echo ""
60
+ echo "Checking YAML frontmatter..."
61
+
62
+ # Count frontmatter markers in first 50 lines
63
+ MARKERS=$(head -n 50 "$COMMAND_FILE" | grep -c "^---" || true)
64
+ if [ "$MARKERS" -lt 2 ]; then
65
+ echo "❌ Error: Invalid YAML frontmatter (need exactly 2 '---' markers, found $MARKERS)"
66
+ ((error_count++))
67
+ elif [ "$MARKERS" -gt 2 ]; then
68
+ echo "âš ī¸ Warning: Multiple frontmatter markers detected ($MARKERS). Only first pair is used."
69
+ ((warning_count++))
70
+ else
71
+ echo "✅ YAML frontmatter delimiters valid"
72
+ fi
73
+
74
+ # Check for malformed YAML (basic check)
75
+ # Extract frontmatter - only between first and second --- markers
76
+ local frontmatter
77
+ frontmatter=$(awk '
78
+ /^---$/ { count++; if (count == 2) exit; next }
79
+ count == 1 { print }
80
+ ' "$COMMAND_FILE")
81
+
82
+ if [ -n "$frontmatter" ]; then
83
+ # Check for tabs (YAML prefers spaces)
84
+ if echo "$frontmatter" | grep -q $'\t'; then
85
+ echo "âš ī¸ Warning: Frontmatter contains tabs (YAML prefers spaces)"
86
+ ((warning_count++))
87
+ fi
88
+
89
+ # Check for common YAML errors - key without value
90
+ if echo "$frontmatter" | grep -qE "^[a-z-]+:$"; then
91
+ echo "âš ī¸ Warning: Frontmatter has keys without values"
92
+ ((warning_count++))
93
+ fi
94
+ fi
95
+ else
96
+ echo ""
97
+ echo "â„šī¸ No YAML frontmatter (optional)"
98
+ fi
99
+
100
+ # Check 5: Location warning
101
+ echo ""
102
+ echo "Checking location..."
103
+ if [[ "$COMMAND_FILE" == *".claude/commands/"* ]] || [[ "$COMMAND_FILE" == *"/commands/"* ]]; then
104
+ echo "✅ File in expected commands directory"
105
+ else
106
+ echo "âš ī¸ Warning: File not in .claude/commands/ or plugin commands/ directory"
107
+ ((warning_count++))
108
+ fi
109
+
110
+ # Check 6: Filename conventions
111
+ echo ""
112
+ echo "Checking filename..."
113
+ local filename
114
+ filename=$(basename "$COMMAND_FILE" .md)
115
+
116
+ if [[ "$filename" =~ [A-Z] ]]; then
117
+ echo "âš ī¸ Warning: Filename contains uppercase letters (recommend lowercase)"
118
+ ((warning_count++))
119
+ elif [[ "$filename" =~ [[:space:]] ]]; then
120
+ echo "âš ī¸ Warning: Filename contains spaces (use hyphens instead)"
121
+ ((warning_count++))
122
+ else
123
+ echo "✅ Filename follows conventions"
124
+ fi
125
+
126
+ # Summary
127
+ echo ""
128
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
129
+ if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then
130
+ echo "✅ $COMMAND_FILE: All checks passed!"
131
+ elif [ $error_count -eq 0 ]; then
132
+ echo "âš ī¸ $COMMAND_FILE: Passed with $warning_count warning(s)"
133
+ else
134
+ echo "❌ $COMMAND_FILE: Failed with $error_count error(s) and $warning_count warning(s)"
135
+ fi
136
+ echo ""
137
+
138
+ total_errors=$((total_errors + error_count))
139
+ total_warnings=$((total_warnings + warning_count))
140
+
141
+ return $error_count
142
+ }
143
+
144
+ # Process all provided files
145
+ for file in "$@"; do
146
+ validate_command "$file" || true
147
+ done
148
+
149
+ # Final summary for multiple files
150
+ if [ $# -gt 1 ]; then
151
+ echo "═══════════════════════════════════════"
152
+ echo "Total: $# files validated"
153
+ echo "Errors: $total_errors"
154
+ echo "Warnings: $total_warnings"
155
+ fi
156
+
157
+ if [ $total_errors -gt 0 ]; then
158
+ exit 1
159
+ fi
160
+ exit 0