codebyplan 1.5.1 → 1.8.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/dist/cli.js +4462 -748
- package/package.json +5 -1
- package/templates/.gitkeep +0 -0
- package/templates/README.md +20 -0
- package/templates/agents/cbp-cc-executor.md +213 -0
- package/templates/agents/cbp-database-agent.md +229 -0
- package/templates/agents/cbp-improve-claude.md +245 -0
- package/templates/agents/cbp-improve-round.md +284 -0
- package/templates/agents/cbp-mechanical-edits.md +111 -0
- package/templates/agents/cbp-research.md +282 -0
- package/templates/agents/cbp-round-executor.md +604 -0
- package/templates/agents/cbp-security-agent.md +134 -0
- package/templates/agents/cbp-task-check.md +213 -0
- package/templates/agents/cbp-task-planner.md +582 -0
- package/templates/agents/cbp-test-e2e-agent.md +363 -0
- package/templates/agents/cbp-testing-qa-agent.md +400 -0
- package/templates/context/mcp-docs.md +139 -0
- package/templates/hooks/README.md +236 -0
- package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
- package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
- package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
- package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
- package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
- package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
- package/templates/hooks/cbp-notify.sh +68 -0
- package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
- package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
- package/templates/hooks/cbp-statusline.sh +347 -0
- package/templates/hooks/cbp-subagent-statusline.sh +182 -0
- package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
- package/templates/hooks/cbp-test-hooks.sh +320 -0
- package/templates/hooks/hooks.json +85 -0
- package/templates/hooks/validate-context-usage.sh +59 -0
- package/templates/hooks/validate-git-commit.sh +78 -0
- package/templates/hooks/validate-git-stash-deny.sh +32 -0
- package/templates/hooks/validate-structure-lengths.sh +57 -0
- package/templates/hooks/validate-structure-lib.sh +104 -0
- package/templates/hooks/validate-structure-patterns.sh +54 -0
- package/templates/hooks/validate-structure-scope.sh +33 -0
- package/templates/hooks/validate-structure-smoke.sh +95 -0
- package/templates/hooks/validate-structure-templates.sh +34 -0
- package/templates/hooks/validate-structure.sh +69 -0
- package/templates/rules/.gitkeep +0 -0
- package/templates/rules/README.md +47 -0
- package/templates/rules/context-file-loading.md +52 -0
- package/templates/rules/scope-vocabulary.md +64 -0
- package/templates/rules/todo-backend.md +109 -0
- package/templates/settings.project.base.json +55 -0
- package/templates/settings.user.base.json +25 -0
- package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
- package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
- package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
- package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
- package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
- package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
- package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
- package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
- package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
- package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
- package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
- package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
- package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
- package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
- package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
- package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
- package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
- package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
- package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
- package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
- package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
- package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
- package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
- package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
- package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
- package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
- package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
- package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
- package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
- package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
- package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
- package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
- package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
- package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
- package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
- package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
- package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
- package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
- package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
- package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
- package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
- package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
- package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
- package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
- package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
- package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
- package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
- package/templates/skills/cbp-checkpoint-create/SKILL.md +287 -0
- package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
- package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
- package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
- package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
- package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
- package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
- package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
- package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
- package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
- package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
- package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
- package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
- package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
- package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
- package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
- package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
- package/templates/skills/cbp-git-commit/SKILL.md +278 -0
- package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
- package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
- package/templates/skills/cbp-merge-main/SKILL.md +228 -0
- package/templates/skills/cbp-round-check/SKILL.md +104 -0
- package/templates/skills/cbp-round-end/SKILL.md +183 -0
- package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
- package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
- package/templates/skills/cbp-round-execute/SKILL.md +211 -0
- package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
- package/templates/skills/cbp-round-input/SKILL.md +165 -0
- package/templates/skills/cbp-round-start/SKILL.md +222 -0
- package/templates/skills/cbp-round-update/SKILL.md +163 -0
- package/templates/skills/cbp-session-end/SKILL.md +187 -0
- package/templates/skills/cbp-session-start/SKILL.md +155 -0
- package/templates/skills/cbp-ship/SKILL.md +332 -0
- package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
- package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
- package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
- package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
- package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
- package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
- package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
- package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
- package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
- package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
- package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
- package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
- package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
- package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
- package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
- package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
- package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
- package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
- package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
- package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
- package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
- package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
- package/templates/skills/cbp-ship/reference/versioning.md +116 -0
- package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
- package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
- package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
- package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
- package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
- package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
- package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
- package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
- package/templates/skills/cbp-ship/templates/eas.json +66 -0
- package/templates/skills/cbp-ship/templates/railway.toml +15 -0
- package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
- package/templates/skills/cbp-ship/templates/vercel.json +19 -0
- package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
- package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
- package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
- package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
- package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
- package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
- package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
- package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
- package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
- package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
- package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
- package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
- package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
- package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
- package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
- package/templates/skills/cbp-ship-main/SKILL.md +65 -0
- package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
- package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
- package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
- package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
- package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
- package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
- package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
- package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
- package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
- package/templates/skills/cbp-task-check/SKILL.md +166 -0
- package/templates/skills/cbp-task-complete/SKILL.md +206 -0
- package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
- package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
- package/templates/skills/cbp-task-create/SKILL.md +167 -0
- package/templates/skills/cbp-task-start/SKILL.md +239 -0
- package/templates/skills/cbp-task-testing/SKILL.md +277 -0
- package/templates/skills/cbp-todo/SKILL.md +97 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @hook: NOT-A-HOOK (test suite for plugin hooks; invoked by cbp-auto-test-hooks.sh)
|
|
3
|
+
# Purpose: Test suite for plugin's shipped hooks. Invoked by cbp-auto-test-hooks.sh whenever a
|
|
4
|
+
# plugin hook file is edited. Not a PreToolUse/PostToolUse/Notification hook itself —
|
|
5
|
+
# do NOT register in hooks.json hooks[].
|
|
6
|
+
# Run manually: bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-test-hooks.sh
|
|
7
|
+
# Run by: ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-auto-test-hooks.sh (PostToolUse Edit|Write)
|
|
8
|
+
#
|
|
9
|
+
# Exit 0 = all tests pass, Exit 1 = some tests failed
|
|
10
|
+
|
|
11
|
+
# Don't use set -e because ((VAR++)) returns 1 when VAR=0
|
|
12
|
+
|
|
13
|
+
HOOKS_DIR="$(dirname "$0")"
|
|
14
|
+
REPO_ROOT="${CLAUDE_PROJECT_DIR:-}"
|
|
15
|
+
PASSED=0
|
|
16
|
+
FAILED=0
|
|
17
|
+
|
|
18
|
+
# Colors for output
|
|
19
|
+
RED='\033[0;31m'
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
NC='\033[0m' # No Color
|
|
22
|
+
|
|
23
|
+
test_result() {
|
|
24
|
+
local name="$1"
|
|
25
|
+
local expected="$2"
|
|
26
|
+
local actual="$3"
|
|
27
|
+
|
|
28
|
+
if [ "$expected" = "$actual" ]; then
|
|
29
|
+
echo -e "${GREEN}PASS${NC}: $name"
|
|
30
|
+
PASSED=$((PASSED + 1))
|
|
31
|
+
else
|
|
32
|
+
echo -e "${RED}FAIL${NC}: $name (expected: $expected, got: $actual)"
|
|
33
|
+
FAILED=$((FAILED + 1))
|
|
34
|
+
fi
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
echo "=== PLUGIN HOOK TEST SUITE ==="
|
|
38
|
+
echo ""
|
|
39
|
+
|
|
40
|
+
# ===== HOOK STRUCTURE VALIDATION =====
|
|
41
|
+
echo "## Hook Structure Validation"
|
|
42
|
+
|
|
43
|
+
# Check all hooks have required header comments (for documentation)
|
|
44
|
+
for hook_file in "$HOOKS_DIR"/*.sh; do
|
|
45
|
+
hook_name=$(basename "$hook_file" .sh)
|
|
46
|
+
|
|
47
|
+
# Skip utility scripts (recursion-guard) and statusline (different header format)
|
|
48
|
+
case "$hook_name" in
|
|
49
|
+
cbp-test-hooks|cbp-auto-test-hooks)
|
|
50
|
+
continue
|
|
51
|
+
;;
|
|
52
|
+
cbp-statusline)
|
|
53
|
+
# StatusLine script — not a hook, uses different header format
|
|
54
|
+
if grep -q '^# Claude Code Status Line' "$hook_file"; then
|
|
55
|
+
test_result "$hook_name has header comments" "passed" "passed"
|
|
56
|
+
else
|
|
57
|
+
test_result "$hook_name has header comments" "passed" "missing"
|
|
58
|
+
fi
|
|
59
|
+
continue
|
|
60
|
+
;;
|
|
61
|
+
esac
|
|
62
|
+
|
|
63
|
+
# Check for header comments (required for documentation generation).
|
|
64
|
+
# Accept either marker convention used across the plugin's hooks:
|
|
65
|
+
# - "# Hook:" + "# Purpose:" (used by notify, auto-test-hooks, etc.)
|
|
66
|
+
# - "# @event:" + a description line (used by maestro-yaml-validate, etc.)
|
|
67
|
+
if (grep -q '^# Hook:' "$hook_file" && grep -q '^# Purpose:' "$hook_file") \
|
|
68
|
+
|| grep -q '^# @event:' "$hook_file"; then
|
|
69
|
+
test_result "$hook_name has header comments" "passed" "passed"
|
|
70
|
+
else
|
|
71
|
+
test_result "$hook_name has header comments" "passed" "missing"
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
|
|
75
|
+
echo ""
|
|
76
|
+
|
|
77
|
+
# ===== FUNCTIONAL SMOKE TESTS =====
|
|
78
|
+
echo "## Functional Smoke Tests"
|
|
79
|
+
|
|
80
|
+
# cbp-notify.sh — graceful-degrade: exit 0 whether or not terminal-notifier is installed
|
|
81
|
+
ACTUAL_EXIT=$(echo '{"message":"test","cwd":"/tmp"}' | bash "$HOOKS_DIR/cbp-notify.sh" >/dev/null 2>&1; echo $?)
|
|
82
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
83
|
+
test_result "cbp-notify.sh graceful-degrade exits 0" "passed" "passed"
|
|
84
|
+
else
|
|
85
|
+
test_result "cbp-notify.sh graceful-degrade exits 0" "passed" "failed"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# cbp-lint-format-on-edit.sh — graceful-degrade: CLAUDE_PROJECT_DIR unset → exit 0
|
|
89
|
+
if [ ! -f "$HOOKS_DIR/cbp-lint-format-on-edit.sh" ]; then
|
|
90
|
+
test_result "cbp-lint-format-on-edit.sh present" "passed" "missing"
|
|
91
|
+
else
|
|
92
|
+
ACTUAL_EXIT=$(env -u CLAUDE_PROJECT_DIR bash "$HOOKS_DIR/cbp-lint-format-on-edit.sh" <<< '{"tool_input":{"file_path":"/tmp/dummy.ts"}}' >/dev/null 2>&1; echo $?)
|
|
93
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
94
|
+
test_result "cbp-lint-format-on-edit.sh graceful-degrade exits 0" "passed" "passed"
|
|
95
|
+
else
|
|
96
|
+
test_result "cbp-lint-format-on-edit.sh graceful-degrade exits 0" "passed" "failed"
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# cbp-test-coverage-gate.sh — fast-path: not a commit → exit 0
|
|
101
|
+
if [ ! -f "$HOOKS_DIR/cbp-test-coverage-gate.sh" ]; then
|
|
102
|
+
test_result "cbp-test-coverage-gate.sh present" "passed" "missing"
|
|
103
|
+
else
|
|
104
|
+
ACTUAL_EXIT=$(echo '{"tool_input":{"command":"git status"}}' | bash "$HOOKS_DIR/cbp-test-coverage-gate.sh" >/dev/null 2>&1; echo $?)
|
|
105
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
106
|
+
test_result "cbp-test-coverage-gate.sh fast-path exits 0" "passed" "passed"
|
|
107
|
+
else
|
|
108
|
+
test_result "cbp-test-coverage-gate.sh fast-path exits 0" "passed" "failed"
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# cbp-pre-commit-quality-gate.sh — fast-path: not a commit → exit 0
|
|
113
|
+
if [ ! -f "$HOOKS_DIR/cbp-pre-commit-quality-gate.sh" ]; then
|
|
114
|
+
test_result "cbp-pre-commit-quality-gate.sh present" "passed" "missing"
|
|
115
|
+
else
|
|
116
|
+
ACTUAL_EXIT=$(echo '{"tool_input":{"command":"git status"}}' | bash "$HOOKS_DIR/cbp-pre-commit-quality-gate.sh" >/dev/null 2>&1; echo $?)
|
|
117
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
118
|
+
test_result "cbp-pre-commit-quality-gate.sh fast-path exits 0" "passed" "passed"
|
|
119
|
+
else
|
|
120
|
+
test_result "cbp-pre-commit-quality-gate.sh fast-path exits 0" "passed" "failed"
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# cbp-maestro-yaml-validate.sh — fast-path: not maestro YAML → exit 0
|
|
125
|
+
if [ ! -f "$HOOKS_DIR/cbp-maestro-yaml-validate.sh" ]; then
|
|
126
|
+
test_result "cbp-maestro-yaml-validate.sh present" "passed" "missing"
|
|
127
|
+
else
|
|
128
|
+
ACTUAL_EXIT=$(echo '{"tool_input":{"file_path":"/tmp/foo.txt"}}' | bash "$HOOKS_DIR/cbp-maestro-yaml-validate.sh" >/dev/null 2>&1; echo $?)
|
|
129
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
130
|
+
test_result "cbp-maestro-yaml-validate.sh fast-path exits 0" "passed" "passed"
|
|
131
|
+
else
|
|
132
|
+
test_result "cbp-maestro-yaml-validate.sh fast-path exits 0" "passed" "failed"
|
|
133
|
+
fi
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# cbp-auto-test-hooks.sh — fast-path: not a hook file → exit 0
|
|
137
|
+
ACTUAL_EXIT=$(echo '{"tool_input":{"file_path":"/tmp/foo.txt"}}' | bash "$HOOKS_DIR/cbp-auto-test-hooks.sh" >/dev/null 2>&1; echo $?)
|
|
138
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
139
|
+
test_result "cbp-auto-test-hooks.sh fast-path exits 0" "passed" "passed"
|
|
140
|
+
else
|
|
141
|
+
test_result "cbp-auto-test-hooks.sh fast-path exits 0" "passed" "failed"
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
echo ""
|
|
145
|
+
|
|
146
|
+
# ===== NEW HOOK SMOKE TESTS =====
|
|
147
|
+
echo "## New Hook Smoke Tests (CHK-131)"
|
|
148
|
+
|
|
149
|
+
# --- validate-git-stash-deny.sh ---
|
|
150
|
+
|
|
151
|
+
# Existence + shebang + scope marker
|
|
152
|
+
if [ ! -f "$HOOKS_DIR/validate-git-stash-deny.sh" ]; then
|
|
153
|
+
test_result "validate-git-stash-deny.sh present" "passed" "missing"
|
|
154
|
+
else
|
|
155
|
+
test_result "validate-git-stash-deny.sh present" "passed" "passed"
|
|
156
|
+
|
|
157
|
+
FIRST_LINE=$(head -1 "$HOOKS_DIR/validate-git-stash-deny.sh")
|
|
158
|
+
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
159
|
+
test_result "validate-git-stash-deny.sh has shebang" "passed" "passed"
|
|
160
|
+
else
|
|
161
|
+
test_result "validate-git-stash-deny.sh has shebang" "passed" "missing"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
if grep -q '@scope: org-shared' "$HOOKS_DIR/validate-git-stash-deny.sh"; then
|
|
165
|
+
test_result "validate-git-stash-deny.sh has @scope: org-shared" "passed" "passed"
|
|
166
|
+
else
|
|
167
|
+
test_result "validate-git-stash-deny.sh has @scope: org-shared" "passed" "missing"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
FIXTURES_DIR="$HOOKS_DIR/__test-fixtures__/validate-git-stash-deny"
|
|
171
|
+
if [ -d "$FIXTURES_DIR" ]; then
|
|
172
|
+
# stash-pop.json — should be blocked (exit 2)
|
|
173
|
+
ACTUAL_EXIT=$(bash "$HOOKS_DIR/validate-git-stash-deny.sh" < "$FIXTURES_DIR/stash-pop.json" >/dev/null 2>&1; echo $?)
|
|
174
|
+
if [ "$ACTUAL_EXIT" = "2" ]; then
|
|
175
|
+
test_result "validate-git-stash-deny.sh blocks git stash pop (exit 2)" "passed" "passed"
|
|
176
|
+
else
|
|
177
|
+
test_result "validate-git-stash-deny.sh blocks git stash pop (exit 2)" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# stash-apply.json — should be blocked (exit 2)
|
|
181
|
+
ACTUAL_EXIT=$(bash "$HOOKS_DIR/validate-git-stash-deny.sh" < "$FIXTURES_DIR/stash-apply.json" >/dev/null 2>&1; echo $?)
|
|
182
|
+
if [ "$ACTUAL_EXIT" = "2" ]; then
|
|
183
|
+
test_result "validate-git-stash-deny.sh blocks git stash apply (exit 2)" "passed" "passed"
|
|
184
|
+
else
|
|
185
|
+
test_result "validate-git-stash-deny.sh blocks git stash apply (exit 2)" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# git-status.json — should be allowed (exit 0)
|
|
189
|
+
ACTUAL_EXIT=$(bash "$HOOKS_DIR/validate-git-stash-deny.sh" < "$FIXTURES_DIR/git-status.json" >/dev/null 2>&1; echo $?)
|
|
190
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
191
|
+
test_result "validate-git-stash-deny.sh allows git status (exit 0)" "passed" "passed"
|
|
192
|
+
else
|
|
193
|
+
test_result "validate-git-stash-deny.sh allows git status (exit 0)" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
# stash-with-c.json — git -C <path> stash — should be blocked (exit 2)
|
|
197
|
+
if [ -f "$FIXTURES_DIR/stash-with-c.json" ]; then
|
|
198
|
+
EXIT_CODE=$(bash "$HOOKS_DIR/validate-git-stash-deny.sh" < "$FIXTURES_DIR/stash-with-c.json" >/dev/null 2>&1; echo $?)
|
|
199
|
+
if [ "$EXIT_CODE" = "2" ]; then
|
|
200
|
+
test_result "validate-git-stash-deny.sh blocks git -C <path> stash (exit 2)" "passed" "passed"
|
|
201
|
+
else
|
|
202
|
+
test_result "validate-git-stash-deny.sh blocks git -C <path> stash (exit 2)" "passed" "failed (exit $EXIT_CODE)"
|
|
203
|
+
fi
|
|
204
|
+
fi
|
|
205
|
+
else
|
|
206
|
+
test_result "validate-git-stash-deny.sh fixtures dir present" "passed" "missing"
|
|
207
|
+
fi
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
# --- cbp-mcp-worktree-inject.sh ---
|
|
211
|
+
|
|
212
|
+
if [ ! -f "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" ]; then
|
|
213
|
+
test_result "cbp-mcp-worktree-inject.sh present" "passed" "missing"
|
|
214
|
+
else
|
|
215
|
+
test_result "cbp-mcp-worktree-inject.sh present" "passed" "passed"
|
|
216
|
+
|
|
217
|
+
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-mcp-worktree-inject.sh")
|
|
218
|
+
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
219
|
+
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "passed"
|
|
220
|
+
else
|
|
221
|
+
test_result "cbp-mcp-worktree-inject.sh has shebang" "passed" "missing"
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-mcp-worktree-inject.sh"; then
|
|
225
|
+
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "passed"
|
|
226
|
+
else
|
|
227
|
+
test_result "cbp-mcp-worktree-inject.sh has @scope: org-shared" "passed" "missing"
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
FIXTURES_DIR="$HOOKS_DIR/__test-fixtures__/cbp-mcp-worktree-inject"
|
|
231
|
+
if [ -d "$FIXTURES_DIR" ]; then
|
|
232
|
+
# already-has-id.json — expect exit 0 (passthrough)
|
|
233
|
+
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/already-has-id.json" >/dev/null 2>&1; echo $?)
|
|
234
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
235
|
+
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "passed"
|
|
236
|
+
else
|
|
237
|
+
test_result "cbp-mcp-worktree-inject.sh already-has-id exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
# missing-id-both-empty.json — resolvers return empty (in test env), expect exit 0
|
|
241
|
+
ACTUAL_EXIT=$(bash "$HOOKS_DIR/cbp-mcp-worktree-inject.sh" < "$FIXTURES_DIR/missing-id-both-empty.json" >/dev/null 2>&1; echo $?)
|
|
242
|
+
if [ "$ACTUAL_EXIT" = "0" ]; then
|
|
243
|
+
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "passed"
|
|
244
|
+
else
|
|
245
|
+
test_result "cbp-mcp-worktree-inject.sh missing-id passthrough exits 0" "passed" "failed (exit $ACTUAL_EXIT)"
|
|
246
|
+
fi
|
|
247
|
+
else
|
|
248
|
+
test_result "cbp-mcp-worktree-inject.sh fixtures dir present" "passed" "missing"
|
|
249
|
+
fi
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# --- cbp-mcp-round-sync.sh ---
|
|
253
|
+
|
|
254
|
+
if [ ! -f "$HOOKS_DIR/cbp-mcp-round-sync.sh" ]; then
|
|
255
|
+
test_result "cbp-mcp-round-sync.sh present" "passed" "missing"
|
|
256
|
+
else
|
|
257
|
+
test_result "cbp-mcp-round-sync.sh present" "passed" "passed"
|
|
258
|
+
|
|
259
|
+
FIRST_LINE=$(head -1 "$HOOKS_DIR/cbp-mcp-round-sync.sh")
|
|
260
|
+
if echo "$FIRST_LINE" | grep -q '^#!/'; then
|
|
261
|
+
test_result "cbp-mcp-round-sync.sh has shebang" "passed" "passed"
|
|
262
|
+
else
|
|
263
|
+
test_result "cbp-mcp-round-sync.sh has shebang" "passed" "missing"
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
if grep -q '@scope: org-shared' "$HOOKS_DIR/cbp-mcp-round-sync.sh"; then
|
|
267
|
+
test_result "cbp-mcp-round-sync.sh has @scope: org-shared" "passed" "passed"
|
|
268
|
+
else
|
|
269
|
+
test_result "cbp-mcp-round-sync.sh has @scope: org-shared" "passed" "missing"
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
FIXTURES_DIR="$HOOKS_DIR/__test-fixtures__/cbp-mcp-round-sync"
|
|
273
|
+
if [ -d "$FIXTURES_DIR" ]; then
|
|
274
|
+
# stale-file.json — DB has a.ts but git has nothing → expect removed_from_diff: true
|
|
275
|
+
DRY_OUTPUT=$(bash "$HOOKS_DIR/cbp-mcp-round-sync.sh" --dry-run < "$FIXTURES_DIR/stale-file.json" 2>/dev/null)
|
|
276
|
+
if echo "$DRY_OUTPUT" | jq -e '[.[] | select(.path == "a.ts" and .removed_from_diff == true)] | length > 0' >/dev/null 2>&1; then
|
|
277
|
+
test_result "cbp-mcp-round-sync.sh stale-file marks removed_from_diff=true" "passed" "passed"
|
|
278
|
+
else
|
|
279
|
+
test_result "cbp-mcp-round-sync.sh stale-file marks removed_from_diff=true" "passed" "failed"
|
|
280
|
+
fi
|
|
281
|
+
|
|
282
|
+
# reactivated-file.json — DB has a.ts with removed_from_diff=true.
|
|
283
|
+
# If a.ts is in the current git working tree, expect removed_from_diff=false.
|
|
284
|
+
# If a.ts is NOT in git (normal test env), it will remain removed_from_diff=true —
|
|
285
|
+
# this is expected behaviour; the real reactivation path requires a live working tree.
|
|
286
|
+
# Test: verify the hook runs without error and produces a valid JSON array.
|
|
287
|
+
DRY_OUTPUT=$(bash "$HOOKS_DIR/cbp-mcp-round-sync.sh" --dry-run < "$FIXTURES_DIR/reactivated-file.json" 2>/dev/null)
|
|
288
|
+
if echo "$DRY_OUTPUT" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
|
289
|
+
test_result "cbp-mcp-round-sync.sh reactivated-file produces valid JSON array" "passed" "passed"
|
|
290
|
+
else
|
|
291
|
+
test_result "cbp-mcp-round-sync.sh reactivated-file produces valid JSON array" "passed" "failed"
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# new-file.json — --dry-run mode produces a valid JSON array (no API call)
|
|
295
|
+
DRY_OUTPUT=$(bash "$HOOKS_DIR/cbp-mcp-round-sync.sh" --dry-run < "$FIXTURES_DIR/new-file.json" 2>/dev/null)
|
|
296
|
+
if echo "$DRY_OUTPUT" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
|
297
|
+
test_result "cbp-mcp-round-sync.sh --dry-run on new-file produces valid JSON array" "passed" "passed"
|
|
298
|
+
else
|
|
299
|
+
test_result "cbp-mcp-round-sync.sh --dry-run on new-file produces valid JSON array" "passed" "failed"
|
|
300
|
+
fi
|
|
301
|
+
else
|
|
302
|
+
test_result "cbp-mcp-round-sync.sh fixtures dir present" "passed" "missing"
|
|
303
|
+
fi
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
echo ""
|
|
307
|
+
|
|
308
|
+
# ===== SUMMARY =====
|
|
309
|
+
echo "=== TEST SUMMARY ==="
|
|
310
|
+
echo -e "Passed: ${GREEN}$PASSED${NC}"
|
|
311
|
+
echo -e "Failed: ${RED}$FAILED${NC}"
|
|
312
|
+
echo ""
|
|
313
|
+
|
|
314
|
+
if [ "$FAILED" -gt 0 ]; then
|
|
315
|
+
echo -e "${RED}TESTS FAILED${NC}"
|
|
316
|
+
exit 1
|
|
317
|
+
else
|
|
318
|
+
echo -e "${GREEN}ALL TESTS PASSED${NC}"
|
|
319
|
+
exit 0
|
|
320
|
+
fi
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "Edit|Write|MultiEdit",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-maestro-yaml-validate.sh"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"matcher": "Bash",
|
|
15
|
+
"hooks": [
|
|
16
|
+
{
|
|
17
|
+
"type": "command",
|
|
18
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/validate-git-stash-deny.sh"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-test-coverage-gate.sh"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "command",
|
|
26
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-pre-commit-quality-gate.sh"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"matcher": "mcp__codebyplan__(update_task|complete_task|update_checkpoint|create_checkpoint|create_task)",
|
|
32
|
+
"hooks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-migration-guard.sh"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"matcher": "mcp__codebyplan__(update_task|complete_task|complete_round|update_checkpoint)",
|
|
41
|
+
"hooks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-worktree-inject.sh"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"PostToolUse": [
|
|
50
|
+
{
|
|
51
|
+
"matcher": "Edit|Write",
|
|
52
|
+
"hooks": [
|
|
53
|
+
{
|
|
54
|
+
"type": "command",
|
|
55
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-auto-test-hooks.sh"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "command",
|
|
59
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-lint-format-on-edit.sh"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"matcher": "mcp__codebyplan__complete_round",
|
|
65
|
+
"hooks": [
|
|
66
|
+
{
|
|
67
|
+
"type": "command",
|
|
68
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-mcp-round-sync.sh"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"Notification": [
|
|
74
|
+
{
|
|
75
|
+
"matcher": "*",
|
|
76
|
+
"hooks": [
|
|
77
|
+
{
|
|
78
|
+
"type": "command",
|
|
79
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/cbp-notify.sh"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# Hook Helper: Context file usage validation for validate-structure.sh
|
|
4
|
+
# Purpose: Ensure context files are referenced by at least one agent or skill
|
|
5
|
+
# Sourced by validate-structure.sh - not run directly
|
|
6
|
+
#
|
|
7
|
+
# Expects: $REL_PATH, $FILE_PATH, $REPO_ROOT, warn()
|
|
8
|
+
|
|
9
|
+
# Only check .claude/context/ files
|
|
10
|
+
if ! echo "$REL_PATH" | grep -qE '^/\.claude/context/.*\.md$'; then
|
|
11
|
+
return 0 2>/dev/null || true
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
# Get the relative path without leading slash for grep
|
|
15
|
+
CONTEXT_REL="${REL_PATH#/}"
|
|
16
|
+
|
|
17
|
+
# Also build shorter path variants for matching
|
|
18
|
+
# e.g., ".claude/context/testing/unit.md" and "context/testing/unit.md"
|
|
19
|
+
CONTEXT_SHORT="${CONTEXT_REL#.claude/}"
|
|
20
|
+
|
|
21
|
+
# Search agents and skills for any reference to this context file
|
|
22
|
+
AGENTS_DIR="$REPO_ROOT/.claude/agents"
|
|
23
|
+
SKILLS_DIR="$REPO_ROOT/.claude/skills"
|
|
24
|
+
|
|
25
|
+
FOUND=0
|
|
26
|
+
|
|
27
|
+
# Check agents
|
|
28
|
+
if [ -d "$AGENTS_DIR" ]; then
|
|
29
|
+
if grep -rqF -e "$CONTEXT_REL" -e "$CONTEXT_SHORT" "$AGENTS_DIR" 2>/dev/null; then
|
|
30
|
+
FOUND=1
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Check skills
|
|
35
|
+
if [ "$FOUND" -eq 0 ] && [ -d "$SKILLS_DIR" ]; then
|
|
36
|
+
if grep -rqF -e "$CONTEXT_REL" -e "$CONTEXT_SHORT" "$SKILLS_DIR" 2>/dev/null; then
|
|
37
|
+
FOUND=1
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check authoring skills (scope:org-shared content shipped via the codebyplan npm package's claude subcommand)
|
|
42
|
+
PLUGIN_SKILLS_DIR="$REPO_ROOT/packages/codebyplan-package/templates/skills"
|
|
43
|
+
if [ "$FOUND" -eq 0 ] && [ -d "$PLUGIN_SKILLS_DIR" ]; then
|
|
44
|
+
if grep -rqF -e "$CONTEXT_REL" -e "$CONTEXT_SHORT" "$PLUGIN_SKILLS_DIR" 2>/dev/null; then
|
|
45
|
+
FOUND=1
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Check authoring agents
|
|
50
|
+
PLUGIN_AGENTS_DIR="$REPO_ROOT/packages/codebyplan-package/templates/agents"
|
|
51
|
+
if [ "$FOUND" -eq 0 ] && [ -d "$PLUGIN_AGENTS_DIR" ]; then
|
|
52
|
+
if grep -rqF -e "$CONTEXT_REL" -e "$CONTEXT_SHORT" "$PLUGIN_AGENTS_DIR" 2>/dev/null; then
|
|
53
|
+
FOUND=1
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [ "$FOUND" -eq 0 ]; then
|
|
58
|
+
warn "Context file not referenced by any agent or skill. Context files must be used by agents/skills — move informational docs to .claude/docs/ instead."
|
|
59
|
+
fi
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# @hook: PreToolUse Bash
|
|
4
|
+
# Hook: PreToolUse for Bash (git commit commands)
|
|
5
|
+
# Purpose: Prevent Claude attribution in git commits
|
|
6
|
+
# Exit 0 = allow, Exit 2 = block (stderr sent to Claude)
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
echo "[HOOK START] validate-git-commit"
|
|
11
|
+
|
|
12
|
+
# Read JSON input from stdin
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
|
|
15
|
+
# Extract command from tool input
|
|
16
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
|
|
17
|
+
|
|
18
|
+
if [ -z "$COMMAND" ]; then
|
|
19
|
+
echo "[HOOK END] validate-git-commit (no command)"
|
|
20
|
+
exit 0 # No command, allow
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Only check git commit commands
|
|
24
|
+
if ! echo "$COMMAND" | grep -qE 'git\s+commit'; then
|
|
25
|
+
echo "[HOOK END] validate-git-commit (not git commit)"
|
|
26
|
+
exit 0 # Not a git commit, allow
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Function to block with message
|
|
30
|
+
block() {
|
|
31
|
+
echo "[HOOK END] validate-git-commit (BLOCKED)"
|
|
32
|
+
echo "$1" >&2
|
|
33
|
+
exit 2
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Check for Claude attribution patterns
|
|
37
|
+
# Case-insensitive check for various patterns
|
|
38
|
+
|
|
39
|
+
# Check for "Claude" mentions (but allow CLAUDE.md files and .claude/ folder paths)
|
|
40
|
+
# First, remove CLAUDE.md filenames and .claude(/path|word-end) — BSD-compatible word-boundary via [[:>:]]
|
|
41
|
+
# Word-boundary allows ".claude folder" / ".claude rules" / ".claude/" all as legit folder references
|
|
42
|
+
COMMAND_WITHOUT_FILES=$(echo "$COMMAND" \
|
|
43
|
+
| sed -E 's/CLAUDE(\.[a-z]+)?\.md//gi' \
|
|
44
|
+
| sed -E 's/\.claude(\/[a-zA-Z0-9_./-]*|[[:>:]])//gi' \
|
|
45
|
+
| sed -E 's/\$\{CLAUDE[A-Z_]*\}//g' \
|
|
46
|
+
| sed -E 's/claude-plugin[a-zA-Z0-9_./-]*//gi' \
|
|
47
|
+
| sed -E 's/codebyplan-claude[a-zA-Z0-9_./-]*//gi' \
|
|
48
|
+
| sed -E 's/@codebyplan\/claude[a-zA-Z0-9_./-]*//gi')
|
|
49
|
+
if echo "$COMMAND_WITHOUT_FILES" | grep -qiE 'claude|anthropic'; then
|
|
50
|
+
block "BLOCKED: Git commit contains Claude/Anthropic attribution. Remove any mention of Claude from the commit message. Author should only be: midevyou <midevyosauhing@gmail.com>"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Check for "Generated with" patterns
|
|
54
|
+
if echo "$COMMAND" | grep -qiE 'generated\s+(with|by)|auto-?generated'; then
|
|
55
|
+
block "BLOCKED: Git commit contains 'generated with/by' text. Remove this attribution from the commit message."
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Check for co-author patterns
|
|
59
|
+
if echo "$COMMAND" | grep -qiE 'co-?authored-?by'; then
|
|
60
|
+
block "BLOCKED: Git commit contains Co-Authored-By. Do not add co-author lines. Only author: midevyou <midevyosauhing@gmail.com>"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Check for AI/bot emoji markers
|
|
64
|
+
if echo "$COMMAND" | grep -qE '🤖|🧠|✨|🔮'; then
|
|
65
|
+
block "BLOCKED: Git commit contains emoji markers (🤖, 🧠, ✨, 🔮). Remove these from the commit message."
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# Check for --author flag overriding
|
|
69
|
+
if echo "$COMMAND" | grep -qE '\-\-author'; then
|
|
70
|
+
# Allow only if it's the correct author
|
|
71
|
+
if ! echo "$COMMAND" | grep -qE '\-\-author.*midevyou'; then
|
|
72
|
+
block "BLOCKED: Git commit has custom --author. Only allowed author: midevyou <midevyosauhing@gmail.com>"
|
|
73
|
+
fi
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# All checks passed
|
|
77
|
+
echo "[HOOK END] validate-git-commit (passed)"
|
|
78
|
+
exit 0
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# Hook: PreToolUse Bash
|
|
4
|
+
# Purpose: Deny any `git stash` command. Git stash is banned per the
|
|
5
|
+
# feedback_no-git-stash auto-memory entry. Alternatives:
|
|
6
|
+
# - View uncommitted changes: git diff <ref>
|
|
7
|
+
# - View a file at a commit: git show <ref>:<path>
|
|
8
|
+
# - Isolate work: git worktree add <path> <branch>
|
|
9
|
+
# Exit 0 = allow, Exit 2 = block (stderr message returned to Claude)
|
|
10
|
+
|
|
11
|
+
INPUT=$(cat)
|
|
12
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
13
|
+
|
|
14
|
+
# Only intercept Bash tool calls
|
|
15
|
+
[ "$TOOL_NAME" = "Bash" ] || exit 0
|
|
16
|
+
|
|
17
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
18
|
+
|
|
19
|
+
[ -z "$COMMAND" ] && exit 0
|
|
20
|
+
|
|
21
|
+
# Block any `git stash` invocation (stash, stash pop, stash apply, stash list, etc.)
|
|
22
|
+
# Regex permits zero or more -X <arg> global option groups between `git` and `stash`
|
|
23
|
+
# (e.g. git -C <path> stash, git -c key=val stash).
|
|
24
|
+
if echo "$COMMAND" | grep -qE '(^|[[:space:]])git(\s+-[A-Za-z]\s+\S+)*\s+stash([[:space:]]|$)'; then
|
|
25
|
+
echo "BLOCKED: git stash is banned. See auto-memory: feedback_no-git-stash. Use alternatives instead:
|
|
26
|
+
- View uncommitted changes: git diff <ref>
|
|
27
|
+
- View a file at a commit: git show <ref>:<path>
|
|
28
|
+
- Isolate work safely: git worktree add <path> <branch>" >&2
|
|
29
|
+
exit 2
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
exit 0
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# @scope: org-shared
|
|
3
|
+
# Hook Helper: File-length enforcement for validate-structure.sh
|
|
4
|
+
# Two-tier policy: warn at recommended → stderr notice; block at hard cap (~2× warn) → exit 2
|
|
5
|
+
# Sourced by validate-structure.sh — not run directly.
|
|
6
|
+
#
|
|
7
|
+
# Expects: $REL_PATH, $FILE_PATH, $INPUT, block(), warn(),
|
|
8
|
+
# read_input_content(), count_lines() (from validate-structure-lib.sh)
|
|
9
|
+
|
|
10
|
+
# Returns "WARN BLOCK" pair, or empty if the file has no limit.
|
|
11
|
+
_get_limit() {
|
|
12
|
+
case "$1" in
|
|
13
|
+
# Documented exceptions — higher budget
|
|
14
|
+
/docs/templates/*/task.md) echo "450 900"; return;;
|
|
15
|
+
/.claude/docs/architecture/development.md) echo "1200 2000"; return;;
|
|
16
|
+
/.claude/skills/cbp-round-start/SKILL.md) echo "600 1000"; return;;
|
|
17
|
+
/.claude/rules/development-workflow.md) echo "250 400"; return;;
|
|
18
|
+
# Unlimited files
|
|
19
|
+
/CHANGELOG.md|*/CHANGELOG.md|*/user-input.md|/.claude/docs/research/*) echo ""; return;;
|
|
20
|
+
# Managed .claude/ files
|
|
21
|
+
/.claude/rules/*.md) echo "100 200"; return;;
|
|
22
|
+
/.claude/context/*.md|/.claude/context/*/*.md) echo "200 400"; return;;
|
|
23
|
+
/.claude/skills/*/SKILL.md) echo "300 600"; return;;
|
|
24
|
+
/.claude/skills/*/reference/*.md) echo "200 400"; return;;
|
|
25
|
+
/.claude/skills/*/examples/*.md|/.claude/skills/*/templates/*) echo "100 200"; return;;
|
|
26
|
+
/.claude/agents/*/AGENT.md) echo "400 800"; return;;
|
|
27
|
+
/.claude/agents/*/*.md) echo "200 400"; return;;
|
|
28
|
+
/.claude/hooks/*.sh) echo "150 300"; return;;
|
|
29
|
+
/.claude/docs/architecture/*.md|/.claude/docs/server/*.md) echo "200 400"; return;;
|
|
30
|
+
/.claude/docs/stack/*/index.md|/.claude/docs/stack/*/guide.md) echo "150 300"; return;;
|
|
31
|
+
/.claude/docs/stack/*/usage.md|/.claude/docs/stack/*/updates.md) echo "100 200"; return;;
|
|
32
|
+
/.claude/CLAUDE.md|/CLAUDE.md) echo "200 400"; return;;
|
|
33
|
+
# Repo work-tracking markdown
|
|
34
|
+
*/checkpoint.md|*/idea.md|*/launch.md) echo "200 400"; return;;
|
|
35
|
+
*/TASK-*.md|*/handoff*.md) echo "150 300"; return;;
|
|
36
|
+
*/prompt.md) echo "100 200"; return;;
|
|
37
|
+
# Docs templates
|
|
38
|
+
/docs/templates/*) echo "150 300"; return;;
|
|
39
|
+
esac
|
|
40
|
+
echo ""
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
PAIR="$(_get_limit "$REL_PATH")"
|
|
44
|
+
[ -z "$PAIR" ] && return 0
|
|
45
|
+
|
|
46
|
+
WARN_AT="${PAIR% *}"
|
|
47
|
+
BLOCK_AT="${PAIR#* }"
|
|
48
|
+
|
|
49
|
+
LINES=$(count_lines "$(read_input_content)" "$FILE_PATH")
|
|
50
|
+
|
|
51
|
+
if [ "$LINES" -gt "$BLOCK_AT" ]; then
|
|
52
|
+
block "File exceeds hard limit: $LINES > $BLOCK_AT lines" "Pattern: $REL_PATH (warn $WARN_AT / block $BLOCK_AT). Split by concern, extract reference material, or add a documented exception in validate-structure-lengths.sh"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if [ "$LINES" -gt "$WARN_AT" ]; then
|
|
56
|
+
warn "File over recommended length: $LINES > $WARN_AT lines (hard limit $BLOCK_AT). Consider splitting."
|
|
57
|
+
fi
|