claude-dev-env 2.13.0 → 2.14.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/AGENTS.md +61 -0
- package/CLAUDE.md +1 -57
- package/_shared/AGENTS.md +15 -0
- package/_shared/CLAUDE.md +1 -15
- package/_shared/advisor/AGENTS.md +22 -0
- package/_shared/advisor/CLAUDE.md +1 -22
- package/_shared/pr-loop/AGENTS.md +27 -0
- package/_shared/pr-loop/CLAUDE.md +1 -27
- package/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +42 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +1 -42
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +26 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -26
- package/_shared/pr-loop/scripts/tests/AGENTS.md +44 -0
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -44
- package/_shared/process-tree/AGENTS.md +41 -0
- package/_shared/process-tree/CLAUDE.md +1 -41
- package/agents/AGENTS.md +31 -0
- package/agents/CLAUDE.md +1 -31
- package/agents/clean-coder.md +6 -6
- package/agents/test_agent_frontmatter.py +4 -4
- package/audit-rubrics/AGENTS.md +43 -0
- package/audit-rubrics/CLAUDE.md +1 -43
- package/audit-rubrics/category_rubrics/AGENTS.md +37 -0
- package/audit-rubrics/category_rubrics/CLAUDE.md +1 -37
- package/audit-rubrics/prompts/AGENTS.md +37 -0
- package/audit-rubrics/prompts/CLAUDE.md +1 -37
- package/bin/AGENTS.md +112 -0
- package/bin/CLAUDE.md +1 -112
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +6 -7
- package/bin/install.mjs +24 -5
- package/bin/install.test.mjs +34 -0
- package/commands/AGENTS.md +23 -0
- package/commands/CLAUDE.md +1 -23
- package/commands/hook-log-extract.md +3 -3
- package/docs/AGENTS.md +32 -0
- package/docs/CLAUDE.md +1 -32
- package/docs/CODE_RULES.md +1 -1
- package/docs/imagegen.md +22 -0
- package/docs/references/AGENTS.md +17 -0
- package/docs/references/CLAUDE.md +1 -17
- package/hooks/AGENTS.md +31 -0
- package/hooks/CLAUDE.md +1 -31
- package/hooks/_gh_pr_author_swap_utils.py +14 -0
- package/hooks/advisory/AGENTS.md +16 -0
- package/hooks/advisory/CLAUDE.md +1 -16
- package/hooks/blocking/AGENTS.md +123 -0
- package/hooks/blocking/CLAUDE.md +1 -123
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +28 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/CLAUDE.md +1 -28
- package/hooks/blocking/code_rules_banned_identifiers.py +1 -1
- package/hooks/blocking/code_rules_dead_module_constant.py +149 -37
- package/hooks/blocking/code_rules_probe_chains.py +6 -2
- package/hooks/blocking/config/AGENTS.md +10 -0
- package/hooks/blocking/config/CLAUDE.md +1 -10
- package/hooks/blocking/gh_pr_author_restore.py +7 -2
- package/hooks/blocking/intent_only_ending_blocker.py +11 -16
- package/hooks/blocking/inventory_intent_records/AGENTS.md +26 -0
- package/hooks/blocking/inventory_intent_records/CLAUDE.md +1 -26
- package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +26 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/CLAUDE.md +1 -26
- package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +24 -0
- package/hooks/blocking/pii_prevention_blocker_parts/CLAUDE.md +1 -24
- package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +30 -0
- package/hooks/blocking/tdd_enforcer_parts/CLAUDE.md +1 -30
- package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +171 -0
- package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
- package/hooks/blocking/test_gh_pr_author_restore.py +2 -1
- package/hooks/blocking/test_intent_only_ending_blocker.py +4 -0
- package/hooks/diagnostic/AGENTS.md +43 -0
- package/hooks/diagnostic/CLAUDE.md +1 -43
- package/hooks/diagnostic/hook_log_extractor.py +2 -2
- package/hooks/diagnostic/migrations/AGENTS.md +16 -0
- package/hooks/diagnostic/migrations/CLAUDE.md +1 -16
- package/hooks/diagnostic/queries/AGENTS.md +19 -0
- package/hooks/diagnostic/queries/CLAUDE.md +1 -19
- package/hooks/diagnostic/test_hook_log_extractor.py +2 -2
- package/hooks/git-hooks/AGENTS.md +31 -0
- package/hooks/git-hooks/CLAUDE.md +1 -31
- package/hooks/git-hooks/git_hooks_constants/AGENTS.md +21 -0
- package/hooks/git-hooks/git_hooks_constants/CLAUDE.md +1 -21
- package/hooks/git-hooks/git_hooks_constants/__init__.py +4 -6
- package/hooks/git-hooks/pre_push.py +47 -34
- package/hooks/git-hooks/test_pre_push.py +111 -7
- package/hooks/hooks_constants/AGENTS.md +104 -0
- package/hooks/hooks_constants/CLAUDE.md +1 -104
- package/hooks/hooks_constants/hook_log_extractor_constants.py +1 -2
- package/hooks/hooks_constants/task_list_loop_starter_constants.py +4 -3
- package/hooks/hooks_constants/working_style_prompt_constants.py +29 -20
- package/hooks/lifecycle/AGENTS.md +18 -0
- package/hooks/lifecycle/CLAUDE.md +1 -18
- package/hooks/observability/AGENTS.md +20 -0
- package/hooks/observability/CLAUDE.md +1 -20
- package/hooks/session/AGENTS.md +33 -0
- package/hooks/session/CLAUDE.md +1 -33
- package/hooks/session/gh_pr_author_session_cleanup.py +7 -2
- package/hooks/session/task_list_loop_starter.py +3 -3
- package/hooks/session/test_gh_pr_author_session_cleanup.py +2 -1
- package/hooks/session/test_task_list_loop_starter.py +10 -2
- package/hooks/session/test_working_style_prompt.py +9 -4
- package/hooks/validation/AGENTS.md +20 -0
- package/hooks/validation/CLAUDE.md +1 -20
- package/hooks/validators/AGENTS.md +51 -0
- package/hooks/validators/CLAUDE.md +1 -51
- package/hooks/validators/health_check.py +52 -19
- package/hooks/validators/python_style_checks.py +1 -1
- package/hooks/validators/test_health_check.py +112 -27
- package/hooks/workflow/AGENTS.md +16 -0
- package/hooks/workflow/CLAUDE.md +1 -16
- package/installable-surfaces.manifest.json +1 -0
- package/output-styles/AGENTS.md +15 -0
- package/output-styles/CLAUDE.md +1 -15
- package/package.json +2 -1
- package/rules/AGENTS.md +61 -0
- package/rules/CLAUDE.md +1 -61
- package/rules/code-standards.md +5 -9
- package/rules/doc-prose-cuts.md +1 -1
- package/scripts/AGENTS.md +62 -0
- package/scripts/CLAUDE.md +1 -62
- package/scripts/codex_compat_materializer.py +4 -0
- package/scripts/dev_env_scripts_constants/AGENTS.md +21 -0
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -21
- package/scripts/sync_to_cursor/AGENTS.md +23 -0
- package/scripts/sync_to_cursor/CLAUDE.md +1 -23
- package/scripts/test_validate_instruction_pairs.py +90 -0
- package/scripts/test_verify_installable_package.py +5 -1
- package/scripts/tests/AGENTS.md +33 -0
- package/scripts/tests/CLAUDE.md +1 -33
- package/scripts/tests/test_codex_compat_materializer.py +36 -1
- package/scripts/validate_instruction_pairs.py +183 -0
- package/skills/AGENTS.md +72 -0
- package/skills/CLAUDE.md +1 -72
- package/skills/_shared/AGENTS.md +44 -0
- package/skills/_shared/CLAUDE.md +1 -44
- package/skills/_shared/advisor/AGENTS.md +9 -0
- package/skills/_shared/advisor/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/AGENTS.md +50 -0
- package/skills/_shared/pr-loop/CLAUDE.md +1 -50
- package/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
- package/skills/_shared/pr-loop/prompts/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +24 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -24
- package/skills/anthropic-plan/AGENTS.md +34 -0
- package/skills/anthropic-plan/CLAUDE.md +1 -34
- package/skills/anthropic-plan/scripts/AGENTS.md +11 -0
- package/skills/anthropic-plan/scripts/CLAUDE.md +1 -11
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +16 -0
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +1 -16
- package/skills/anthropic-plan/templates/AGENTS.md +13 -0
- package/skills/anthropic-plan/templates/CLAUDE.md +1 -13
- package/skills/anthropic-plan/workflow/AGENTS.md +14 -0
- package/skills/anthropic-plan/workflow/CLAUDE.md +1 -14
- package/skills/auditing-claude-config/AGENTS.md +21 -0
- package/skills/auditing-claude-config/CLAUDE.md +1 -21
- package/skills/autoconverge/AGENTS.md +36 -0
- package/skills/autoconverge/CLAUDE.md +1 -36
- package/skills/autoconverge/reference/AGENTS.md +16 -0
- package/skills/autoconverge/reference/CLAUDE.md +1 -16
- package/skills/autoconverge/workflow/AGENTS.md +26 -0
- package/skills/autoconverge/workflow/CLAUDE.md +1 -26
- package/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +16 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +1 -16
- package/skills/bugteam/AGENTS.md +30 -0
- package/skills/bugteam/CLAUDE.md +1 -30
- package/skills/bugteam/reference/AGENTS.md +20 -0
- package/skills/bugteam/reference/CLAUDE.md +1 -20
- package/skills/bugteam/reference/obstacles/AGENTS.md +24 -0
- package/skills/bugteam/reference/obstacles/CLAUDE.md +1 -24
- package/skills/bugteam/scripts/AGENTS.md +30 -0
- package/skills/bugteam/scripts/CLAUDE.md +1 -30
- package/skills/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +18 -0
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +1 -18
- package/skills/closeout/reference/handoff-prompt-template.md +1 -1
- package/skills/codex-review/AGENTS.md +46 -0
- package/skills/codex-review/CLAUDE.md +1 -46
- package/skills/codex-review/reference/AGENTS.md +15 -0
- package/skills/codex-review/reference/CLAUDE.md +1 -15
- package/skills/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +1 -18
- package/skills/codex-review/test_skill_scaffold.py +3 -3
- package/skills/copilot-review/AGENTS.md +18 -0
- package/skills/copilot-review/CLAUDE.md +1 -18
- package/skills/everything-search/AGENTS.md +17 -0
- package/skills/everything-search/CLAUDE.md +1 -17
- package/skills/fresh-branch/AGENTS.md +14 -0
- package/skills/fresh-branch/CLAUDE.md +1 -14
- package/skills/grok-spawn/AGENTS.md +28 -0
- package/skills/grok-spawn/CLAUDE.md +1 -28
- package/skills/pr-converge/AGENTS.md +32 -0
- package/skills/pr-converge/CLAUDE.md +1 -32
- package/skills/pr-converge/pr_converge_skill_constants/AGENTS.md +26 -0
- package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +1 -26
- package/skills/pr-converge/reference/AGENTS.md +28 -0
- package/skills/pr-converge/reference/CLAUDE.md +1 -28
- package/skills/pr-converge/reference/obstacles/AGENTS.md +23 -0
- package/skills/pr-converge/reference/obstacles/CLAUDE.md +1 -23
- package/skills/pr-converge/scripts/AGENTS.md +46 -0
- package/skills/pr-converge/scripts/CLAUDE.md +1 -46
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -18
- package/skills/pr-converge/workflows/AGENTS.md +16 -0
- package/skills/pr-converge/workflows/CLAUDE.md +1 -16
- package/skills/prototype/reference/honest-limitations.md +1 -1
- package/skills/rebase/AGENTS.md +32 -0
- package/skills/rebase/CLAUDE.md +1 -32
- package/skills/recall/AGENTS.md +30 -0
- package/skills/recall/CLAUDE.md +1 -30
- package/skills/remember/AGENTS.md +31 -0
- package/skills/remember/CLAUDE.md +1 -31
- package/skills/reviews/SKILL.md +1 -1
- package/skills/session-log/AGENTS.md +32 -0
- package/skills/session-log/CLAUDE.md +1 -32
- package/skills/session-tidy/AGENTS.md +36 -0
- package/skills/session-tidy/CLAUDE.md +1 -36
- package/skills/skill-builder/AGENTS.md +49 -0
- package/skills/skill-builder/CLAUDE.md +1 -49
- package/skills/skill-builder/references/AGENTS.md +25 -0
- package/skills/skill-builder/references/CLAUDE.md +1 -25
- package/skills/skill-builder/references/deterministic-elements.md +1 -1
- package/skills/skill-builder/templates/AGENTS.md +14 -0
- package/skills/skill-builder/templates/CLAUDE.md +1 -14
- package/skills/skill-builder/workflows/AGENTS.md +19 -0
- package/skills/skill-builder/workflows/CLAUDE.md +1 -19
- package/skills/task-build/AGENTS.md +29 -0
- package/skills/task-build/CLAUDE.md +1 -29
- package/skills/update/AGENTS.md +38 -0
- package/skills/update/CLAUDE.md +1 -38
- package/system-prompts/AGENTS.md +17 -0
- package/system-prompts/CLAUDE.md +1 -17
- package/system-prompts/software-engineer.xml +3 -3
- package/skills/imagegen/SKILL.md +0 -21
- package/skills/imagegen/scripts/config/__init__.py +0 -1
- package/skills/imagegen/scripts/config/constants.py +0 -28
- package/skills/imagegen/scripts/imagegen.py +0 -45
- package/skills/imagegen/scripts/imagegen_core.py +0 -528
- package/skills/imagegen/scripts/test_imagegen.py +0 -204
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
PostToolUse hooks that validate code quality after Claude writes or edits a file. Unlike the blocking hooks (which fire PreToolUse and can deny the write), these hooks run after the write and report errors that need a follow-up fix.
|
|
4
|
-
|
|
5
|
-
## Key files
|
|
6
|
-
|
|
7
|
-
| File | Event | What it does |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `mypy_validator.py` | PostToolUse (Write/Edit on `.py` files) | Runs mypy on the written file and blocks (via PostToolUse block decision) when type errors are found — catches missing attributes, wrong signatures, type mismatches, and import errors |
|
|
10
|
-
| `hook_format_validator.py` | PostToolUse | Validates that a hook script's output JSON matches the expected Claude Code hook-output schema |
|
|
11
|
-
| `test_mypy_validator.py` | — | Tests for `mypy_validator.py` |
|
|
12
|
-
| `test_hook_format_validator.py` | — | Tests for `hook_format_validator.py` |
|
|
13
|
-
|
|
14
|
-
## Conventions
|
|
15
|
-
|
|
16
|
-
- `mypy_validator.py` resolves the project root via `CLAUDE_PROJECT_ROOT` or `git rev-parse --show-toplevel`.
|
|
17
|
-
- It works on both WSL and Windows.
|
|
18
|
-
- Constants (timeouts, max displayed errors) are inline in `mypy_validator.py`; longer tunables go in `hooks_constants/`.
|
|
19
|
-
- The `eval_*.txt` files in this directory are evaluation exports used during development — not runtime artifacts.
|
|
20
|
-
- Tests run with `python -m pytest validation/test_<name>.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# hooks/validators
|
|
2
|
+
|
|
3
|
+
A library of check modules used by the validation hooks. Each module focuses on one concern; `run_all_validators.py` runs them all and collects results. These modules do not hook into Claude Code directly — they are imported by the validation hooks.
|
|
4
|
+
|
|
5
|
+
## Core infrastructure
|
|
6
|
+
|
|
7
|
+
| File | Role |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `validator_base.py` | Defines the `Violation` dataclass (`file`, `line`, `message`) used by every check module |
|
|
10
|
+
| `validator_defaults.py` | Default configuration values shared across check modules |
|
|
11
|
+
| `exempt_paths.py` | Path exemption logic — paths that checks skip (e.g. vendored code) |
|
|
12
|
+
| `output_formatter.py` | Formats `Violation` lists into human-readable output |
|
|
13
|
+
| `run_all_validators.py` | Entry point — runs every check module and aggregates results |
|
|
14
|
+
| `health_check.py` | Verifies that all validator dependencies (ruff, mypy) are reachable |
|
|
15
|
+
| `pyproject_config_discovery.py` | Shared walk-up primitive that resolves a tool's pyproject.toml config from an original target path, matching the `[tool.<name>]` table the tool owns |
|
|
16
|
+
| `python_style_helpers.py` | Shared source-line splitting and function-discovery helpers imported by `python_style_checks.py` |
|
|
17
|
+
|
|
18
|
+
## Check modules
|
|
19
|
+
|
|
20
|
+
| Module | What it checks |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `abbreviation_checks.py` | Abbreviated names in Python code |
|
|
23
|
+
| `code_quality_checks.py` | General code quality concerns (dead code, stub bodies, etc.) |
|
|
24
|
+
| `comment_checks.py` | Inline comment presence and content |
|
|
25
|
+
| `file_structure_checks.py` | File-level structural rules (line count, module layout) |
|
|
26
|
+
| `git_checks.py` | Git-state checks (untracked files, merge conflicts) |
|
|
27
|
+
| `magic_value_checks.py` | Magic numbers and strings |
|
|
28
|
+
| `mypy_integration.py` | Runs mypy and converts its output to `Violation` objects |
|
|
29
|
+
| `pr_reference_checks.py` | PR references in commit messages and changelogs |
|
|
30
|
+
| `python_antipattern_checks.py` | Python-specific anti-patterns (bare `except`, `Any`, etc.) |
|
|
31
|
+
| `python_style_checks.py` | Python style rules (naming, imports, type hints) |
|
|
32
|
+
| `react_checks.py` | React/TSX-specific checks (class component patterns, PureComponent usage) |
|
|
33
|
+
| `ruff_integration.py` | Runs ruff and converts its output to `Violation` objects |
|
|
34
|
+
| `security_checks.py` | Security anti-patterns (hardcoded secrets, unsafe calls) |
|
|
35
|
+
| `todo_checks.py` | TODO/FIXME markers without an associated issue reference |
|
|
36
|
+
| `type_safety_checks.py` | Type-safety rules (no `Any`, no `cast`, no `# type: ignore`) |
|
|
37
|
+
| `useless_test_checks.py` | Tests that check only existence or constant values |
|
|
38
|
+
|
|
39
|
+
## Subdirectory
|
|
40
|
+
|
|
41
|
+
| Directory | Role |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `config/` | Constants module (`directory_exemption_constants.py`) holding the exemption directory-segment names that `validate_proposed_file` staging keeps |
|
|
44
|
+
| `test_files/` | Fixture files used by the validator tests — not checked-in test code |
|
|
45
|
+
|
|
46
|
+
## Conventions
|
|
47
|
+
|
|
48
|
+
- Every check module exposes one or more functions that take file content or an AST and return a list of `Violation` objects.
|
|
49
|
+
- Test files live beside the modules they test: `test_<module>.py`. Run with `python -m pytest validators/test_<name>.py`.
|
|
50
|
+
- `conftest.py` provides shared test fixtures (sample files, fixture paths).
|
|
51
|
+
- `README.md` in this directory documents the validator design and how to add a new check.
|
|
@@ -1,51 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
A library of check modules used by the validation hooks. Each module focuses on one concern; `run_all_validators.py` runs them all and collects results. These modules do not hook into Claude Code directly — they are imported by the validation hooks.
|
|
4
|
-
|
|
5
|
-
## Core infrastructure
|
|
6
|
-
|
|
7
|
-
| File | Role |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `validator_base.py` | Defines the `Violation` dataclass (`file`, `line`, `message`) used by every check module |
|
|
10
|
-
| `validator_defaults.py` | Default configuration values shared across check modules |
|
|
11
|
-
| `exempt_paths.py` | Path exemption logic — paths that checks skip (e.g. vendored code) |
|
|
12
|
-
| `output_formatter.py` | Formats `Violation` lists into human-readable output |
|
|
13
|
-
| `run_all_validators.py` | Entry point — runs every check module and aggregates results |
|
|
14
|
-
| `health_check.py` | Verifies that all validator dependencies (ruff, mypy) are reachable |
|
|
15
|
-
| `pyproject_config_discovery.py` | Shared walk-up primitive that resolves a tool's pyproject.toml config from an original target path, matching the `[tool.<name>]` table the tool owns |
|
|
16
|
-
| `python_style_helpers.py` | Shared source-line splitting and function-discovery helpers imported by `python_style_checks.py` |
|
|
17
|
-
|
|
18
|
-
## Check modules
|
|
19
|
-
|
|
20
|
-
| Module | What it checks |
|
|
21
|
-
|---|---|
|
|
22
|
-
| `abbreviation_checks.py` | Abbreviated names in Python code |
|
|
23
|
-
| `code_quality_checks.py` | General code quality concerns (dead code, stub bodies, etc.) |
|
|
24
|
-
| `comment_checks.py` | Inline comment presence and content |
|
|
25
|
-
| `file_structure_checks.py` | File-level structural rules (line count, module layout) |
|
|
26
|
-
| `git_checks.py` | Git-state checks (untracked files, merge conflicts) |
|
|
27
|
-
| `magic_value_checks.py` | Magic numbers and strings |
|
|
28
|
-
| `mypy_integration.py` | Runs mypy and converts its output to `Violation` objects |
|
|
29
|
-
| `pr_reference_checks.py` | PR references in commit messages and changelogs |
|
|
30
|
-
| `python_antipattern_checks.py` | Python-specific anti-patterns (bare `except`, `Any`, etc.) |
|
|
31
|
-
| `python_style_checks.py` | Python style rules (naming, imports, type hints) |
|
|
32
|
-
| `react_checks.py` | React/TSX-specific checks (class component patterns, PureComponent usage) |
|
|
33
|
-
| `ruff_integration.py` | Runs ruff and converts its output to `Violation` objects |
|
|
34
|
-
| `security_checks.py` | Security anti-patterns (hardcoded secrets, unsafe calls) |
|
|
35
|
-
| `todo_checks.py` | TODO/FIXME markers without an associated issue reference |
|
|
36
|
-
| `type_safety_checks.py` | Type-safety rules (no `Any`, no `cast`, no `# type: ignore`) |
|
|
37
|
-
| `useless_test_checks.py` | Tests that check only existence or constant values |
|
|
38
|
-
|
|
39
|
-
## Subdirectory
|
|
40
|
-
|
|
41
|
-
| Directory | Role |
|
|
42
|
-
|---|---|
|
|
43
|
-
| `config/` | Constants module (`directory_exemption_constants.py`) holding the exemption directory-segment names that `validate_proposed_file` staging keeps |
|
|
44
|
-
| `test_files/` | Fixture files used by the validator tests — not checked-in test code |
|
|
45
|
-
|
|
46
|
-
## Conventions
|
|
47
|
-
|
|
48
|
-
- Every check module exposes one or more functions that take file content or an AST and return a list of `Violation` objects.
|
|
49
|
-
- Test files live beside the modules they test: `test_<module>.py`. Run with `python -m pytest validators/test_<name>.py`.
|
|
50
|
-
- `conftest.py` provides shared test fixtures (sample files, fixture paths).
|
|
51
|
-
- `README.md` in this directory documents the validator design and how to add a new check.
|
|
1
|
+
@AGENTS.md
|
|
@@ -7,14 +7,15 @@ Provides:
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import hashlib
|
|
10
|
+
import stat
|
|
10
11
|
import subprocess
|
|
11
12
|
import sys
|
|
12
13
|
from dataclasses import dataclass
|
|
13
|
-
from datetime import datetime
|
|
14
|
+
from datetime import datetime, timezone
|
|
15
|
+
from enum import StrEnum
|
|
14
16
|
from pathlib import Path
|
|
15
17
|
from typing import Dict, Optional
|
|
16
18
|
|
|
17
|
-
|
|
18
19
|
VALIDATOR_FILES = [
|
|
19
20
|
"python_style_checks.py",
|
|
20
21
|
"test_safety_checks.py",
|
|
@@ -25,15 +26,38 @@ VALIDATOR_FILES = [
|
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
class ValidatorStatus(StrEnum):
|
|
30
|
+
"""Displayed state for one required validator."""
|
|
31
|
+
|
|
32
|
+
READY = "[READY]"
|
|
33
|
+
FILE_REQUIRED = "[FILE REQUIRED]"
|
|
34
|
+
ACCESS_REQUIRED = "[ACCESS REQUIRED]"
|
|
35
|
+
|
|
36
|
+
|
|
28
37
|
@dataclass(frozen=True)
|
|
29
38
|
class ValidatorHealth:
|
|
30
39
|
"""Health status of a single validator."""
|
|
31
40
|
|
|
32
41
|
name: str
|
|
33
|
-
|
|
42
|
+
status: ValidatorStatus
|
|
34
43
|
error: Optional[str] = None
|
|
35
44
|
last_modified: Optional[datetime] = None
|
|
36
45
|
|
|
46
|
+
@property
|
|
47
|
+
def is_healthy(self) -> bool:
|
|
48
|
+
"""Return whether the validator is ready for use."""
|
|
49
|
+
return self.status is ValidatorStatus.READY
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def healthy(self) -> bool:
|
|
53
|
+
"""Return the readiness state for compatibility readers."""
|
|
54
|
+
return self.is_healthy
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def is_present(self) -> bool:
|
|
58
|
+
"""Return whether the validator file is present on disk."""
|
|
59
|
+
return self.status is not ValidatorStatus.FILE_REQUIRED
|
|
60
|
+
|
|
37
61
|
|
|
38
62
|
@dataclass(frozen=True)
|
|
39
63
|
class SystemHealth:
|
|
@@ -56,26 +80,33 @@ def check_validator_exists(validator_path: Path) -> ValidatorHealth:
|
|
|
56
80
|
"""
|
|
57
81
|
name = validator_path.stem
|
|
58
82
|
|
|
59
|
-
|
|
83
|
+
try:
|
|
84
|
+
validator_stat = validator_path.stat()
|
|
85
|
+
if not stat.S_ISREG(validator_stat.st_mode):
|
|
86
|
+
return ValidatorHealth(
|
|
87
|
+
name=name,
|
|
88
|
+
status=ValidatorStatus.FILE_REQUIRED,
|
|
89
|
+
error=f"Validator file required: {validator_path}",
|
|
90
|
+
)
|
|
91
|
+
validator_path.read_text(encoding="utf-8")
|
|
60
92
|
return ValidatorHealth(
|
|
61
93
|
name=name,
|
|
62
|
-
|
|
63
|
-
|
|
94
|
+
status=ValidatorStatus.READY,
|
|
95
|
+
last_modified=datetime.fromtimestamp(
|
|
96
|
+
validator_stat.st_mtime, tz=timezone.utc
|
|
97
|
+
),
|
|
64
98
|
)
|
|
65
|
-
|
|
66
|
-
try:
|
|
67
|
-
validator_path.read_text(encoding="utf-8")
|
|
68
|
-
mtime = datetime.fromtimestamp(validator_path.stat().st_mtime)
|
|
99
|
+
except FileNotFoundError:
|
|
69
100
|
return ValidatorHealth(
|
|
70
101
|
name=name,
|
|
71
|
-
|
|
72
|
-
|
|
102
|
+
status=ValidatorStatus.FILE_REQUIRED,
|
|
103
|
+
error=f"Validator file required: {validator_path}",
|
|
73
104
|
)
|
|
74
105
|
except (IOError, OSError, PermissionError) as error:
|
|
75
106
|
return ValidatorHealth(
|
|
76
107
|
name=name,
|
|
77
|
-
|
|
78
|
-
error=f"
|
|
108
|
+
status=ValidatorStatus.ACCESS_REQUIRED,
|
|
109
|
+
error=f"Validator read access requires attention: {error}",
|
|
79
110
|
)
|
|
80
111
|
|
|
81
112
|
|
|
@@ -135,7 +166,10 @@ def get_validator_version(validators_dir: Optional[Path] = None) -> str:
|
|
|
135
166
|
for validator_file in sorted(VALIDATOR_FILES):
|
|
136
167
|
validator_path = validators_dir / validator_file
|
|
137
168
|
if validator_path.exists():
|
|
138
|
-
|
|
169
|
+
try:
|
|
170
|
+
content = validator_path.read_bytes()
|
|
171
|
+
except (FileNotFoundError, OSError):
|
|
172
|
+
continue
|
|
139
173
|
hasher.update(content)
|
|
140
174
|
|
|
141
175
|
return hasher.hexdigest()[:8]
|
|
@@ -154,7 +188,7 @@ def get_system_health(validators_dir: Optional[Path] = None) -> SystemHealth:
|
|
|
154
188
|
validators_dir = Path(__file__).parent
|
|
155
189
|
|
|
156
190
|
validators = check_all_validators(validators_dir)
|
|
157
|
-
all_healthy = all(v.
|
|
191
|
+
all_healthy = all(v.is_healthy for v in validators.values())
|
|
158
192
|
|
|
159
193
|
optional_tools = {
|
|
160
194
|
"ruff": check_optional_tool("ruff"),
|
|
@@ -187,15 +221,14 @@ def print_health_report(health: SystemHealth) -> None:
|
|
|
187
221
|
|
|
188
222
|
print("Required Validators:")
|
|
189
223
|
for name, validator in sorted(health.validators.items()):
|
|
190
|
-
|
|
191
|
-
print(f" {status} {name}")
|
|
224
|
+
print(f" {validator.status.value} {name}")
|
|
192
225
|
if validator.error:
|
|
193
226
|
print(f" Error: {validator.error}")
|
|
194
227
|
print()
|
|
195
228
|
|
|
196
229
|
print("Optional Tools:")
|
|
197
230
|
for tool, available in sorted(health.optional_tools.items()):
|
|
198
|
-
status =
|
|
231
|
+
status = ValidatorStatus.READY.value if available else "[OPTIONAL]"
|
|
199
232
|
print(f" {status} {tool}")
|
|
200
233
|
print()
|
|
201
234
|
|
|
@@ -1,35 +1,92 @@
|
|
|
1
1
|
"""Tests for validator health checks."""
|
|
2
2
|
|
|
3
|
-
import tempfile
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
6
5
|
import pytest
|
|
7
6
|
|
|
8
7
|
from .health_check import (
|
|
8
|
+
SystemHealth,
|
|
9
9
|
ValidatorHealth,
|
|
10
|
+
ValidatorStatus,
|
|
10
11
|
check_validator_exists,
|
|
11
12
|
check_all_validators,
|
|
12
13
|
get_validator_version,
|
|
14
|
+
print_health_report,
|
|
13
15
|
)
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class TestValidatorExists:
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def
|
|
19
|
+
def test_existing_validator_is_ready(self, tmp_path: Path) -> None:
|
|
20
|
+
validator_path = tmp_path / "validator.py"
|
|
21
|
+
validator_path.write_text("print('hello')", encoding="utf-8")
|
|
22
|
+
|
|
23
|
+
result = check_validator_exists(validator_path)
|
|
24
|
+
|
|
25
|
+
assert result.is_healthy is True
|
|
26
|
+
assert result.healthy is result.is_healthy
|
|
27
|
+
assert result.status is ValidatorStatus.READY
|
|
28
|
+
assert result.error is None
|
|
29
|
+
assert result.is_present is True
|
|
30
|
+
|
|
31
|
+
def test_missing_validator_requires_a_file(self) -> None:
|
|
30
32
|
result = check_validator_exists(Path("/nonexistent/validator.py"))
|
|
31
|
-
assert result.
|
|
32
|
-
assert
|
|
33
|
+
assert result.is_healthy is False
|
|
34
|
+
assert result.status is ValidatorStatus.FILE_REQUIRED
|
|
35
|
+
assert result.is_present is False
|
|
36
|
+
assert "file required" in result.error.lower()
|
|
37
|
+
|
|
38
|
+
def test_unreadable_validator_reports_read_access_state(
|
|
39
|
+
self,
|
|
40
|
+
tmp_path: Path,
|
|
41
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
42
|
+
) -> None:
|
|
43
|
+
validator_path = tmp_path / "validator.py"
|
|
44
|
+
validator_path.write_text("print('ready')", encoding="utf-8")
|
|
45
|
+
|
|
46
|
+
def raise_read_error(*_args: object, **_kwargs: object) -> str:
|
|
47
|
+
raise OSError("permission detail")
|
|
48
|
+
|
|
49
|
+
monkeypatch.setattr(Path, "read_text", raise_read_error)
|
|
50
|
+
|
|
51
|
+
result = check_validator_exists(validator_path)
|
|
52
|
+
|
|
53
|
+
assert result.is_healthy is False
|
|
54
|
+
assert result.status is ValidatorStatus.ACCESS_REQUIRED
|
|
55
|
+
assert result.is_present is True
|
|
56
|
+
assert "read access requires attention" in result.error.lower()
|
|
57
|
+
|
|
58
|
+
def test_directory_at_validator_path_requires_a_file(self, tmp_path: Path) -> None:
|
|
59
|
+
validator_path = tmp_path / "validator.py"
|
|
60
|
+
validator_path.mkdir()
|
|
61
|
+
|
|
62
|
+
result = check_validator_exists(validator_path)
|
|
63
|
+
|
|
64
|
+
assert result.is_healthy is False
|
|
65
|
+
assert result.status is ValidatorStatus.FILE_REQUIRED
|
|
66
|
+
assert result.is_present is False
|
|
67
|
+
|
|
68
|
+
def test_validator_disappearance_reports_file_required(
|
|
69
|
+
self,
|
|
70
|
+
tmp_path: Path,
|
|
71
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
72
|
+
) -> None:
|
|
73
|
+
validator_path = tmp_path / "validator.py"
|
|
74
|
+
validator_path.write_text("print('ready')", encoding="utf-8")
|
|
75
|
+
|
|
76
|
+
original_read_text = Path.read_text
|
|
77
|
+
|
|
78
|
+
def remove_before_read(
|
|
79
|
+
each_path: Path, **all_keyword_arguments: object
|
|
80
|
+
) -> str:
|
|
81
|
+
each_path.unlink()
|
|
82
|
+
return original_read_text(each_path, **all_keyword_arguments)
|
|
83
|
+
|
|
84
|
+
monkeypatch.setattr(Path, "read_text", remove_before_read)
|
|
85
|
+
|
|
86
|
+
result = check_validator_exists(validator_path)
|
|
87
|
+
|
|
88
|
+
assert result.status is ValidatorStatus.FILE_REQUIRED
|
|
89
|
+
assert result.is_present is False
|
|
33
90
|
|
|
34
91
|
|
|
35
92
|
class TestCheckAllValidators:
|
|
@@ -41,17 +98,45 @@ class TestCheckAllValidators:
|
|
|
41
98
|
|
|
42
99
|
|
|
43
100
|
class TestGetValidatorVersion:
|
|
44
|
-
def test_version_changes_when_content_changes(self) -> None:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
101
|
+
def test_version_changes_when_content_changes(self, tmp_path: Path) -> None:
|
|
102
|
+
validator_file = tmp_path / "python_style_checks.py"
|
|
103
|
+
|
|
104
|
+
validator_file.write_text("# version 1")
|
|
105
|
+
version1 = get_validator_version(tmp_path)
|
|
106
|
+
|
|
107
|
+
validator_file.write_text("# version 2 - different content")
|
|
108
|
+
version2 = get_validator_version(tmp_path)
|
|
109
|
+
|
|
110
|
+
assert version1 != version2
|
|
111
|
+
assert isinstance(version1, str)
|
|
112
|
+
assert len(version1) > 0
|
|
113
|
+
|
|
48
114
|
|
|
49
|
-
|
|
50
|
-
|
|
115
|
+
def test_print_health_report_distinguishes_validator_states(
|
|
116
|
+
capsys: pytest.CaptureFixture[str],
|
|
117
|
+
) -> None:
|
|
118
|
+
health = SystemHealth(
|
|
119
|
+
all_healthy=False,
|
|
120
|
+
validators={
|
|
121
|
+
"missing_validator": ValidatorHealth(
|
|
122
|
+
name="missing_validator",
|
|
123
|
+
status=ValidatorStatus.FILE_REQUIRED,
|
|
124
|
+
error="Validator file required: missing_validator.py",
|
|
125
|
+
),
|
|
126
|
+
"unreadable_validator": ValidatorHealth(
|
|
127
|
+
name="unreadable_validator",
|
|
128
|
+
status=ValidatorStatus.ACCESS_REQUIRED,
|
|
129
|
+
error="Validator read access requires attention: permission detail",
|
|
130
|
+
),
|
|
131
|
+
},
|
|
132
|
+
python_version="3.12.0",
|
|
133
|
+
optional_tools={"mypy": True, "ruff": False},
|
|
134
|
+
)
|
|
51
135
|
|
|
52
|
-
|
|
53
|
-
version2 = get_validator_version(temp_path)
|
|
136
|
+
print_health_report(health)
|
|
54
137
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
138
|
+
report = capsys.readouterr().out
|
|
139
|
+
assert "[FILE REQUIRED] missing_validator" in report
|
|
140
|
+
assert "[ACCESS REQUIRED] unreadable_validator" in report
|
|
141
|
+
assert "[READY] mypy" in report
|
|
142
|
+
assert "[OPTIONAL] ruff" in report
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# hooks/workflow
|
|
2
|
+
|
|
3
|
+
PostToolUse hooks that run after Claude writes a file. They do not block the write; they run follow-up side effects — reformatting the written file and resetting the investigation tracker.
|
|
4
|
+
|
|
5
|
+
## Key files
|
|
6
|
+
|
|
7
|
+
| File | Event | What it does |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `auto_formatter.py` | PostToolUse (Write/Edit) | Runs the project's auto-formatter (ruff, prettier, etc.) on the written file and sends a desktop notification when formatting changes are applied |
|
|
10
|
+
| `investigation_tracker_reset.py` | PostToolUse | Resets the investigation tracker state after a tool call |
|
|
11
|
+
| `test_auto_formatter.py` | — | Tests for `auto_formatter.py` |
|
|
12
|
+
|
|
13
|
+
## Conventions
|
|
14
|
+
|
|
15
|
+
- `auto_formatter.py` exits 0 even on failure — it logs warnings to stderr but does not break Claude's flow.
|
|
16
|
+
- Tests run with `python -m pytest workflow/test_<name>.py`.
|
package/hooks/workflow/CLAUDE.md
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
PostToolUse hooks that run after Claude writes a file. They do not block the write; they run follow-up side effects — reformatting the written file and resetting the investigation tracker.
|
|
4
|
-
|
|
5
|
-
## Key files
|
|
6
|
-
|
|
7
|
-
| File | Event | What it does |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `auto_formatter.py` | PostToolUse (Write/Edit) | Runs the project's auto-formatter (ruff, prettier, etc.) on the written file and sends a desktop notification when formatting changes are applied |
|
|
10
|
-
| `investigation_tracker_reset.py` | PostToolUse | Resets the investigation tracker state after a tool call |
|
|
11
|
-
| `test_auto_formatter.py` | — | Tests for `auto_formatter.py` |
|
|
12
|
-
|
|
13
|
-
## Conventions
|
|
14
|
-
|
|
15
|
-
- `auto_formatter.py` exits 0 even on failure — it logs warnings to stderr but does not break Claude's flow.
|
|
16
|
-
- Tests run with `python -m pytest workflow/test_<name>.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# output-styles
|
|
2
|
+
|
|
3
|
+
Output-style instruction files installed into `~/.claude/output-styles/` by `bin/install.mjs`. Each file instructs an agent or session to respond in a specific voice or format.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
No output-style instruction files ship in this directory. The active caveman behavior lives in `agents/caveman.md`.
|
|
8
|
+
|
|
9
|
+
## Format
|
|
10
|
+
|
|
11
|
+
Each file uses YAML frontmatter (`name`, `description`, optional `keep-coding-instructions`) followed by Markdown instructions. The `keep-coding-instructions: true` flag tells Claude Code to keep the session's coding rules even when this style is active.
|
|
12
|
+
|
|
13
|
+
## Adding a style
|
|
14
|
+
|
|
15
|
+
Create a `.md` file with frontmatter and behavioral instructions, then run `bin/install.mjs` to copy it to `~/.claude/output-styles/`.
|
package/output-styles/CLAUDE.md
CHANGED
|
@@ -1,15 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Output-style instruction files installed into `~/.claude/output-styles/` by `bin/install.mjs`. Each file instructs an agent or session to respond in a specific voice or format.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
No output-style instruction files ship in this directory. The active caveman behavior lives in `agents/caveman.md`.
|
|
8
|
-
|
|
9
|
-
## Format
|
|
10
|
-
|
|
11
|
-
Each file uses YAML frontmatter (`name`, `description`, optional `keep-coding-instructions`) followed by Markdown instructions. The `keep-coding-instructions: true` flag tells Claude Code to keep the session's coding rules even when this style is active.
|
|
12
|
-
|
|
13
|
-
## Adding a style
|
|
14
|
-
|
|
15
|
-
Create a `.md` file with frontmatter and behavioral instructions, then run `bin/install.mjs` to copy it to `~/.claude/output-styles/`.
|
|
1
|
+
@AGENTS.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-dev-env",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"installable-surfaces.manifest.json",
|
|
27
27
|
"_shared/",
|
|
28
28
|
"audit-rubrics/",
|
|
29
|
+
"AGENTS.md",
|
|
29
30
|
"CLAUDE.md",
|
|
30
31
|
"!**/__pycache__/**",
|
|
31
32
|
"!**/*.py[cod]",
|
package/rules/AGENTS.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- "**/rules/**"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# rules
|
|
7
|
+
|
|
8
|
+
Rule files installed into `~/.claude/rules/` by `bin/install.mjs`. A rule without `paths:` frontmatter loads at the start of every session; a rule with `paths:` frontmatter loads only when the session works with a file its globs match. The `InstructionsLoaded` log records that match as a `path_glob_match` event. Each `.md` file covers one named rule; hook-enforced rules are also backed by a Python hook in `hooks/`.
|
|
9
|
+
|
|
10
|
+
## Files
|
|
11
|
+
|
|
12
|
+
| File | Rule |
|
|
13
|
+
|---|---|
|
|
14
|
+
| `agent-spawn-protocol.md` | Check context sufficiency before a spawn and ask subagents for file-and-line answers; `/prompt-generator` is recommended for a complex or user-facing spawn |
|
|
15
|
+
| `anti-corollary-tests.md` | Tests must carry information: no corollary matrices over canonical reductions, no suite that only matches a dead-implementation default, stated mutation in the audit lane |
|
|
16
|
+
| `ask-user-question-required.md` | Every user-directed question goes through the `AskUserQuestion` tool — no plain-text questions |
|
|
17
|
+
| `bdd.md` | BDD discovery-driven development workflow and Example Mapping reference |
|
|
18
|
+
| `claims-as-quotes.md` | On agent reports, hand-offs, review verdicts, and PR or commit prose, a design-gating claim travels with its quoted lines and `path:line` reference; chat keeps research-mode compact citations; a claim without its quote is a lead to check |
|
|
19
|
+
| `cleanup-temp-files.md` | Remove temporary files created during a task when the task is complete |
|
|
20
|
+
| `code-standards.md` | Pointer to `CODE_RULES.md` as the single source of truth, including §8 (TDD) and §7 (right-sizing); BDD is the outer process and TDD the inner loop |
|
|
21
|
+
| `confirm-implementation-forks.md` | Stop and ask when two or more workable implementation paths change the deliverable |
|
|
22
|
+
| `conservative-action.md` | Research and recommend when intent is ambiguous; act only on explicit request |
|
|
23
|
+
| `context7.md` | Use Context7 MCP to fetch current library docs; always prefer live docs over built-in knowledge |
|
|
24
|
+
| `destructive-commands.md` | Allowed removal forms and the ephemeral namespace the `destructive_command_blocker` auto-allows; keep destructive literals out of a Bash command string even as data |
|
|
25
|
+
| `doc-inventory-integrity.md` | Three inventory shapes stay in step with the code: a per-directory `CLAUDE.md` file list, a package `README`/`SKILL.md` inventory, and an env-var summary table |
|
|
26
|
+
| `doc-prose-cuts.md` | Four sentence shapes to cut from prose: exclusion claims, justification sentences, conversation references, and time references |
|
|
27
|
+
| `docstring-prose-matches-implementation.md` | Prose enumerations in docstrings cover every behavior the body applies |
|
|
28
|
+
| `durable-post-artifacts.md` | GitHub post bodies never reference volatile scratch paths; text embeds inline and binary artifacts upload to the `artifacts` release with the permanent URL linked |
|
|
29
|
+
| `eli11-replies.md` | Every chat reply the user reads follows one shape: action first, detail last, few words; `plain-language.md` governs word choice, this rule governs reply length and shape |
|
|
30
|
+
| `explore-thoroughly.md` | Read relevant files and map existing patterns before proposing a change |
|
|
31
|
+
| `falsify-before-green.md` | A check's green counts as evidence only after that same check ran red on a named break, with a passing control beside it |
|
|
32
|
+
| `file-global-constants.md` | File-global constants need at least two same-file references; otherwise move value to `config/` |
|
|
33
|
+
| `filesystem-search.md` | Every filesystem search names a scope; `es.exe`, `Glob`, `Grep`, and `Read` are equally sanctioned, and the `unscoped_search_blocker` denies a walk from a root |
|
|
34
|
+
| `gh-cli-conventions.md` | `--body-file` for every `gh` body; `--paginate --slurp` piped to external `jq` for every paginated list read |
|
|
35
|
+
| `git-workflow.md` | PR workflow: always create as draft, one commit per review stage, never commit working docs or images; carries the review-response protocol and a See-also block for its seven siblings |
|
|
36
|
+
| `hedging-claims.md` | State the evidence or name the claim unverified; the `hedging_language_blocker` Stop hook sends a hedged response back for a re-check |
|
|
37
|
+
| `long-horizon-autonomy.md` | Autonomous-run behaviors: act on what you have, do not end on a promise, delegate and keep working |
|
|
38
|
+
| `measurement-denominators.md` | Every reported count names what it scanned and carries its denominator; a rate needs two runs; the consumer cross-checks the count against the scope its denominator names |
|
|
39
|
+
| `nas-ssh-invocation.md` | Reach the NAS through the paramiko-backed `nas_ssh_key.py` runner, which signs in-process; every ssh-family client reads the key through file permissions, refuses it, and stalls an unattended run on a password prompt |
|
|
40
|
+
| `no-cross-skill-duplicate-helpers.md` | Within one skill a duplicated helper is blocked; across two skill folders a small self-contained copy is a sanctioned isolation tradeoff that draws a non-blocking advisory naming the source skill |
|
|
41
|
+
| `orphan-css-class.md` | Every `class="..."` attribute in Python-generated markup has a matching selector in the `<style>` block |
|
|
42
|
+
| `opus5-communication-contract.md` | Visible concision, one-sentence first progress, important-change-only updates, outcome-first finals, thinking-disabled tool narration (`opus5-communication-contract-v1`) |
|
|
43
|
+
| `paired-test-coverage.md` | A public function omitted by a module's established paired test suite must get a behavioral test |
|
|
44
|
+
| `parallel-tools.md` | Make all independent tool calls in a single response |
|
|
45
|
+
| `plain-illustrative-docstrings.md` | Public docstring narrative reads plainly and shows behavior with a diagram block (a `::` example or a doctest), painting a concrete scene a general developer follows on first read; a run-on backstop hook, a prose-wall backstop hook, and Category O9 audit enforce it |
|
|
46
|
+
| `plain-language.md` | Everyday words, short active sentences, lead with the answer |
|
|
47
|
+
| `prompt-workflow-context-controls.md` | Keep prompt-workflow instruction layers small and stable; load heavy skills on demand |
|
|
48
|
+
| `re-stage-before-commit.md` | Stage the files edited this session before `git commit`; the session edit stage gate denies a commit that leaves a tracked session edit unstaged, with `-a`, a pathspec, a preceding `git add`, and `# partial-commit` as escapes |
|
|
49
|
+
| `research-mode.md` | Three anti-hallucination constraints: say "I don't know", verify with citations, quote for factual grounding |
|
|
50
|
+
| `shell-invocation.md` | Windows shell commands run through `pwsh`; no `$(...)`, backtick, or process substitution in a Bash tool command |
|
|
51
|
+
| `testing.md` | Test quality and infrastructure standards |
|
|
52
|
+
| `vault-context.md` | Search Obsidian vault for prior sessions and decisions before substantive project work |
|
|
53
|
+
| `verify-before-asking.md` | Answer questions by inspecting files or running tools before asking; recalled facts expire until re-checked this session |
|
|
54
|
+
| `verify-runtime-state.md` | A "component is fine / not at fault" verdict rests on a live probe this session, never code reading or prior-session memory |
|
|
55
|
+
| `windows-filesystem-safe.md` | Use safe `rmtree` patterns on Windows; `mkdirSync` with `recursive: true` on possibly-existing paths |
|
|
56
|
+
| `workers-done-before-complete.md` | A task reaches `completed` only when every spawned worker has finished and its results are merged into run state |
|
|
57
|
+
| `workflow-substitution-slots.md` | Per-iteration values in `.workflow.js` templates use angle-bracket slots |
|
|
58
|
+
|
|
59
|
+
## Hook enforcement
|
|
60
|
+
|
|
61
|
+
Rules marked with ⚡ in `~/.claude/docs/CODE_RULES.md` are backed by a blocking hook in `hooks/blocking/`. Rules without a hook are judgment-based and enforced via audit rubrics (`audit-rubrics/`).
|