claude-dev-env 1.0.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/LICENSE +21 -0
- package/README.md +219 -0
- package/agents/agent-writer.md +157 -0
- package/agents/clasp-deployment-orchestrator.md +609 -0
- package/agents/clean-coder.md +295 -0
- package/agents/code-quality-agent.md +40 -0
- package/agents/code-standards-agent.md +93 -0
- package/agents/config-centralizer.md +686 -0
- package/agents/config-extraction-agent.md +225 -0
- package/agents/doc-orchestrator.md +47 -0
- package/agents/docs-agent.md +112 -0
- package/agents/docx-agent.md +211 -0
- package/agents/git-commit-crafter.md +100 -0
- package/agents/magic-value-eliminator-agent.md +72 -0
- package/agents/mandatory-agent-workflow-agent.md +88 -0
- package/agents/parallel-workflow-coordinator.md +779 -0
- package/agents/pdf-agent.md +302 -0
- package/agents/plan-executor.md +226 -0
- package/agents/pr-description-writer.md +87 -0
- package/agents/project-context-loader.md +238 -0
- package/agents/project-docs-analyzer.md +54 -0
- package/agents/project-structure-organizer-agent.md +72 -0
- package/agents/readability-review-agent.md +76 -0
- package/agents/refactoring-specialist.md +69 -0
- package/agents/right-sized-engineer.md +129 -0
- package/agents/session-continuity-manager.md +53 -0
- package/agents/skill-to-agent-converter.md +371 -0
- package/agents/skill-writer-agent.md +470 -0
- package/agents/stub-detector-agent.md +140 -0
- package/agents/tdd-test-writer.md +62 -0
- package/agents/test-data-builder.md +68 -0
- package/agents/tooling-builder.md +78 -0
- package/agents/user-docs-writer.md +67 -0
- package/agents/validation-expert.md +71 -0
- package/agents/workflow-visual-documenter.md +82 -0
- package/agents/xlsx-agent.md +169 -0
- package/bin/install.mjs +256 -0
- package/commands/commit.md +28 -0
- package/commands/docupdate.md +322 -0
- package/commands/implement.md +102 -0
- package/commands/initialize.md +91 -0
- package/commands/plan.md +63 -0
- package/commands/pr-comments.md +47 -0
- package/commands/readability-review.md +20 -0
- package/commands/review-plan.md +7 -0
- package/commands/right-size.md +15 -0
- package/commands/stubcheck.md +89 -0
- package/commands/sum.md +30 -0
- package/docs/CODE_RULES.md +186 -0
- package/docs/DJANGO_PATTERNS.md +80 -0
- package/docs/REACT_PATTERNS.md +185 -0
- package/docs/TEST_QUALITY.md +104 -0
- package/hooks/advisory/migration-safety-advisor.py +49 -0
- package/hooks/advisory/refactor-guard.py +205 -0
- package/hooks/blocking/block-main-commit.py +168 -0
- package/hooks/blocking/code-rules-enforcer.py +549 -0
- package/hooks/blocking/destructive-command-blocker.py +107 -0
- package/hooks/blocking/docker-settings-guard.py +44 -0
- package/hooks/blocking/hedging-language-blocker.py +130 -0
- package/hooks/blocking/parallel-task-blocker.py +69 -0
- package/hooks/blocking/pr-description-enforcer.py +87 -0
- package/hooks/blocking/pyautogui-scroll-blocker.py +74 -0
- package/hooks/blocking/sensitive-file-protector.py +70 -0
- package/hooks/blocking/tdd-enforcer.py +62 -0
- package/hooks/blocking/test-preflight-check.py +343 -0
- package/hooks/blocking/write-existing-file-blocker.py +63 -0
- package/hooks/git-hooks/post-commit.py +103 -0
- package/hooks/github-action/test_workflow.py +33 -0
- package/hooks/hooks.json +246 -0
- package/hooks/lifecycle/config-change-guard.py +84 -0
- package/hooks/lifecycle/session-end-cleanup.py +59 -0
- package/hooks/notification/attention-needed-notify.py +63 -0
- package/hooks/notification/claude-notification-handler.py +59 -0
- package/hooks/notification/notification_utils.py +206 -0
- package/hooks/rewrite-plugin-paths.py +116 -0
- package/hooks/session/bulk-edit-reminder.py +30 -0
- package/hooks/session/code-rules-reminder.py +97 -0
- package/hooks/session/compact-context-reinject.py +39 -0
- package/hooks/session/hook-structure-context.py +140 -0
- package/hooks/session/plugin-data-dir-cleanup.py +39 -0
- package/hooks/validation/code-style-validator.py +145 -0
- package/hooks/validation/e2e-test-validator.py +142 -0
- package/hooks/validation/hook-format-validator.py +66 -0
- package/hooks/validation/mypy_validator.py +180 -0
- package/hooks/validators/README.md +125 -0
- package/hooks/validators/VALIDATION_REPORT.md +287 -0
- package/hooks/validators/__init__.py +19 -0
- package/hooks/validators/abbreviation_checks.py +82 -0
- package/hooks/validators/code_quality_checks.py +133 -0
- package/hooks/validators/comment_checks.py +188 -0
- package/hooks/validators/file_structure_checks.py +182 -0
- package/hooks/validators/git_checks.py +107 -0
- package/hooks/validators/health_check.py +214 -0
- package/hooks/validators/magic_value_checks.py +81 -0
- package/hooks/validators/mypy_integration.py +52 -0
- package/hooks/validators/output_formatter.py +266 -0
- package/hooks/validators/pr_reference_checks.py +72 -0
- package/hooks/validators/python_antipattern_checks.py +110 -0
- package/hooks/validators/python_style_checks.py +364 -0
- package/hooks/validators/react_checks.py +90 -0
- package/hooks/validators/ruff_integration.py +80 -0
- package/hooks/validators/run_all_validators.py +772 -0
- package/hooks/validators/security_checks.py +135 -0
- package/hooks/validators/test_abbreviation_checks.py +76 -0
- package/hooks/validators/test_bad.tsx +7 -0
- package/hooks/validators/test_code_quality_checks.py +129 -0
- package/hooks/validators/test_file_structure_checks.py +307 -0
- package/hooks/validators/test_files/01_basic_component.tsx +10 -0
- package/hooks/validators/test_files/02_component_without_react.tsx +10 -0
- package/hooks/validators/test_files/03_pure_component.tsx +10 -0
- package/hooks/validators/test_files/04_pure_component_import.tsx +10 -0
- package/hooks/validators/test_files/05_typescript_generics.tsx +14 -0
- package/hooks/validators/test_files/06_typescript_two_generics.tsx +18 -0
- package/hooks/validators/test_files/07_multiline_declaration.tsx +11 -0
- package/hooks/validators/test_files/08_error_boundary_valid.tsx +14 -0
- package/hooks/validators/test_files/09_error_boundary_with_other_class.tsx +20 -0
- package/hooks/validators/test_files/10_inheritance_chain.tsx +16 -0
- package/hooks/validators/test_files/11_ts_file.ts +10 -0
- package/hooks/validators/test_files/12_non_react_class.tsx +14 -0
- package/hooks/validators/test_files/13_functional_component.tsx +8 -0
- package/hooks/validators/test_files/14_indented_class.tsx +13 -0
- package/hooks/validators/test_files/15_getDerivedStateFromError.tsx +14 -0
- package/hooks/validators/test_files/16_mixed_components.tsx +20 -0
- package/hooks/validators/test_files/EXECUTIVE_SUMMARY.md +175 -0
- package/hooks/validators/test_files/TEST_RESULTS_TABLE.txt +60 -0
- package/hooks/validators/test_files/VALIDATION_REPORT.md +201 -0
- package/hooks/validators/test_files/async_views.py +23 -0
- package/hooks/validators/test_files/async_with_imports.py +14 -0
- package/hooks/validators/test_files/bad_inline_imports.py +37 -0
- package/hooks/validators/test_files/management/commands/cmd_01_no_debug_check.py +10 -0
- package/hooks/validators/test_files/management/commands/cmd_02_proper_debug_check.py +14 -0
- package/hooks/validators/test_files/management/commands/cmd_03_debug_check_with_return.py +14 -0
- package/hooks/validators/test_files/management/commands/cmd_04_imported_DEBUG.py +14 -0
- package/hooks/validators/test_files/management/commands/cmd_05_debug_check_in_helper.py +16 -0
- package/hooks/validators/test_files/management/commands/cmd_06_debug_check_late.py +22 -0
- package/hooks/validators/test_files/management/commands/cmd_07_positive_debug_check.py +15 -0
- package/hooks/validators/test_files/management/commands/cmd_08_debug_with_and.py +14 -0
- package/hooks/validators/test_files/not_management_command.py +10 -0
- package/hooks/validators/test_files/skip_decorators/test_01_simple_skip.py +8 -0
- package/hooks/validators/test_files/skip_decorators/test_02_pytest_skipif.py +8 -0
- package/hooks/validators/test_files/skip_decorators/test_03_unittest_skipIf.py +8 -0
- package/hooks/validators/test_files/skip_decorators/test_04_skip_with_parens.py +8 -0
- package/hooks/validators/test_files/skip_decorators/test_05_xfail.py +7 -0
- package/hooks/validators/test_files/skip_decorators/test_06_custom_skip.py +11 -0
- package/hooks/validators/test_files/skip_decorators/test_07_capital_Skip.py +8 -0
- package/hooks/validators/test_files/skip_decorators/test_08_skipUnless.py +7 -0
- package/hooks/validators/test_files/skip_decorators/test_09_pytest_mark_skip_simple.py +7 -0
- package/hooks/validators/test_files/test_async_functions.py +45 -0
- package/hooks/validators/test_files/test_purecomponent/PureComponentExample.tsx +7 -0
- package/hooks/validators/test_files/test_purecomponent/ReactPureComponentExample.tsx +7 -0
- package/hooks/validators/test_git_checks.py +295 -0
- package/hooks/validators/test_good.tsx +5 -0
- package/hooks/validators/test_health_check.py +57 -0
- package/hooks/validators/test_magic_value_checks.py +63 -0
- package/hooks/validators/test_mypy_integration.py +27 -0
- package/hooks/validators/test_output_formatter.py +150 -0
- package/hooks/validators/test_pr_reference_checks.py +41 -0
- package/hooks/validators/test_python_antipattern_checks.py +113 -0
- package/hooks/validators/test_python_style_checks.py +439 -0
- package/hooks/validators/test_react_checks.py +213 -0
- package/hooks/validators/test_results.txt +25 -0
- package/hooks/validators/test_ruff_integration.py +27 -0
- package/hooks/validators/test_run_all_validators.py +228 -0
- package/hooks/validators/test_run_all_validators_integration.py +48 -0
- package/hooks/validators/test_safety_checks.py +243 -0
- package/hooks/validators/test_security_checks.py +105 -0
- package/hooks/validators/test_test_safety_checks.py +321 -0
- package/hooks/validators/test_todo_checks.py +39 -0
- package/hooks/validators/test_type_safety_checks.py +85 -0
- package/hooks/validators/test_useless_test_checks.py +55 -0
- package/hooks/validators/test_validator_base.py +26 -0
- package/hooks/validators/test_verify_paths.py +34 -0
- package/hooks/validators/todo_checks.py +59 -0
- package/hooks/validators/type_safety_checks.py +101 -0
- package/hooks/validators/useless_test_checks.py +92 -0
- package/hooks/validators/validator_base.py +19 -0
- package/hooks/validators/verify_paths.py +57 -0
- package/hooks/workflow/auto-formatter.py +114 -0
- package/hooks/workflow/investigation-tracker-reset.py +46 -0
- package/package.json +30 -0
- package/rules/agent-spawn-protocol.md +47 -0
- package/rules/cleanup-temp-files.md +27 -0
- package/rules/code-reviews.md +11 -0
- package/rules/code-standards.md +43 -0
- package/rules/conservative-action.md +20 -0
- package/rules/context7.md +12 -0
- package/rules/explore-thoroughly.md +27 -0
- package/rules/git-workflow.md +42 -0
- package/rules/parallel-tools.md +23 -0
- package/rules/research-mode.md +23 -0
- package/rules/right-sized-engineering.md +28 -0
- package/rules/tdd.md +7 -0
- package/rules/testing.md +12 -0
- package/skills/agent-prompt/SKILL.md +102 -0
- package/skills/anthropic-plan/SKILL.md +107 -0
- package/skills/everything-search/SKILL.md +144 -0
- package/skills/ingest/SKILL.md +40 -0
- package/skills/npm-creator/SKILL.md +183 -0
- package/skills/pr-review-responder/EXAMPLES.md +590 -0
- package/skills/pr-review-responder/PRINCIPLES.md +539 -0
- package/skills/pr-review-responder/README.md +209 -0
- package/skills/pr-review-responder/SKILL.md +202 -0
- package/skills/pr-review-responder/TESTING.md +407 -0
- package/skills/pr-review-responder/scripts/respond_to_reviews.py +376 -0
- package/skills/pr-review-responder/update_skill.py +297 -0
- package/skills/prompt-generator/REFERENCE.md +150 -0
- package/skills/prompt-generator/SKILL.md +154 -0
- package/skills/readability-review/SKILL.md +127 -0
- package/skills/recall/SKILL.md +27 -0
- package/skills/remember/SKILL.md +63 -0
- package/skills/rule-audit/SKILL.md +307 -0
- package/skills/rule-creator/SKILL.md +150 -0
- package/skills/skill-writer/REFERENCE.md +246 -0
- package/skills/skill-writer/SKILL.md +270 -0
- package/skills/tdd-team/SKILL.md +128 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PreToolUse hook that blocks direct commits to main/master branch in any git project.
|
|
3
|
+
Requires explicit user confirmation before allowing the commit.
|
|
4
|
+
|
|
5
|
+
Handles commits in any directory context:
|
|
6
|
+
- Plain `git commit` (uses CWD)
|
|
7
|
+
- `cd /path && git commit` or `cd /path; git commit`
|
|
8
|
+
- `pushd /path && git commit`
|
|
9
|
+
- `git -C /path commit`
|
|
10
|
+
- Quoted and tilde-expanded paths
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
GIT_COMMAND_TIMEOUT_SECONDS = 5
|
|
20
|
+
PROTECTED_BRANCHES = ("main", "master")
|
|
21
|
+
PROTECTED_REMOTE_PATTERNS: list[str] = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def extract_git_working_directory(bash_command: str) -> str | None:
|
|
25
|
+
"""Extract the directory where git commit will actually execute.
|
|
26
|
+
|
|
27
|
+
Parses the bash command for directory-changing patterns that precede
|
|
28
|
+
the git commit, and for git's own -C flag.
|
|
29
|
+
|
|
30
|
+
Returns None if the commit runs in the hook's CWD.
|
|
31
|
+
"""
|
|
32
|
+
git_c_match = re.search(
|
|
33
|
+
r"git\s+-C\s+[\"']?([^\"';&|]+?)[\"']?\s+commit",
|
|
34
|
+
bash_command,
|
|
35
|
+
)
|
|
36
|
+
if git_c_match:
|
|
37
|
+
return git_c_match.group(1).strip()
|
|
38
|
+
|
|
39
|
+
commit_pos = bash_command.lower().find("git commit")
|
|
40
|
+
if commit_pos == -1:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
prefix = bash_command[:commit_pos]
|
|
44
|
+
|
|
45
|
+
cd_matches = re.findall(
|
|
46
|
+
r"(?:cd|pushd)\s+[\"']?([^\"';&|]+?)[\"']?\s*[;&|]",
|
|
47
|
+
prefix,
|
|
48
|
+
)
|
|
49
|
+
if cd_matches:
|
|
50
|
+
return cd_matches[-1].strip()
|
|
51
|
+
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def resolve_directory(directory: str | None) -> str | None:
|
|
56
|
+
"""Resolve a directory path, expanding ~ and validating existence."""
|
|
57
|
+
if directory is None:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
expanded = os.path.expanduser(directory)
|
|
61
|
+
|
|
62
|
+
if not os.path.isabs(expanded):
|
|
63
|
+
expanded = os.path.abspath(expanded)
|
|
64
|
+
|
|
65
|
+
if os.path.isdir(expanded):
|
|
66
|
+
return expanded
|
|
67
|
+
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_branch_at_directory(working_dir: str | None = None) -> str | None:
|
|
72
|
+
"""Get the current git branch at a specific directory."""
|
|
73
|
+
try:
|
|
74
|
+
completed_process = subprocess.run(
|
|
75
|
+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
|
76
|
+
capture_output=True,
|
|
77
|
+
text=True,
|
|
78
|
+
timeout=GIT_COMMAND_TIMEOUT_SECONDS,
|
|
79
|
+
cwd=working_dir,
|
|
80
|
+
)
|
|
81
|
+
if completed_process.returncode == 0:
|
|
82
|
+
return completed_process.stdout.strip()
|
|
83
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def is_protected_repo(working_dir: str | None = None) -> bool:
|
|
90
|
+
if not PROTECTED_REMOTE_PATTERNS:
|
|
91
|
+
return True
|
|
92
|
+
try:
|
|
93
|
+
completed_process = subprocess.run(
|
|
94
|
+
["git", "remote", "get-url", "origin"],
|
|
95
|
+
capture_output=True,
|
|
96
|
+
text=True,
|
|
97
|
+
timeout=GIT_COMMAND_TIMEOUT_SECONDS,
|
|
98
|
+
cwd=working_dir,
|
|
99
|
+
)
|
|
100
|
+
if completed_process.returncode == 0:
|
|
101
|
+
remote_url = completed_process.stdout.strip()
|
|
102
|
+
return any(pattern in remote_url for pattern in PROTECTED_REMOTE_PATTERNS)
|
|
103
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
|
104
|
+
pass
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def is_commit_command(bash_command: str) -> bool:
|
|
109
|
+
return "git commit" in bash_command.lower().strip()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def is_main_commit_confirmed(bash_command: str) -> bool:
|
|
113
|
+
"""Return True if the command includes the explicit confirmation sentinel."""
|
|
114
|
+
return "--allow-main-commit" in bash_command
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def parse_bash_command_from_stdin() -> str:
|
|
118
|
+
try:
|
|
119
|
+
hook_event = json.load(sys.stdin)
|
|
120
|
+
except json.JSONDecodeError:
|
|
121
|
+
return ""
|
|
122
|
+
|
|
123
|
+
return hook_event.get("tool_input", {}).get("command", "")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def build_denial_response(branch_name: str, repo_dir: str | None) -> dict:
|
|
127
|
+
location = f" in {repo_dir}" if repo_dir else ""
|
|
128
|
+
denial_reason = f"BLOCKED: Direct commit to '{branch_name}' is not allowed. Create a feature branch first: git checkout -b feature/your-branch-name. If you must commit to main, the user needs to approve explicitly."
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
"hookSpecificOutput": {
|
|
132
|
+
"hookEventName": "PreToolUse",
|
|
133
|
+
"permissionDecision": "deny",
|
|
134
|
+
"permissionDecisionReason": denial_reason,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def main() -> None:
|
|
140
|
+
bash_command = parse_bash_command_from_stdin()
|
|
141
|
+
|
|
142
|
+
if not is_commit_command(bash_command):
|
|
143
|
+
sys.exit(0)
|
|
144
|
+
|
|
145
|
+
if is_main_commit_confirmed(bash_command):
|
|
146
|
+
sys.exit(0)
|
|
147
|
+
|
|
148
|
+
target_dir_raw = extract_git_working_directory(bash_command)
|
|
149
|
+
target_dir = resolve_directory(target_dir_raw)
|
|
150
|
+
|
|
151
|
+
if target_dir_raw and not target_dir:
|
|
152
|
+
sys.exit(0)
|
|
153
|
+
|
|
154
|
+
current_branch = get_branch_at_directory(working_dir=target_dir)
|
|
155
|
+
|
|
156
|
+
if current_branch not in PROTECTED_BRANCHES:
|
|
157
|
+
sys.exit(0)
|
|
158
|
+
|
|
159
|
+
if not is_protected_repo(working_dir=target_dir):
|
|
160
|
+
sys.exit(0)
|
|
161
|
+
|
|
162
|
+
denial = build_denial_response(current_branch, target_dir)
|
|
163
|
+
print(json.dumps(denial))
|
|
164
|
+
sys.exit(0)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
if __name__ == "__main__":
|
|
168
|
+
main()
|