codebyplan 1.5.1 → 1.9.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.
Files changed (211) hide show
  1. package/dist/cli.js +4462 -748
  2. package/package.json +5 -1
  3. package/templates/.gitkeep +0 -0
  4. package/templates/README.md +20 -0
  5. package/templates/agents/cbp-cc-executor.md +213 -0
  6. package/templates/agents/cbp-database-agent.md +229 -0
  7. package/templates/agents/cbp-improve-claude.md +245 -0
  8. package/templates/agents/cbp-improve-round.md +284 -0
  9. package/templates/agents/cbp-mechanical-edits.md +111 -0
  10. package/templates/agents/cbp-research.md +282 -0
  11. package/templates/agents/cbp-round-executor.md +604 -0
  12. package/templates/agents/cbp-security-agent.md +134 -0
  13. package/templates/agents/cbp-task-check.md +213 -0
  14. package/templates/agents/cbp-task-planner.md +582 -0
  15. package/templates/agents/cbp-test-e2e-agent.md +363 -0
  16. package/templates/agents/cbp-testing-qa-agent.md +400 -0
  17. package/templates/context/mcp-docs.md +139 -0
  18. package/templates/hooks/README.md +236 -0
  19. package/templates/hooks/cbp-auto-test-hooks.sh +44 -0
  20. package/templates/hooks/cbp-lint-format-on-edit.sh +159 -0
  21. package/templates/hooks/cbp-maestro-yaml-validate.sh +100 -0
  22. package/templates/hooks/cbp-mcp-migration-guard.sh +32 -0
  23. package/templates/hooks/cbp-mcp-round-sync.sh +79 -0
  24. package/templates/hooks/cbp-mcp-worktree-inject.sh +76 -0
  25. package/templates/hooks/cbp-notify.sh +68 -0
  26. package/templates/hooks/cbp-plugin-dispatch.sh +29 -0
  27. package/templates/hooks/cbp-pre-commit-quality-gate.sh +204 -0
  28. package/templates/hooks/cbp-statusline.sh +347 -0
  29. package/templates/hooks/cbp-subagent-statusline.sh +182 -0
  30. package/templates/hooks/cbp-test-coverage-gate.sh +144 -0
  31. package/templates/hooks/cbp-test-hooks.sh +320 -0
  32. package/templates/hooks/hooks.json +85 -0
  33. package/templates/hooks/validate-context-usage.sh +59 -0
  34. package/templates/hooks/validate-git-commit.sh +78 -0
  35. package/templates/hooks/validate-git-stash-deny.sh +32 -0
  36. package/templates/hooks/validate-structure-lengths.sh +57 -0
  37. package/templates/hooks/validate-structure-lib.sh +104 -0
  38. package/templates/hooks/validate-structure-patterns.sh +54 -0
  39. package/templates/hooks/validate-structure-scope.sh +33 -0
  40. package/templates/hooks/validate-structure-smoke.sh +95 -0
  41. package/templates/hooks/validate-structure-templates.sh +34 -0
  42. package/templates/hooks/validate-structure.sh +69 -0
  43. package/templates/rules/.gitkeep +0 -0
  44. package/templates/rules/README.md +47 -0
  45. package/templates/rules/context-file-loading.md +52 -0
  46. package/templates/rules/scope-vocabulary.md +64 -0
  47. package/templates/rules/todo-backend.md +109 -0
  48. package/templates/settings.project.base.json +55 -0
  49. package/templates/settings.user.base.json +25 -0
  50. package/templates/skills/cbp-build-cc-agent/SKILL.md +139 -0
  51. package/templates/skills/cbp-build-cc-agent/examples/read-only-reviewer.md +32 -0
  52. package/templates/skills/cbp-build-cc-agent/examples/with-hooks.md +41 -0
  53. package/templates/skills/cbp-build-cc-agent/examples/with-skills-preload.md +25 -0
  54. package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +153 -0
  55. package/templates/skills/cbp-build-cc-agent/reference/frontmatter-fields.md +37 -0
  56. package/templates/skills/cbp-build-cc-agent/reference/permission-modes.md +18 -0
  57. package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +67 -0
  58. package/templates/skills/cbp-build-cc-agent/templates/agent.md +66 -0
  59. package/templates/skills/cbp-build-cc-claude-file/SKILL.md +178 -0
  60. package/templates/skills/cbp-build-cc-claude-file/examples/minimal-project.md +33 -0
  61. package/templates/skills/cbp-build-cc-claude-file/examples/monorepo-with-imports.md +39 -0
  62. package/templates/skills/cbp-build-cc-claude-file/reference/imports.md +72 -0
  63. package/templates/skills/cbp-build-cc-claude-file/reference/what-belongs.md +39 -0
  64. package/templates/skills/cbp-build-cc-claude-file/templates/project-claude-md.md +48 -0
  65. package/templates/skills/cbp-build-cc-claude-file/templates/user-claude-md.md +22 -0
  66. package/templates/skills/cbp-build-cc-memory/SKILL.md +201 -0
  67. package/templates/skills/cbp-build-cc-memory/examples/feedback-memory.md +11 -0
  68. package/templates/skills/cbp-build-cc-memory/examples/project-memory.md +11 -0
  69. package/templates/skills/cbp-build-cc-memory/examples/reference-memory.md +13 -0
  70. package/templates/skills/cbp-build-cc-memory/examples/user-memory.md +14 -0
  71. package/templates/skills/cbp-build-cc-memory/reference/memory-types.md +59 -0
  72. package/templates/skills/cbp-build-cc-memory/reference/when-to-save.md +62 -0
  73. package/templates/skills/cbp-build-cc-memory/templates/MEMORY-index.md +4 -0
  74. package/templates/skills/cbp-build-cc-memory/templates/memory-entry.md +15 -0
  75. package/templates/skills/cbp-build-cc-mode/SKILL.md +99 -0
  76. package/templates/skills/cbp-build-cc-rule/SKILL.md +176 -0
  77. package/templates/skills/cbp-build-cc-rule/examples/global-rule.md +19 -0
  78. package/templates/skills/cbp-build-cc-rule/examples/scoped-rule.md +41 -0
  79. package/templates/skills/cbp-build-cc-rule/reference/paths-patterns.md +48 -0
  80. package/templates/skills/cbp-build-cc-rule/templates/rule.md +32 -0
  81. package/templates/skills/cbp-build-cc-settings/SKILL.md +220 -0
  82. package/templates/skills/cbp-build-cc-settings/examples/hooks-config.json +64 -0
  83. package/templates/skills/cbp-build-cc-settings/examples/permissions-config.json +34 -0
  84. package/templates/skills/cbp-build-cc-settings/examples/sandbox-config.json +42 -0
  85. package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +104 -0
  86. package/templates/skills/cbp-build-cc-settings/reference/permission-rules.md +61 -0
  87. package/templates/skills/cbp-build-cc-settings/reference/scope-precedence.md +73 -0
  88. package/templates/skills/cbp-build-cc-settings/reference/settings-fields.md +166 -0
  89. package/templates/skills/cbp-build-cc-settings/templates/settings.json +23 -0
  90. package/templates/skills/cbp-build-cc-settings/templates/settings.local.json +10 -0
  91. package/templates/skills/cbp-build-cc-skill/SKILL.md +154 -0
  92. package/templates/skills/cbp-build-cc-skill/examples/dynamic-context.md +31 -0
  93. package/templates/skills/cbp-build-cc-skill/examples/fork-skill.md +22 -0
  94. package/templates/skills/cbp-build-cc-skill/examples/knowledge-skill.md +25 -0
  95. package/templates/skills/cbp-build-cc-skill/examples/task-skill.md +29 -0
  96. package/templates/skills/cbp-build-cc-skill/reference/cbp-quality.md +157 -0
  97. package/templates/skills/cbp-build-cc-skill/reference/frontmatter-fields.md +35 -0
  98. package/templates/skills/cbp-build-cc-skill/reference/string-substitutions.md +60 -0
  99. package/templates/skills/cbp-build-cc-skill/scripts/validate-skill.sh +90 -0
  100. package/templates/skills/cbp-build-cc-skill/templates/skill.md +51 -0
  101. package/templates/skills/cbp-checkpoint-check/SKILL.md +156 -0
  102. package/templates/skills/cbp-checkpoint-complete/SKILL.md +109 -0
  103. package/templates/skills/cbp-checkpoint-create/SKILL.md +116 -0
  104. package/templates/skills/cbp-checkpoint-end/SKILL.md +241 -0
  105. package/templates/skills/cbp-checkpoint-plan/SKILL.md +137 -0
  106. package/templates/skills/cbp-checkpoint-plan/reference/alternative-comparison-template.md +54 -0
  107. package/templates/skills/cbp-checkpoint-plan/reference/dep-decision-rubric.md +50 -0
  108. package/templates/skills/cbp-checkpoint-plan/reference/e2e-discovery-probe.md +57 -0
  109. package/templates/skills/cbp-checkpoint-plan/reference/gap-analysis-playbook.md +47 -0
  110. package/templates/skills/cbp-checkpoint-start/SKILL.md +84 -0
  111. package/templates/skills/cbp-checkpoint-update/SKILL.md +115 -0
  112. package/templates/skills/cbp-frontend-a11y/SKILL.md +109 -0
  113. package/templates/skills/cbp-frontend-a11y/reference/aria-roles-states.md +130 -0
  114. package/templates/skills/cbp-frontend-a11y/reference/contrast-visual.md +122 -0
  115. package/templates/skills/cbp-frontend-a11y/reference/keyboard-patterns.md +154 -0
  116. package/templates/skills/cbp-frontend-a11y/reference/semantic-html.md +111 -0
  117. package/templates/skills/cbp-frontend-design/SKILL.md +145 -0
  118. package/templates/skills/cbp-frontend-design/reference/nextjs-scss.md +118 -0
  119. package/templates/skills/cbp-frontend-design/reference/rn-expo.md +101 -0
  120. package/templates/skills/cbp-frontend-design/reference/tauri-react.md +82 -0
  121. package/templates/skills/cbp-frontend-ui/SKILL.md +262 -0
  122. package/templates/skills/cbp-frontend-ui/reference/ui-label-maps.md +42 -0
  123. package/templates/skills/cbp-frontend-ui/reference/ui-layout-patterns.md +105 -0
  124. package/templates/skills/cbp-frontend-ui/reference/variant-defaults.md +149 -0
  125. package/templates/skills/cbp-frontend-ux/SKILL.md +181 -0
  126. package/templates/skills/cbp-git-branch-feat-create/SKILL.md +115 -0
  127. package/templates/skills/cbp-git-commit/SKILL.md +278 -0
  128. package/templates/skills/cbp-git-worktree-create/SKILL.md +226 -0
  129. package/templates/skills/cbp-git-worktree-remove/SKILL.md +145 -0
  130. package/templates/skills/cbp-merge-main/SKILL.md +228 -0
  131. package/templates/skills/cbp-round-check/SKILL.md +104 -0
  132. package/templates/skills/cbp-round-end/SKILL.md +183 -0
  133. package/templates/skills/cbp-round-end/reference/findings-presentation.md +44 -0
  134. package/templates/skills/cbp-round-end/reference/inline-fallback.md +35 -0
  135. package/templates/skills/cbp-round-execute/SKILL.md +211 -0
  136. package/templates/skills/cbp-round-execute/reference/inline-fallback.md +59 -0
  137. package/templates/skills/cbp-round-input/SKILL.md +165 -0
  138. package/templates/skills/cbp-round-start/SKILL.md +222 -0
  139. package/templates/skills/cbp-round-update/SKILL.md +163 -0
  140. package/templates/skills/cbp-session-end/SKILL.md +187 -0
  141. package/templates/skills/cbp-session-start/SKILL.md +155 -0
  142. package/templates/skills/cbp-ship/SKILL.md +332 -0
  143. package/templates/skills/cbp-ship/reference/changesets-overview.md +120 -0
  144. package/templates/skills/cbp-ship/reference/eas-cli-overview.md +60 -0
  145. package/templates/skills/cbp-ship/reference/gh-cli-overview.md +135 -0
  146. package/templates/skills/cbp-ship/reference/gh-cli-shipment-commands.md +283 -0
  147. package/templates/skills/cbp-ship/reference/npm-publish-monorepo.md +252 -0
  148. package/templates/skills/cbp-ship/reference/npm-publish-oidc-trusted.md +157 -0
  149. package/templates/skills/cbp-ship/reference/npm-publish-overview.md +171 -0
  150. package/templates/skills/cbp-ship/reference/preflight-checklist.md +88 -0
  151. package/templates/skills/cbp-ship/reference/railway-nestjs-deployment.md +169 -0
  152. package/templates/skills/cbp-ship/reference/railway-overview.md +120 -0
  153. package/templates/skills/cbp-ship/reference/railway-troubleshooting.md +168 -0
  154. package/templates/skills/cbp-ship/reference/release-please-overview.md +99 -0
  155. package/templates/skills/cbp-ship/reference/surface-expo-eas.md +155 -0
  156. package/templates/skills/cbp-ship/reference/surface-npm.md +180 -0
  157. package/templates/skills/cbp-ship/reference/surface-railway.md +152 -0
  158. package/templates/skills/cbp-ship/reference/surface-supabase.md +178 -0
  159. package/templates/skills/cbp-ship/reference/surface-tauri.md +138 -0
  160. package/templates/skills/cbp-ship/reference/surface-vercel.md +124 -0
  161. package/templates/skills/cbp-ship/reference/surface-vscode-ext.md +144 -0
  162. package/templates/skills/cbp-ship/reference/surfaces.md +60 -0
  163. package/templates/skills/cbp-ship/reference/testflight-automation.md +215 -0
  164. package/templates/skills/cbp-ship/reference/testflight-internal-vs-external.md +69 -0
  165. package/templates/skills/cbp-ship/reference/testflight-overview.md +98 -0
  166. package/templates/skills/cbp-ship/reference/versioning.md +116 -0
  167. package/templates/skills/cbp-ship/scripts/detect-surfaces.sh +217 -0
  168. package/templates/skills/cbp-ship/scripts/verify-expo-eas.sh +35 -0
  169. package/templates/skills/cbp-ship/scripts/verify-npm.sh +21 -0
  170. package/templates/skills/cbp-ship/scripts/verify-railway.sh +41 -0
  171. package/templates/skills/cbp-ship/scripts/verify-supabase.sh +19 -0
  172. package/templates/skills/cbp-ship/scripts/verify-tauri.sh +24 -0
  173. package/templates/skills/cbp-ship/scripts/verify-vercel.sh +32 -0
  174. package/templates/skills/cbp-ship/scripts/verify-vscode-ext.sh +25 -0
  175. package/templates/skills/cbp-ship/templates/eas.json +66 -0
  176. package/templates/skills/cbp-ship/templates/railway.toml +15 -0
  177. package/templates/skills/cbp-ship/templates/release-please-config.json +17 -0
  178. package/templates/skills/cbp-ship/templates/vercel.json +19 -0
  179. package/templates/skills/cbp-ship/templates/vscodeignore +21 -0
  180. package/templates/skills/cbp-ship/templates/workflow-changesets.yml +41 -0
  181. package/templates/skills/cbp-ship/templates/workflow-eas-submit.yml +53 -0
  182. package/templates/skills/cbp-ship/templates/workflow-npm-publish.yml +36 -0
  183. package/templates/skills/cbp-ship/templates/workflow-release-please.yml +21 -0
  184. package/templates/skills/cbp-ship/templates/workflow-tauri-release.yml +69 -0
  185. package/templates/skills/cbp-ship/templates/workflow-vsce-publish.yml +31 -0
  186. package/templates/skills/cbp-ship-configure/SKILL.md +296 -0
  187. package/templates/skills/cbp-ship-configure/reference/expo-mobile.md +204 -0
  188. package/templates/skills/cbp-ship-configure/reference/npm-package.md +165 -0
  189. package/templates/skills/cbp-ship-configure/reference/railway-backend.md +199 -0
  190. package/templates/skills/cbp-ship-configure/reference/supabase.md +200 -0
  191. package/templates/skills/cbp-ship-configure/reference/tauri-desktop.md +181 -0
  192. package/templates/skills/cbp-ship-configure/reference/vercel.md +117 -0
  193. package/templates/skills/cbp-ship-configure/reference/vscode-ext.md +155 -0
  194. package/templates/skills/cbp-ship-main/SKILL.md +65 -0
  195. package/templates/skills/cbp-supabase-branch-check/SKILL.md +337 -0
  196. package/templates/skills/cbp-supabase-branch-check/reference/dag-steps.md +29 -0
  197. package/templates/skills/cbp-supabase-migrate/SKILL.md +314 -0
  198. package/templates/skills/cbp-supabase-migrate/reference/advisor-triage.md +70 -0
  199. package/templates/skills/cbp-supabase-migrate/reference/cli-fallback.md +87 -0
  200. package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +58 -0
  201. package/templates/skills/cbp-supabase-setup/SKILL.md +239 -0
  202. package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +121 -0
  203. package/templates/skills/cbp-supabase-setup/reference/cli-fallback.md +109 -0
  204. package/templates/skills/cbp-task-check/SKILL.md +166 -0
  205. package/templates/skills/cbp-task-complete/SKILL.md +206 -0
  206. package/templates/skills/cbp-task-complete/reference/checkpoint-done-branching.md +48 -0
  207. package/templates/skills/cbp-task-complete/reference/next-step-heuristic.md +56 -0
  208. package/templates/skills/cbp-task-create/SKILL.md +167 -0
  209. package/templates/skills/cbp-task-start/SKILL.md +239 -0
  210. package/templates/skills/cbp-task-testing/SKILL.md +277 -0
  211. package/templates/skills/cbp-todo/SKILL.md +111 -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