@amsterdamdatalabs/enact-extensions 0.1.0 → 0.1.3
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/README.md +96 -21
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +171 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +402 -49
- package/dist/install.js.map +1 -1
- package/dist/internal/codex.d.ts.map +1 -1
- package/dist/internal/codex.js +7 -1
- package/dist/internal/codex.js.map +1 -1
- package/dist/internal/platform.d.ts +8 -0
- package/dist/internal/platform.d.ts.map +1 -1
- package/dist/internal/platform.js +46 -2
- package/dist/internal/platform.js.map +1 -1
- package/dist/provision.d.ts +30 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +202 -0
- package/dist/provision.js.map +1 -0
- package/dist/validate/index.d.ts +44 -0
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +157 -0
- package/dist/validate/index.js.map +1 -1
- package/extensions/cmux/.agents/plugin.json +37 -0
- package/extensions/cmux/skills/cmux/SKILL.md +82 -0
- package/extensions/cmux/skills/cmux/agents/openai.yaml +4 -0
- package/extensions/cmux/skills/cmux/references/handles-and-identify.md +35 -0
- package/extensions/cmux/skills/cmux/references/panes-surfaces.md +37 -0
- package/extensions/cmux/skills/cmux/references/trigger-flash-and-health.md +23 -0
- package/extensions/cmux/skills/cmux/references/windows-workspaces.md +31 -0
- package/extensions/cmux/skills/cmux-vm-monitor/SKILL.md +122 -0
- package/extensions/cmux/skills/cmux-vm-monitor/agents/openai.yaml +4 -0
- package/extensions/cmux/skills/cmux-vm-monitor/references/cmux-commands.md +66 -0
- package/extensions/cmux/skills/cmux-vm-monitor/scripts/codex_vm_monitor.sh +45 -0
- package/extensions/cmux/skills/cmux-workspace/SKILL.md +93 -0
- package/extensions/dev-state/.agents/plugin.json +35 -0
- package/extensions/dev-state/skills/dev-state-plan-graduation/SKILL.md +194 -0
- package/extensions/dev-state/skills/dev-state-plan-graduation/agents/openai.yaml +4 -0
- package/extensions/dev-state/skills/dev-state-plan-graduation/references/reference.md +130 -0
- package/extensions/devops/.agents/plugin.json +36 -0
- package/extensions/devops/skills/azure-devops-cli/SKILL.md +431 -0
- package/extensions/devops/skills/azure-devops-cli/agents/openai.yaml +4 -0
- package/extensions/devops/skills/ci-pipeline-strategy/SKILL.md +217 -0
- package/extensions/devops/skills/ci-pipeline-strategy/agents/openai.yaml +4 -0
- package/extensions/enact-context/.agents/plugin.json +40 -0
- package/extensions/enact-context/.mcp.json +8 -0
- package/extensions/enact-context/README.md +25 -0
- package/extensions/enact-context/assets/icon.png +0 -0
- package/extensions/enact-context/assets/logo.png +0 -0
- package/extensions/enact-context/hooks/hooks.json +115 -0
- package/extensions/enact-context/skills/enact-context/SKILL.md +149 -0
- package/extensions/enact-context/skills/enact-context/scripts/install.sh +69 -0
- package/extensions/enact-factory/.agents/plugin.json +42 -0
- package/extensions/enact-factory/.mcp.json +8 -0
- package/extensions/enact-factory/assets/icon.png +0 -0
- package/extensions/enact-factory/assets/logo.png +0 -0
- package/extensions/enact-factory/hooks/user-prompt-submit.mjs +67 -0
- package/extensions/enact-factory/skills/testing-strategy/SKILL.md +167 -0
- package/extensions/enact-factory/skills/workitem-triage/SKILL.md +22 -0
- package/extensions/enact-operator/.agents/plugin.json +57 -0
- package/extensions/enact-operator/.app.json +3 -0
- package/extensions/enact-operator/.mcp.json +10 -0
- package/extensions/enact-operator/_taxonomy.md +86 -0
- package/extensions/enact-operator/agents/README.md +5 -0
- package/extensions/enact-operator/agents/architect.toml +25 -0
- package/extensions/enact-operator/agents/code-reviewer.toml +24 -0
- package/extensions/enact-operator/agents/critic.toml +30 -0
- package/extensions/enact-operator/agents/executor.toml +24 -0
- package/extensions/enact-operator/agents/explore.toml +23 -0
- package/extensions/enact-operator/agents/planner.toml +24 -0
- package/extensions/enact-operator/agents/verifier.toml +24 -0
- package/extensions/enact-operator/assets/icon.png +0 -0
- package/extensions/enact-operator/assets/logo.png +0 -0
- package/extensions/enact-operator/commands/doctor.md +39 -0
- package/extensions/enact-operator/commands/setup.md +51 -0
- package/extensions/enact-operator/hooks/hooks.json +146 -0
- package/extensions/enact-operator/skills/_variants.md +44 -0
- package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +50 -0
- package/extensions/enact-operator/skills/analyze/SKILL.md +91 -0
- package/extensions/enact-operator/skills/ask/SKILL.md +47 -0
- package/extensions/enact-operator/skills/autopilot/SKILL.md +170 -0
- package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +79 -0
- package/extensions/enact-operator/skills/cancel/SKILL.md +99 -0
- package/extensions/enact-operator/skills/configure-notifications/SKILL.md +77 -0
- package/extensions/enact-operator/skills/deep-interview/SKILL.md +80 -0
- package/extensions/enact-operator/skills/doctor/SKILL.md +48 -0
- package/extensions/enact-operator/skills/hud/SKILL.md +49 -0
- package/extensions/enact-operator/skills/hyperplan/SKILL.md +47 -0
- package/extensions/enact-operator/skills/plan/SKILL.md +78 -0
- package/extensions/enact-operator/skills/ralph/SKILL.md +201 -0
- package/extensions/enact-operator/skills/ralph/gemini.md +18 -0
- package/extensions/enact-operator/skills/ralplan/SKILL.md +151 -0
- package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +45 -0
- package/extensions/enact-operator/skills/research/SKILL.md +74 -0
- package/extensions/enact-operator/skills/review/SKILL.md +58 -0
- package/extensions/enact-operator/skills/security-research/SKILL.md +54 -0
- package/extensions/enact-operator/skills/setup/SKILL.md +91 -0
- package/extensions/enact-operator/skills/setup/scripts/install.sh +50 -0
- package/extensions/enact-operator/skills/skill/SKILL.md +82 -0
- package/extensions/enact-operator/skills/tdd/SKILL.md +59 -0
- package/extensions/enact-operator/skills/team/SKILL.md +199 -0
- package/extensions/enact-operator/skills/trace/SKILL.md +41 -0
- package/extensions/enact-operator/skills/ultragoal/SKILL.md +99 -0
- package/extensions/enact-operator/skills/ultraqa/SKILL.md +113 -0
- package/extensions/enact-operator/skills/ultrawork/SKILL.md +145 -0
- package/extensions/enact-operator/skills/ultrawork/planner.md +28 -0
- package/extensions/enact-operator/skills/wiki/SKILL.md +41 -0
- package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +51 -0
- package/extensions/enact-wiki/.agents/plugin.json +42 -0
- package/extensions/enact-wiki/.mcp.json +15 -0
- package/extensions/enact-wiki/README.md +44 -0
- package/extensions/enact-wiki/assets/icon.png +0 -0
- package/extensions/enact-wiki/assets/logo.png +0 -0
- package/extensions/enact-wiki/skills/document-parser/SKILL.md +17 -0
- package/extensions/enact-wiki/skills/document-parser/scripts/parse.sh +60 -0
- package/extensions/enact-wiki/skills/document-parser/skill.json +9 -0
- package/extensions/enact-wiki/skills/enact-wiki/SKILL.md +30 -0
- package/extensions/enact-wiki/skills/enact-wiki/references/ingest.md +62 -0
- package/extensions/enact-wiki/skills/enact-wiki/references/manage.md +34 -0
- package/extensions/enact-wiki/skills/enact-wiki/references/query.md +59 -0
- package/extensions/enact-wiki/skills/search-lab/SKILL.md +57 -0
- package/extensions/enact-wiki/skills/search-lab/scripts/analyze.ts +23 -0
- package/{plugins/net-revenue-management/.codex-plugin → extensions/net-revenue-management/.agents}/plugin.json +10 -6
- package/extensions/plugin-dev/.agents/plugin.json +42 -0
- package/extensions/plugin-dev/.mcp.json +3 -0
- package/extensions/plugin-dev/agents/agent-creator.md +199 -0
- package/extensions/plugin-dev/agents/plugin-validator.md +91 -0
- package/extensions/plugin-dev/agents/skill-reviewer.md +212 -0
- package/extensions/plugin-dev/commands/_archive/create-marketplace.md +427 -0
- package/extensions/plugin-dev/commands/_archive/plugin-dev-guide.md +12 -0
- package/extensions/plugin-dev/commands/create-plugin.md +498 -0
- package/extensions/plugin-dev/commands/start.md +81 -0
- package/extensions/plugin-dev/hooks/hooks.json +3 -0
- package/extensions/plugin-dev/skills/agent-development/SKILL.md +641 -0
- package/extensions/plugin-dev/skills/agent-development/examples/agent-creation-prompt.md +250 -0
- package/extensions/plugin-dev/skills/agent-development/examples/complete-agent-examples.md +461 -0
- package/extensions/plugin-dev/skills/agent-development/references/advanced-agent-fields.md +246 -0
- package/extensions/plugin-dev/skills/agent-development/references/agent-creation-system-prompt.md +216 -0
- package/extensions/plugin-dev/skills/agent-development/references/permission-modes-rules.md +226 -0
- package/extensions/plugin-dev/skills/agent-development/references/system-prompt-design.md +464 -0
- package/extensions/plugin-dev/skills/agent-development/references/triggering-examples.md +474 -0
- package/extensions/plugin-dev/skills/agent-development/scripts/create-agent-skeleton.sh +176 -0
- package/extensions/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh +227 -0
- package/extensions/plugin-dev/skills/agent-development/scripts/validate-agent.sh +227 -0
- package/extensions/plugin-dev/skills/command-development/SKILL.md +763 -0
- package/extensions/plugin-dev/skills/command-development/examples/plugin-commands.md +612 -0
- package/extensions/plugin-dev/skills/command-development/examples/simple-commands.md +527 -0
- package/extensions/plugin-dev/skills/command-development/references/advanced-workflows.md +762 -0
- package/extensions/plugin-dev/skills/command-development/references/documentation-patterns.md +769 -0
- package/extensions/plugin-dev/skills/command-development/references/frontmatter-reference.md +508 -0
- package/extensions/plugin-dev/skills/command-development/references/interactive-commands.md +966 -0
- package/extensions/plugin-dev/skills/command-development/references/marketplace-considerations.md +943 -0
- package/extensions/plugin-dev/skills/command-development/references/plugin-features-reference.md +637 -0
- package/extensions/plugin-dev/skills/command-development/references/plugin-integration.md +191 -0
- package/extensions/plugin-dev/skills/command-development/references/skill-tool.md +447 -0
- package/extensions/plugin-dev/skills/command-development/references/testing-strategies.md +723 -0
- package/extensions/plugin-dev/skills/command-development/scripts/check-frontmatter.sh +234 -0
- package/extensions/plugin-dev/skills/command-development/scripts/validate-command.sh +160 -0
- package/extensions/plugin-dev/skills/hook-development/SKILL.md +861 -0
- package/extensions/plugin-dev/skills/hook-development/examples/load-context.sh +55 -0
- package/extensions/plugin-dev/skills/hook-development/examples/validate-bash.sh +57 -0
- package/extensions/plugin-dev/skills/hook-development/examples/validate-write.sh +48 -0
- package/extensions/plugin-dev/skills/hook-development/references/advanced.md +871 -0
- package/extensions/plugin-dev/skills/hook-development/references/hook-input-schemas.md +145 -0
- package/extensions/plugin-dev/skills/hook-development/references/migration.md +392 -0
- package/extensions/plugin-dev/skills/hook-development/references/patterns.md +430 -0
- package/extensions/plugin-dev/skills/hook-development/scripts/README.md +181 -0
- package/extensions/plugin-dev/skills/hook-development/scripts/hook-linter.sh +153 -0
- package/extensions/plugin-dev/skills/hook-development/scripts/test-hook.sh +276 -0
- package/extensions/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh +159 -0
- package/extensions/plugin-dev/skills/mcp-integration/SKILL.md +775 -0
- package/extensions/plugin-dev/skills/mcp-integration/examples/http-server.json +20 -0
- package/extensions/plugin-dev/skills/mcp-integration/examples/sse-server.json +19 -0
- package/extensions/plugin-dev/skills/mcp-integration/examples/stdio-server.json +38 -0
- package/extensions/plugin-dev/skills/mcp-integration/examples/ws-server.json +26 -0
- package/extensions/plugin-dev/skills/mcp-integration/references/authentication.md +601 -0
- package/extensions/plugin-dev/skills/mcp-integration/references/server-discovery.md +190 -0
- package/extensions/plugin-dev/skills/mcp-integration/references/server-types.md +572 -0
- package/extensions/plugin-dev/skills/mcp-integration/references/tool-usage.md +623 -0
- package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +222 -0
- package/extensions/plugin-dev/skills/plugin-structure/SKILL.md +705 -0
- package/extensions/plugin-dev/skills/plugin-structure/examples/advanced-plugin.md +774 -0
- package/extensions/plugin-dev/skills/plugin-structure/examples/minimal-plugin.md +83 -0
- package/extensions/plugin-dev/skills/plugin-structure/examples/standard-plugin.md +611 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/advanced-topics.md +289 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/component-patterns.md +592 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/github-actions.md +233 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/headless-ci-mode.md +193 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/manifest-reference.md +625 -0
- package/extensions/plugin-dev/skills/plugin-structure/references/output-styles.md +116 -0
- package/extensions/plugin-dev/skills/skill-development/SKILL.md +564 -0
- package/extensions/plugin-dev/skills/skill-development/examples/complete-skill.md +465 -0
- package/extensions/plugin-dev/skills/skill-development/examples/frontmatter-templates.md +167 -0
- package/extensions/plugin-dev/skills/skill-development/examples/minimal-skill.md +111 -0
- package/extensions/plugin-dev/skills/skill-development/references/advanced-frontmatter.md +225 -0
- package/extensions/plugin-dev/skills/skill-development/references/commands-vs-skills.md +39 -0
- package/extensions/plugin-dev/skills/skill-development/references/skill-creation-workflow.md +379 -0
- package/extensions/plugin-dev/skills/skill-development/references/skill-creator-original.md +210 -0
- package/package.json +8 -11
- package/scripts/enact-extensions.mjs +823 -21
- package/scripts/hooks/session-start-drift-check.mjs +58 -0
- package/scripts/lib/build-index.mjs +50 -0
- package/scripts/lib/bundle-hash.mjs +137 -0
- package/scripts/lib/hooks.mjs +741 -0
- package/scripts/lib/ledger.mjs +163 -0
- package/scripts/lib/list-bundles.mjs +70 -0
- package/scripts/lib/outdated.mjs +144 -0
- package/scripts/lib/provision-mcp.mjs +16 -0
- package/scripts/lib/resolve-bundle.mjs +121 -0
- package/scripts/lib/run-install.mjs +402 -38
- package/scripts/lib/run-prune.mjs +73 -0
- package/scripts/lib/run-sync.mjs +9 -1
- package/scripts/lib/run-uninstall.mjs +244 -0
- package/scripts/lib/run-update.mjs +152 -0
- package/scripts/lib/run-validate.mjs +21 -18
- package/scripts/lib/serve.mjs +472 -0
- package/scripts/postinstall.mjs +63 -0
- package/scripts/setup-enact-context.sh +2 -2
- package/scripts/version-bump.sh +463 -0
- package/spec/codex.json +1 -11
- package/spec/index.json +59 -0
- package/web/assets/README.md +111 -0
- package/web/assets/logo-full.png +0 -0
- package/web/assets/logo-slim.png +0 -0
- package/web/assets/tokens/base.css +45 -0
- package/web/assets/tokens/colors.css +248 -0
- package/web/assets/tokens/effects.css +24 -0
- package/web/assets/tokens/fonts.css +8 -0
- package/web/assets/tokens/index.css +18 -0
- package/web/assets/tokens/spacing.css +50 -0
- package/web/index.html +1188 -0
- package/.agents/plugins/marketplace.json +0 -20
- package/catalog/enact-context.json +0 -9
- package/catalog/enact-factory.json +0 -7
- package/catalog/enact-operator.json +0 -7
- package/catalog/enact-wiki.json +0 -7
- package/catalog/net-revenue-management.json +0 -8
- package/scripts/rename-supervisor-to-operator.pl +0 -66
- package/scripts/sync-manifests.mjs +0 -23
- package/scripts/validate-catalog.mjs +0 -37
- package/scripts/validate-plugin.mjs +0 -10
- /package/{plugins → extensions}/net-revenue-management/.mcp.json +0 -0
- /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-risks/SKILL.md +0 -0
- /package/{plugins → extensions}/net-revenue-management/skills/net-revenue-scenario/SKILL.md +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Hook Linter
|
|
3
|
+
# Checks hook scripts for common issues and best practices
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
# Usage
|
|
8
|
+
if [ $# -eq 0 ]; then
|
|
9
|
+
echo "Usage: $0 <hook-script.sh> [hook-script2.sh ...]"
|
|
10
|
+
echo ""
|
|
11
|
+
echo "Checks hook scripts for:"
|
|
12
|
+
echo " - Shebang presence"
|
|
13
|
+
echo " - set -euo pipefail usage"
|
|
14
|
+
echo " - Input reading from stdin"
|
|
15
|
+
echo " - Proper error handling"
|
|
16
|
+
echo " - Variable quoting"
|
|
17
|
+
echo " - Exit code usage"
|
|
18
|
+
echo " - Hardcoded paths"
|
|
19
|
+
echo " - Timeout considerations"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
check_script() {
|
|
24
|
+
local script="$1"
|
|
25
|
+
local warnings=0
|
|
26
|
+
local errors=0
|
|
27
|
+
|
|
28
|
+
echo "🔍 Linting: $script"
|
|
29
|
+
echo ""
|
|
30
|
+
|
|
31
|
+
if [ ! -f "$script" ]; then
|
|
32
|
+
echo "❌ Error: File not found"
|
|
33
|
+
return 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Check 1: Executable
|
|
37
|
+
if [ ! -x "$script" ]; then
|
|
38
|
+
echo "⚠️ Not executable (chmod +x $script)"
|
|
39
|
+
((warnings++))
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Check 2: Shebang
|
|
43
|
+
first_line=$(head -1 "$script")
|
|
44
|
+
if [[ ! "$first_line" =~ ^#!/ ]]; then
|
|
45
|
+
echo "❌ Missing shebang (#!/bin/bash)"
|
|
46
|
+
((errors++))
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check 3: set -euo pipefail
|
|
50
|
+
if ! grep -q "set -euo pipefail" "$script"; then
|
|
51
|
+
echo "⚠️ Missing 'set -euo pipefail' (recommended for safety)"
|
|
52
|
+
((warnings++))
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Check 4: Reads from stdin
|
|
56
|
+
if ! grep -Eq "cat|read" "$script"; then
|
|
57
|
+
echo "⚠️ Doesn't appear to read input from stdin"
|
|
58
|
+
((warnings++))
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Check 5: Uses jq for JSON parsing
|
|
62
|
+
if grep -Eq "tool_input|tool_name" "$script" && ! grep -q "jq" "$script"; then
|
|
63
|
+
echo "⚠️ Parses hook input but doesn't use jq"
|
|
64
|
+
((warnings++))
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Check 6: Unquoted variables
|
|
68
|
+
if grep -E '\$[A-Za-z_][A-Za-z0-9_]*[^"]' "$script" | grep -v '#' | grep -q .; then
|
|
69
|
+
echo "⚠️ Potentially unquoted variables detected (injection risk)"
|
|
70
|
+
echo " Always use double quotes: \"\$variable\" not \$variable"
|
|
71
|
+
((warnings++))
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Check 7: Hardcoded paths
|
|
75
|
+
if grep -E '^[^#]*/home/|^[^#]*/usr/|^[^#]*/opt/' "$script" | grep -q .; then
|
|
76
|
+
echo "⚠️ Hardcoded absolute paths detected"
|
|
77
|
+
echo " Use \$CLAUDE_PROJECT_DIR or \$CLAUDE_PLUGIN_ROOT"
|
|
78
|
+
((warnings++))
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Check 8: Uses CLAUDE_PLUGIN_ROOT
|
|
82
|
+
if ! grep -Eq "CLAUDE_PLUGIN_ROOT|CLAUDE_PROJECT_DIR" "$script"; then
|
|
83
|
+
echo "💡 Tip: Use \$CLAUDE_PLUGIN_ROOT for plugin-relative paths"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Check 9: Exit codes
|
|
87
|
+
if ! grep -Eq "exit 0|exit 2" "$script"; then
|
|
88
|
+
echo "⚠️ No explicit exit codes (should exit 0 or 2)"
|
|
89
|
+
((warnings++))
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# Check 10: JSON output for decision hooks
|
|
93
|
+
if grep -Eq "PreToolUse|Stop" "$script"; then
|
|
94
|
+
if ! grep -Eq "permissionDecision|decision" "$script"; then
|
|
95
|
+
echo "💡 Tip: PreToolUse/Stop hooks should output decision JSON"
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# Check 11: Long-running commands
|
|
100
|
+
if grep -E 'sleep [0-9]{3,}|while true' "$script" | grep -v '#' | grep -q .; then
|
|
101
|
+
echo "⚠️ Potentially long-running code detected"
|
|
102
|
+
echo " Hooks should complete quickly (< 60s)"
|
|
103
|
+
((warnings++))
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Check 12: Error messages to stderr
|
|
107
|
+
if grep -Eq 'echo.*".*error|Error|denied|Denied' "$script"; then
|
|
108
|
+
if ! grep -q '>&2' "$script"; then
|
|
109
|
+
echo "⚠️ Error messages should be written to stderr (>&2)"
|
|
110
|
+
((warnings++))
|
|
111
|
+
fi
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Check 13: Input validation
|
|
115
|
+
if ! grep -Eq "if.*empty|if.*null|if.*-z" "$script"; then
|
|
116
|
+
echo "💡 Tip: Consider validating input fields aren't empty"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
echo ""
|
|
120
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
121
|
+
|
|
122
|
+
if [ $errors -eq 0 ] && [ $warnings -eq 0 ]; then
|
|
123
|
+
echo "✅ No issues found"
|
|
124
|
+
return 0
|
|
125
|
+
elif [ $errors -eq 0 ]; then
|
|
126
|
+
echo "⚠️ Found $warnings warning(s)"
|
|
127
|
+
return 0
|
|
128
|
+
else
|
|
129
|
+
echo "❌ Found $errors error(s) and $warnings warning(s)"
|
|
130
|
+
return 1
|
|
131
|
+
fi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
echo "🔎 Hook Script Linter"
|
|
135
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
136
|
+
echo ""
|
|
137
|
+
|
|
138
|
+
total_errors=0
|
|
139
|
+
|
|
140
|
+
for script in "$@"; do
|
|
141
|
+
if ! check_script "$script"; then
|
|
142
|
+
((total_errors++))
|
|
143
|
+
fi
|
|
144
|
+
echo ""
|
|
145
|
+
done
|
|
146
|
+
|
|
147
|
+
if [ $total_errors -eq 0 ]; then
|
|
148
|
+
echo "✅ All scripts passed linting"
|
|
149
|
+
exit 0
|
|
150
|
+
else
|
|
151
|
+
echo "❌ $total_errors script(s) had errors"
|
|
152
|
+
exit 1
|
|
153
|
+
fi
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Hook Testing Helper
|
|
3
|
+
# Tests a hook with sample input and shows output
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
# Usage
|
|
8
|
+
show_usage() {
|
|
9
|
+
echo "Usage: $0 [options] <hook-script> <test-input.json>"
|
|
10
|
+
echo ""
|
|
11
|
+
echo "Options:"
|
|
12
|
+
echo " -h, --help Show this help message"
|
|
13
|
+
echo " -v, --verbose Show detailed execution information"
|
|
14
|
+
echo " -t, --timeout N Set timeout in seconds (default: 60)"
|
|
15
|
+
echo ""
|
|
16
|
+
echo "Examples:"
|
|
17
|
+
echo " $0 validate-bash.sh test-input.json"
|
|
18
|
+
echo " $0 -v -t 30 validate-write.sh write-input.json"
|
|
19
|
+
echo ""
|
|
20
|
+
echo "Creates sample test input with:"
|
|
21
|
+
echo " $0 --create-sample <event-type>"
|
|
22
|
+
exit 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Create sample input
|
|
26
|
+
create_sample() {
|
|
27
|
+
event_type="$1"
|
|
28
|
+
|
|
29
|
+
case "$event_type" in
|
|
30
|
+
PreToolUse)
|
|
31
|
+
cat <<'EOF'
|
|
32
|
+
{
|
|
33
|
+
"session_id": "test-session",
|
|
34
|
+
"transcript_path": "/tmp/transcript.txt",
|
|
35
|
+
"cwd": "/tmp/test-project",
|
|
36
|
+
"permission_mode": "ask",
|
|
37
|
+
"hook_event_name": "PreToolUse",
|
|
38
|
+
"tool_name": "Write",
|
|
39
|
+
"tool_input": {
|
|
40
|
+
"file_path": "/tmp/test.txt",
|
|
41
|
+
"content": "Test content"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
EOF
|
|
45
|
+
;;
|
|
46
|
+
PostToolUse)
|
|
47
|
+
cat <<'EOF'
|
|
48
|
+
{
|
|
49
|
+
"session_id": "test-session",
|
|
50
|
+
"transcript_path": "/tmp/transcript.txt",
|
|
51
|
+
"cwd": "/tmp/test-project",
|
|
52
|
+
"permission_mode": "ask",
|
|
53
|
+
"hook_event_name": "PostToolUse",
|
|
54
|
+
"tool_name": "Bash",
|
|
55
|
+
"tool_result": "Command executed successfully"
|
|
56
|
+
}
|
|
57
|
+
EOF
|
|
58
|
+
;;
|
|
59
|
+
Stop|SubagentStop)
|
|
60
|
+
cat <<'EOF'
|
|
61
|
+
{
|
|
62
|
+
"session_id": "test-session",
|
|
63
|
+
"transcript_path": "/tmp/transcript.txt",
|
|
64
|
+
"cwd": "/tmp/test-project",
|
|
65
|
+
"permission_mode": "ask",
|
|
66
|
+
"hook_event_name": "Stop",
|
|
67
|
+
"reason": "Task appears complete"
|
|
68
|
+
}
|
|
69
|
+
EOF
|
|
70
|
+
;;
|
|
71
|
+
UserPromptSubmit)
|
|
72
|
+
cat <<'EOF'
|
|
73
|
+
{
|
|
74
|
+
"session_id": "test-session",
|
|
75
|
+
"transcript_path": "/tmp/transcript.txt",
|
|
76
|
+
"cwd": "/tmp/test-project",
|
|
77
|
+
"permission_mode": "ask",
|
|
78
|
+
"hook_event_name": "UserPromptSubmit",
|
|
79
|
+
"user_prompt": "Test user prompt"
|
|
80
|
+
}
|
|
81
|
+
EOF
|
|
82
|
+
;;
|
|
83
|
+
SessionStart|SessionEnd)
|
|
84
|
+
cat <<'EOF'
|
|
85
|
+
{
|
|
86
|
+
"session_id": "test-session",
|
|
87
|
+
"transcript_path": "/tmp/transcript.txt",
|
|
88
|
+
"cwd": "/tmp/test-project",
|
|
89
|
+
"permission_mode": "ask",
|
|
90
|
+
"hook_event_name": "SessionStart"
|
|
91
|
+
}
|
|
92
|
+
EOF
|
|
93
|
+
;;
|
|
94
|
+
*)
|
|
95
|
+
echo "Unknown event type: $event_type"
|
|
96
|
+
echo "Valid types: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit, SessionStart, SessionEnd"
|
|
97
|
+
exit 1
|
|
98
|
+
;;
|
|
99
|
+
esac
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Parse arguments
|
|
103
|
+
VERBOSE=false
|
|
104
|
+
TIMEOUT=60
|
|
105
|
+
|
|
106
|
+
while [ $# -gt 0 ]; do
|
|
107
|
+
case "$1" in
|
|
108
|
+
-h|--help)
|
|
109
|
+
show_usage
|
|
110
|
+
;;
|
|
111
|
+
-v|--verbose)
|
|
112
|
+
VERBOSE=true
|
|
113
|
+
shift
|
|
114
|
+
;;
|
|
115
|
+
-t|--timeout)
|
|
116
|
+
TIMEOUT="$2"
|
|
117
|
+
shift 2
|
|
118
|
+
;;
|
|
119
|
+
--create-sample)
|
|
120
|
+
create_sample "$2"
|
|
121
|
+
exit 0
|
|
122
|
+
;;
|
|
123
|
+
*)
|
|
124
|
+
break
|
|
125
|
+
;;
|
|
126
|
+
esac
|
|
127
|
+
done
|
|
128
|
+
|
|
129
|
+
if [ $# -ne 2 ]; then
|
|
130
|
+
echo "Error: Missing required arguments"
|
|
131
|
+
echo ""
|
|
132
|
+
show_usage
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
HOOK_SCRIPT="$1"
|
|
136
|
+
TEST_INPUT="$2"
|
|
137
|
+
|
|
138
|
+
# Validate inputs
|
|
139
|
+
if [ ! -f "$HOOK_SCRIPT" ]; then
|
|
140
|
+
echo "❌ Error: Hook script not found: $HOOK_SCRIPT"
|
|
141
|
+
exit 1
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# Security: Validate hook script path doesn't contain dangerous characters
|
|
145
|
+
# This prevents potential command injection through maliciously crafted paths
|
|
146
|
+
if [[ "$HOOK_SCRIPT" =~ [\;\|\&\`\$\(\)\{\}\<\>] ]]; then
|
|
147
|
+
echo "❌ Error: Hook script path contains invalid characters"
|
|
148
|
+
echo " Path must not contain: ; | & \` \$ ( ) { } < >"
|
|
149
|
+
exit 1
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# Track if we need to invoke with bash explicitly
|
|
153
|
+
HOOK_IS_EXECUTABLE=true
|
|
154
|
+
if [ ! -x "$HOOK_SCRIPT" ]; then
|
|
155
|
+
echo "⚠️ Warning: Hook script is not executable. Attempting to run with bash..."
|
|
156
|
+
HOOK_IS_EXECUTABLE=false
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
if [ ! -f "$TEST_INPUT" ]; then
|
|
160
|
+
echo "❌ Error: Test input not found: $TEST_INPUT"
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# Security: Validate test input path doesn't contain dangerous characters
|
|
165
|
+
# This mirrors the HOOK_SCRIPT validation for defense-in-depth
|
|
166
|
+
if [[ "$TEST_INPUT" =~ [\;\|\&\`\$\(\)\{\}\<\>] ]]; then
|
|
167
|
+
echo "❌ Error: Test input path contains invalid characters"
|
|
168
|
+
echo " Path must not contain: ; | & \` \$ ( ) { } < >"
|
|
169
|
+
exit 1
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Validate test input JSON (with timeout for defensive consistency)
|
|
173
|
+
if ! timeout 5 jq empty "$TEST_INPUT" 2>/dev/null; then
|
|
174
|
+
echo "❌ Error: Test input is not valid JSON"
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
echo "🧪 Testing hook: $HOOK_SCRIPT"
|
|
179
|
+
echo "📥 Input: $TEST_INPUT"
|
|
180
|
+
echo ""
|
|
181
|
+
|
|
182
|
+
if [ "$VERBOSE" = true ]; then
|
|
183
|
+
echo "Input JSON:"
|
|
184
|
+
jq . "$TEST_INPUT"
|
|
185
|
+
echo ""
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# Set up environment
|
|
189
|
+
export CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-/tmp/test-project}"
|
|
190
|
+
export CLAUDE_PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(pwd)}"
|
|
191
|
+
export CLAUDE_ENV_FILE="${CLAUDE_ENV_FILE:-/tmp/test-env-$$}"
|
|
192
|
+
|
|
193
|
+
if [ "$VERBOSE" = true ]; then
|
|
194
|
+
echo "Environment:"
|
|
195
|
+
echo " CLAUDE_PROJECT_DIR=$CLAUDE_PROJECT_DIR"
|
|
196
|
+
echo " CLAUDE_PLUGIN_ROOT=$CLAUDE_PLUGIN_ROOT"
|
|
197
|
+
echo " CLAUDE_ENV_FILE=$CLAUDE_ENV_FILE"
|
|
198
|
+
echo ""
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
# Run the hook
|
|
202
|
+
echo "▶️ Running hook (timeout: ${TIMEOUT}s)..."
|
|
203
|
+
echo ""
|
|
204
|
+
|
|
205
|
+
start_time=$(date +%s)
|
|
206
|
+
|
|
207
|
+
set +e
|
|
208
|
+
# Use proper argument passing to prevent command injection
|
|
209
|
+
# Arguments are passed safely via bash -c's positional parameters
|
|
210
|
+
if [ "$HOOK_IS_EXECUTABLE" = true ]; then
|
|
211
|
+
output=$(timeout "$TIMEOUT" bash -c 'cat "$1" | "$2"' -- "$TEST_INPUT" "$HOOK_SCRIPT" 2>&1)
|
|
212
|
+
else
|
|
213
|
+
output=$(timeout "$TIMEOUT" bash -c 'cat "$1" | bash "$2"' -- "$TEST_INPUT" "$HOOK_SCRIPT" 2>&1)
|
|
214
|
+
fi
|
|
215
|
+
exit_code=$?
|
|
216
|
+
set -e
|
|
217
|
+
|
|
218
|
+
end_time=$(date +%s)
|
|
219
|
+
duration=$((end_time - start_time))
|
|
220
|
+
|
|
221
|
+
# Analyze results
|
|
222
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
223
|
+
echo "Results:"
|
|
224
|
+
echo ""
|
|
225
|
+
echo "Exit Code: $exit_code"
|
|
226
|
+
echo "Duration: ${duration}s"
|
|
227
|
+
echo ""
|
|
228
|
+
|
|
229
|
+
case $exit_code in
|
|
230
|
+
0)
|
|
231
|
+
echo "✅ Hook approved/succeeded"
|
|
232
|
+
;;
|
|
233
|
+
2)
|
|
234
|
+
echo "🚫 Hook blocked/denied"
|
|
235
|
+
;;
|
|
236
|
+
124)
|
|
237
|
+
echo "⏱️ Hook timed out after ${TIMEOUT}s"
|
|
238
|
+
;;
|
|
239
|
+
*)
|
|
240
|
+
echo "⚠️ Hook returned unexpected exit code: $exit_code"
|
|
241
|
+
;;
|
|
242
|
+
esac
|
|
243
|
+
|
|
244
|
+
echo ""
|
|
245
|
+
echo "Output:"
|
|
246
|
+
if [ -n "$output" ]; then
|
|
247
|
+
echo "$output"
|
|
248
|
+
echo ""
|
|
249
|
+
|
|
250
|
+
# Try to parse as JSON
|
|
251
|
+
if echo "$output" | jq empty 2>/dev/null; then
|
|
252
|
+
echo "Parsed JSON output:"
|
|
253
|
+
echo "$output" | jq .
|
|
254
|
+
fi
|
|
255
|
+
else
|
|
256
|
+
echo "(no output)"
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
# Check for environment file
|
|
260
|
+
if [ -f "$CLAUDE_ENV_FILE" ]; then
|
|
261
|
+
echo ""
|
|
262
|
+
echo "Environment file created:"
|
|
263
|
+
cat "$CLAUDE_ENV_FILE"
|
|
264
|
+
rm -f "$CLAUDE_ENV_FILE"
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
echo ""
|
|
268
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
269
|
+
|
|
270
|
+
if [ $exit_code -eq 0 ] || [ $exit_code -eq 2 ]; then
|
|
271
|
+
echo "✅ Test completed successfully"
|
|
272
|
+
exit 0
|
|
273
|
+
else
|
|
274
|
+
echo "❌ Test failed"
|
|
275
|
+
exit 1
|
|
276
|
+
fi
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Hook Schema Validator
|
|
3
|
+
# Validates hooks.json structure and checks for common issues
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
# Usage
|
|
8
|
+
if [ $# -eq 0 ]; then
|
|
9
|
+
echo "Usage: $0 <path/to/hooks.json>"
|
|
10
|
+
echo ""
|
|
11
|
+
echo "Validates hook configuration file for:"
|
|
12
|
+
echo " - Valid JSON syntax"
|
|
13
|
+
echo " - Required fields"
|
|
14
|
+
echo " - Hook type validity"
|
|
15
|
+
echo " - Matcher patterns"
|
|
16
|
+
echo " - Timeout ranges"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
HOOKS_FILE="$1"
|
|
21
|
+
|
|
22
|
+
if [ ! -f "$HOOKS_FILE" ]; then
|
|
23
|
+
echo "❌ Error: File not found: $HOOKS_FILE"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
echo "🔍 Validating hooks configuration: $HOOKS_FILE"
|
|
28
|
+
echo ""
|
|
29
|
+
|
|
30
|
+
# Check 1: Valid JSON
|
|
31
|
+
echo "Checking JSON syntax..."
|
|
32
|
+
if ! jq empty "$HOOKS_FILE" 2>/dev/null; then
|
|
33
|
+
echo "❌ Invalid JSON syntax"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
echo "✅ Valid JSON"
|
|
37
|
+
|
|
38
|
+
# Check 2: Root structure
|
|
39
|
+
echo ""
|
|
40
|
+
echo "Checking root structure..."
|
|
41
|
+
VALID_EVENTS=("PreToolUse" "PermissionRequest" "PostToolUse" "UserPromptSubmit" "Stop" "SubagentStop" "SessionStart" "SessionEnd" "PreCompact" "Notification")
|
|
42
|
+
|
|
43
|
+
for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|
44
|
+
found=false
|
|
45
|
+
for valid_event in "${VALID_EVENTS[@]}"; do
|
|
46
|
+
if [ "$event" = "$valid_event" ]; then
|
|
47
|
+
found=true
|
|
48
|
+
break
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
if [ "$found" = false ]; then
|
|
53
|
+
echo "⚠️ Unknown event type: $event"
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
echo "✅ Root structure valid"
|
|
57
|
+
|
|
58
|
+
# Check 3: Validate each hook
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Validating individual hooks..."
|
|
61
|
+
|
|
62
|
+
error_count=0
|
|
63
|
+
warning_count=0
|
|
64
|
+
|
|
65
|
+
for event in $(jq -r 'keys[]' "$HOOKS_FILE"); do
|
|
66
|
+
hook_count=$(jq -r ".\"$event\" | length" "$HOOKS_FILE")
|
|
67
|
+
|
|
68
|
+
for ((i=0; i<hook_count; i++)); do
|
|
69
|
+
# Check matcher exists
|
|
70
|
+
matcher=$(jq -r ".\"$event\"[$i].matcher // empty" "$HOOKS_FILE")
|
|
71
|
+
if [ -z "$matcher" ]; then
|
|
72
|
+
echo "❌ ${event}[$i]: Missing 'matcher' field"
|
|
73
|
+
((error_count++))
|
|
74
|
+
continue
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Check hooks array exists
|
|
78
|
+
hooks=$(jq -r ".\"$event\"[$i].hooks // empty" "$HOOKS_FILE")
|
|
79
|
+
if [ -z "$hooks" ] || [ "$hooks" = "null" ]; then
|
|
80
|
+
echo "❌ ${event}[$i]: Missing 'hooks' array"
|
|
81
|
+
((error_count++))
|
|
82
|
+
continue
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# Validate each hook in the array
|
|
86
|
+
hook_array_count=$(jq -r ".\"$event\"[$i].hooks | length" "$HOOKS_FILE")
|
|
87
|
+
|
|
88
|
+
for ((j=0; j<hook_array_count; j++)); do
|
|
89
|
+
hook_type=$(jq -r ".\"$event\"[$i].hooks[$j].type // empty" "$HOOKS_FILE")
|
|
90
|
+
|
|
91
|
+
if [ -z "$hook_type" ]; then
|
|
92
|
+
echo "❌ ${event}[$i].hooks[$j]: Missing 'type' field"
|
|
93
|
+
((error_count++))
|
|
94
|
+
continue
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
if [ "$hook_type" != "command" ] && [ "$hook_type" != "prompt" ]; then
|
|
98
|
+
echo "❌ ${event}[$i].hooks[$j]: Invalid type '$hook_type' (must be 'command' or 'prompt')"
|
|
99
|
+
((error_count++))
|
|
100
|
+
continue
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Check type-specific fields
|
|
104
|
+
if [ "$hook_type" = "command" ]; then
|
|
105
|
+
command=$(jq -r ".\"$event\"[$i].hooks[$j].command // empty" "$HOOKS_FILE")
|
|
106
|
+
if [ -z "$command" ]; then
|
|
107
|
+
echo "❌ ${event}[$i].hooks[$j]: Command hooks must have 'command' field"
|
|
108
|
+
((error_count++))
|
|
109
|
+
else
|
|
110
|
+
# Check for hardcoded paths
|
|
111
|
+
if [[ "$command" == /* ]] && [[ "$command" != *'${CLAUDE_PLUGIN_ROOT}'* ]]; then
|
|
112
|
+
echo "⚠️ ${event}[$i].hooks[$j]: Hardcoded absolute path detected. Consider using \${CLAUDE_PLUGIN_ROOT}"
|
|
113
|
+
((warning_count++))
|
|
114
|
+
fi
|
|
115
|
+
fi
|
|
116
|
+
elif [ "$hook_type" = "prompt" ]; then
|
|
117
|
+
prompt=$(jq -r ".\"$event\"[$i].hooks[$j].prompt // empty" "$HOOKS_FILE")
|
|
118
|
+
if [ -z "$prompt" ]; then
|
|
119
|
+
echo "❌ ${event}[$i].hooks[$j]: Prompt hooks must have 'prompt' field"
|
|
120
|
+
((error_count++))
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Check if prompt-based hooks are used on supported events
|
|
124
|
+
if [ "$event" != "Stop" ] && [ "$event" != "SubagentStop" ] && [ "$event" != "UserPromptSubmit" ] && [ "$event" != "PreToolUse" ]; then
|
|
125
|
+
echo "⚠️ ${event}[$i].hooks[$j]: Prompt hooks may not be fully supported on $event (best on Stop, SubagentStop, UserPromptSubmit, PreToolUse)"
|
|
126
|
+
((warning_count++))
|
|
127
|
+
fi
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Check timeout
|
|
131
|
+
timeout=$(jq -r ".\"$event\"[$i].hooks[$j].timeout // empty" "$HOOKS_FILE")
|
|
132
|
+
if [ -n "$timeout" ] && [ "$timeout" != "null" ]; then
|
|
133
|
+
if ! [[ "$timeout" =~ ^[0-9]+$ ]]; then
|
|
134
|
+
echo "❌ ${event}[$i].hooks[$j]: Timeout must be a number"
|
|
135
|
+
((error_count++))
|
|
136
|
+
elif [ "$timeout" -gt 600 ]; then
|
|
137
|
+
echo "⚠️ ${event}[$i].hooks[$j]: Timeout $timeout seconds is very high (max 600s)"
|
|
138
|
+
((warning_count++))
|
|
139
|
+
elif [ "$timeout" -lt 5 ]; then
|
|
140
|
+
echo "⚠️ ${event}[$i].hooks[$j]: Timeout $timeout seconds is very low"
|
|
141
|
+
((warning_count++))
|
|
142
|
+
fi
|
|
143
|
+
fi
|
|
144
|
+
done
|
|
145
|
+
done
|
|
146
|
+
done
|
|
147
|
+
|
|
148
|
+
echo ""
|
|
149
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
150
|
+
if [ $error_count -eq 0 ] && [ $warning_count -eq 0 ]; then
|
|
151
|
+
echo "✅ All checks passed!"
|
|
152
|
+
exit 0
|
|
153
|
+
elif [ $error_count -eq 0 ]; then
|
|
154
|
+
echo "⚠️ Validation passed with $warning_count warning(s)"
|
|
155
|
+
exit 0
|
|
156
|
+
else
|
|
157
|
+
echo "❌ Validation failed with $error_count error(s) and $warning_count warning(s)"
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|