claude-dev-env 2.28.0 → 2.29.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 (212) hide show
  1. package/.agents/agents/AGENTS.md +0 -31
  2. package/.agents/agents/clean-coder.md +1 -1
  3. package/.agents/agents/test_agent_frontmatter.py +3 -1
  4. package/.agents/skills/AGENTS.md +0 -70
  5. package/.agents/skills/_shared/AGENTS.md +0 -44
  6. package/.agents/skills/_shared/advisor/AGENTS.md +0 -8
  7. package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -57
  8. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -8
  9. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -34
  10. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -23
  11. package/.agents/skills/autoconverge/AGENTS.md +0 -35
  12. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -15
  13. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -25
  14. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -15
  15. package/.agents/skills/everything-search/AGENTS.md +0 -16
  16. package/.agents/skills/fresh-branch/AGENTS.md +0 -13
  17. package/.agents/skills/grok-spawn/AGENTS.md +0 -27
  18. package/.agents/skills/orchestrator/.claude/CLAUDE.md +1 -0
  19. package/.agents/skills/orchestrator/AGENTS.md +1 -0
  20. package/.agents/skills/orchestrator/SKILL.md +44 -53
  21. package/.agents/skills/orchestrator/reference/.claude/CLAUDE.md +1 -0
  22. package/.agents/skills/orchestrator/reference/AGENTS.md +1 -0
  23. package/.agents/skills/orchestrator/reference/consult-the-orchestrator.md +70 -0
  24. package/.agents/skills/orchestrator/reference/executor-consult-block.md +62 -0
  25. package/.agents/skills/orchestrator/reference/host-detect.md +15 -0
  26. package/.agents/skills/orchestrator/test_orchestrator_skill_contract.py +62 -0
  27. package/.agents/skills/orchestrator-refresh/SKILL.md +16 -34
  28. package/.agents/skills/rebase/AGENTS.md +0 -31
  29. package/.agents/skills/session-log/AGENTS.md +0 -31
  30. package/.agents/skills/session-tidy/AGENTS.md +0 -35
  31. package/.agents/skills/skill-builder/AGENTS.md +0 -48
  32. package/.agents/skills/skill-builder/references/AGENTS.md +0 -24
  33. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -13
  34. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -18
  35. package/.agents/skills/task-build/AGENTS.md +0 -28
  36. package/.agents/skills/update/AGENTS.md +0 -37
  37. package/.agents/skills-archived/AGENTS.md +0 -44
  38. package/.agents/skills-archived/anthropic-plan/AGENTS.md +0 -33
  39. package/.agents/skills-archived/anthropic-plan/scripts/AGENTS.md +0 -10
  40. package/.agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -15
  41. package/.agents/skills-archived/anthropic-plan/templates/AGENTS.md +0 -12
  42. package/.agents/skills-archived/anthropic-plan/workflow/AGENTS.md +0 -13
  43. package/.agents/skills-archived/auditing-claude-config/AGENTS.md +0 -20
  44. package/.agents/skills-archived/bugteam/AGENTS.md +0 -29
  45. package/.agents/skills-archived/bugteam/reference/AGENTS.md +0 -19
  46. package/.agents/skills-archived/bugteam/reference/obstacles/AGENTS.md +0 -23
  47. package/.agents/skills-archived/bugteam/scripts/AGENTS.md +0 -29
  48. package/.agents/skills-archived/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -17
  49. package/.agents/skills-archived/codex-review/AGENTS.md +0 -45
  50. package/.agents/skills-archived/codex-review/reference/AGENTS.md +0 -14
  51. package/.agents/skills-archived/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
  52. package/.agents/skills-archived/codex-review/test_skill_scaffold.py +13 -3
  53. package/.agents/skills-archived/copilot-review/AGENTS.md +0 -17
  54. package/.agents/skills-archived/pr-converge/AGENTS.md +0 -31
  55. package/.agents/skills-archived/pr-converge/pr_converge_skill_constants/AGENTS.md +0 -25
  56. package/.agents/skills-archived/pr-converge/reference/AGENTS.md +0 -27
  57. package/.agents/skills-archived/pr-converge/reference/obstacles/AGENTS.md +0 -22
  58. package/.agents/skills-archived/pr-converge/scripts/AGENTS.md +0 -45
  59. package/.agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
  60. package/.agents/skills-archived/pr-converge/workflows/AGENTS.md +0 -15
  61. package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
  62. package/.agents/skills-archived/recall/AGENTS.md +0 -29
  63. package/.agents/skills-archived/remember/AGENTS.md +0 -30
  64. package/AGENTS.md +0 -112
  65. package/_shared/AGENTS.md +0 -16
  66. package/_shared/advisor/AGENTS.md +0 -21
  67. package/_shared/advisor/advisor-protocol.md +4 -1
  68. package/_shared/advisor/reference/consult-format.md +4 -2
  69. package/_shared/pr-loop/AGENTS.md +0 -27
  70. package/_shared/pr-loop/scripts/AGENTS.md +0 -49
  71. package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +0 -41
  72. package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
  73. package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
  74. package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +0 -25
  75. package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +0 -25
  76. package/_shared/pr-loop/scripts/tests/AGENTS.md +0 -43
  77. package/_shared/process-tree/AGENTS.md +0 -40
  78. package/audit-rubrics/AGENTS.md +0 -42
  79. package/audit-rubrics/category_rubrics/AGENTS.md +0 -36
  80. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +16 -29
  81. package/audit-rubrics/prompts/AGENTS.md +0 -36
  82. package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
  83. package/bin/AGENTS.md +0 -118
  84. package/bin/install.test.mjs +1 -1
  85. package/commands/AGENTS.md +0 -14
  86. package/docs/AGENTS.md +0 -31
  87. package/docs/CODE_RULES.md +3 -3
  88. package/docs/agent-spawn-protocol.md +1 -1
  89. package/docs/references/AGENTS.md +0 -16
  90. package/docs/references/prose-style-enforcement.md +5 -9
  91. package/hooks/AGENTS.md +0 -27
  92. package/hooks/advisory/AGENTS.md +0 -15
  93. package/hooks/blocking/AGENTS.md +0 -122
  94. package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +0 -27
  95. package/hooks/blocking/code_rules_docstrings.py +10 -2138
  96. package/hooks/blocking/code_rules_enforcer.py +0 -121
  97. package/hooks/blocking/code_rules_imports_logging.py +1 -236
  98. package/hooks/blocking/code_rules_shared.py +23 -0
  99. package/hooks/blocking/code_rules_test_layout.py +8 -8
  100. package/hooks/blocking/config/AGENTS.md +0 -9
  101. package/hooks/blocking/config/prose_style_enforcement_constants.py +4 -2
  102. package/hooks/blocking/config/test_prose_style_enforcement_constants.py +5 -1
  103. package/hooks/blocking/inventory_intent_records/AGENTS.md +0 -25
  104. package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +0 -25
  105. package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +0 -23
  106. package/hooks/blocking/precommit_code_rules_gate.py +8 -43
  107. package/hooks/blocking/state_description_blocker.py +1 -7
  108. package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +0 -29
  109. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
  110. package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +0 -8
  111. package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +11 -112
  112. package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +0 -1
  113. package/hooks/blocking/test_code_rules_enforcer_split_entry_1.py +1 -18
  114. package/hooks/blocking/test_code_rules_shared.py +12 -0
  115. package/hooks/blocking/test_precommit_code_rules_gate.py +32 -179
  116. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -1
  117. package/hooks/blocking/test_state_description_blocker.py +6 -4
  118. package/hooks/blocking/test_stop_dispatcher.py +5 -29
  119. package/hooks/git-hooks/AGENTS.md +0 -31
  120. package/hooks/git-hooks/git_hooks_constants/AGENTS.md +0 -20
  121. package/hooks/hooks_constants/AGENTS.md +0 -104
  122. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -1
  123. package/hooks/hooks_constants/code_rules_enforcer_constants.py +3 -0
  124. package/hooks/hooks_constants/messages.py +0 -2
  125. package/hooks/hooks_constants/precommit_code_rules_gate_constants.py +3 -17
  126. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -2
  127. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -1
  128. package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +7 -0
  129. package/hooks/hooks_constants/test_messages.py +5 -3
  130. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -2
  131. package/hooks/lifecycle/AGENTS.md +0 -17
  132. package/hooks/observability/AGENTS.md +0 -19
  133. package/hooks/session/AGENTS.md +0 -37
  134. package/hooks/validation/AGENTS.md +0 -19
  135. package/hooks/validators/AGENTS.md +0 -51
  136. package/hooks/workflow/AGENTS.md +0 -15
  137. package/output-styles/AGENTS.md +0 -14
  138. package/package.json +1 -1
  139. package/rules/AGENTS.md +0 -58
  140. package/rules/claims-as-quotes.md +0 -10
  141. package/rules/code-standards.md +6 -6
  142. package/rules/explore-thoroughly.md +0 -1
  143. package/rules/failure-blast-radius.md +0 -8
  144. package/rules/falsify-before-green.md +0 -8
  145. package/rules/file-global-constants.md +2 -2
  146. package/rules/filesystem-search.md +1 -1
  147. package/rules/git-workflow.md +1 -9
  148. package/rules/hedging-claims.md +2 -6
  149. package/rules/long-horizon-autonomy.md +1 -1
  150. package/rules/measurement-denominators.md +0 -9
  151. package/rules/research-mode.md +0 -6
  152. package/rules/verify-before-asking.md +0 -5
  153. package/rules/verify-runtime-state.md +0 -5
  154. package/scripts/AGENTS.md +0 -55
  155. package/scripts/codex_compat_materializer.py +0 -12
  156. package/scripts/dev_env_scripts_constants/AGENTS.md +0 -20
  157. package/scripts/sync_to_cursor/AGENTS.md +0 -22
  158. package/scripts/sync_to_cursor/rules.py +0 -10
  159. package/scripts/tests/AGENTS.md +0 -34
  160. package/scripts/tests/test_engine.py +0 -1
  161. package/scripts/tests/test_rules.py +0 -1
  162. package/scripts/tests/test_sync_to_cursor.py +0 -1
  163. package/system-prompts/AGENTS.md +0 -24
  164. package/system-prompts/software-engineer.xml +3 -3
  165. package/hooks/blocking/code_rules_dead_argparse_argument.py +0 -554
  166. package/hooks/blocking/code_rules_dead_config_field.py +0 -568
  167. package/hooks/blocking/code_rules_dead_dataclass_field.py +0 -348
  168. package/hooks/blocking/code_rules_dead_module_constant.py +0 -757
  169. package/hooks/blocking/code_rules_dead_split_branch.py +0 -225
  170. package/hooks/blocking/code_rules_mock_completeness.py +0 -295
  171. package/hooks/blocking/code_rules_scope_binding.py +0 -151
  172. package/hooks/blocking/code_rules_unused_imports.py +0 -197
  173. package/hooks/blocking/hedging_language_blocker.py +0 -221
  174. package/hooks/blocking/intent_only_ending_blocker.py +0 -148
  175. package/hooks/blocking/test_code_rules_enforcer_dead_argparse_argument.py +0 -534
  176. package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +0 -846
  177. package/hooks/blocking/test_code_rules_enforcer_dead_dataclass_field.py +0 -507
  178. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +0 -679
  179. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_alias.py +0 -133
  180. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +0 -103
  181. package/hooks/blocking/test_code_rules_enforcer_dead_split_branch.py +0 -105
  182. package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +0 -425
  183. package/hooks/blocking/test_code_rules_enforcer_docstring_cardinal_family.py +0 -176
  184. package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +0 -385
  185. package/hooks/blocking/test_code_rules_enforcer_docstring_fallback_branch.py +0 -398
  186. package/hooks/blocking/test_code_rules_enforcer_docstring_field_runmode_outcome.py +0 -129
  187. package/hooks/blocking/test_code_rules_enforcer_docstring_inline_literal_claim.py +0 -93
  188. package/hooks/blocking/test_code_rules_enforcer_docstring_length_constant_superlative.py +0 -198
  189. package/hooks/blocking/test_code_rules_enforcer_docstring_mark_glyph_enumeration.py +0 -262
  190. package/hooks/blocking/test_code_rules_enforcer_docstring_no_consumer.py +0 -93
  191. package/hooks/blocking/test_code_rules_enforcer_docstring_no_network.py +0 -115
  192. package/hooks/blocking/test_code_rules_enforcer_docstring_raises_largezipfile.py +0 -226
  193. package/hooks/blocking/test_code_rules_enforcer_docstring_returns_plural_cardinality.py +0 -207
  194. package/hooks/blocking/test_code_rules_enforcer_docstring_step_dispatch.py +0 -262
  195. package/hooks/blocking/test_code_rules_enforcer_docstring_type_checking_gate.py +0 -164
  196. package/hooks/blocking/test_code_rules_enforcer_docstring_unguarded_payload.py +0 -188
  197. package/hooks/blocking/test_code_rules_enforcer_import_block_sort.py +0 -157
  198. package/hooks/blocking/test_code_rules_enforcer_split_mocks_1.py +0 -303
  199. package/hooks/blocking/test_code_rules_enforcer_split_mocks_2.py +0 -111
  200. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +0 -656
  201. package/hooks/blocking/test_hedging_language_blocker.py +0 -261
  202. package/hooks/blocking/test_intent_only_ending_blocker.py +0 -209
  203. package/hooks/hooks_constants/dead_argparse_argument_constants.py +0 -28
  204. package/hooks/hooks_constants/dead_config_field_constants.py +0 -39
  205. package/hooks/hooks_constants/dead_dataclass_field_constants.py +0 -25
  206. package/hooks/hooks_constants/dead_module_constant_constants.py +0 -30
  207. package/hooks/hooks_constants/hedging_uncertainty_constants.py +0 -42
  208. package/hooks/hooks_constants/test_dispatcher_constants_docstrings.py +0 -44
  209. package/rules/conservative-action.md +0 -17
  210. package/rules/context7.md +0 -8
  211. package/rules/few-words.md +0 -3
  212. package/rules/parallel-tools.md +0 -23
@@ -90,7 +90,7 @@ def test_dispatch_re_emits_first_block_with_system_message_and_suppress(
90
90
  HostedHookRun(captured_stdout="", did_crash=False),
91
91
  HostedHookRun(
92
92
  captured_stdout=_block_json(
93
- "hedging blocked",
93
+ "keep fields",
94
94
  system_message="rewrite the ending",
95
95
  suppress_output=True,
96
96
  ),
@@ -108,15 +108,15 @@ def test_dispatch_re_emits_first_block_with_system_message_and_suppress(
108
108
  monkeypatch.setattr(
109
109
  "stop_dispatcher.ALL_STOP_HOSTED_HOOK_PATHS",
110
110
  (
111
- "blocking/hedging_language_blocker.py",
111
+ "blocking/first_stub_hook.py",
112
112
  "blocking/question_to_user_enforcer.py",
113
- "blocking/intent_only_ending_blocker.py",
113
+ "blocking/second_stub_hook.py",
114
114
  ),
115
115
  )
116
116
  dispatch('{"session_id": "test"}')
117
117
  emitted_payload = json.loads(capsys.readouterr().out.strip())
118
118
  assert emitted_payload["decision"] == "block"
119
- assert emitted_payload["reason"] == "hedging blocked"
119
+ assert emitted_payload["reason"] == "keep fields"
120
120
  assert emitted_payload["systemMessage"] == "rewrite the ending"
121
121
  assert emitted_payload["suppressOutput"] is True
122
122
 
@@ -132,7 +132,7 @@ def test_dispatch_writes_nothing_when_no_hook_blocks(
132
132
  )
133
133
  monkeypatch.setattr(
134
134
  "stop_dispatcher.ALL_STOP_HOSTED_HOOK_PATHS",
135
- ("blocking/hedging_language_blocker.py",),
135
+ ("blocking/first_stub_hook.py",),
136
136
  )
137
137
  dispatch('{"session_id": "test"}')
138
138
  assert capsys.readouterr().out == ""
@@ -151,30 +151,6 @@ def test_dispatcher_exits_zero_on_empty_payload() -> None:
151
151
  assert completed.stdout.strip() == ""
152
152
 
153
153
 
154
- def test_dispatcher_blocks_hedging_message_matching_standalone() -> None:
155
- """A hedging last_assistant_message blocks through the dispatcher."""
156
- payload_text = json.dumps(
157
- {
158
- "stop_hook_active": False,
159
- "last_assistant_message": "This is probably correct.",
160
- }
161
- )
162
- environment_by_key = {**os.environ, "CLAUDE_PROSE_STYLE_ENFORCEMENT": "1"}
163
- completed = subprocess.run(
164
- [sys.executable, _DISPATCHER_SCRIPT],
165
- check=False,
166
- input=payload_text,
167
- capture_output=True,
168
- text=True,
169
- encoding="utf-8",
170
- env=environment_by_key,
171
- )
172
- assert completed.returncode == 0
173
- parsed = json.loads(completed.stdout)
174
- assert parsed["decision"] == "block"
175
- assert "probably" in parsed["reason"].lower() or "hedging" in parsed["reason"].lower()
176
-
177
-
178
154
  def test_dispatcher_imports_standalone_with_only_blocking_on_the_path() -> None:
179
155
  """The dispatcher's bootstrap resolves hooks_constants without hooks/ on PYTHONPATH."""
180
156
  subprocess_environment = {**os.environ, "PYTHONPATH": str(_BLOCKING_DIR)}
@@ -1,32 +1 @@
1
- # hooks/git-hooks
2
1
 
3
- Native git hooks that run outside the Claude Code lifecycle — invoked directly by git at commit and push time. The installer copies these scripts into the user's shared git-hooks directory (`core.hooksPath`).
4
-
5
- ## Key files
6
-
7
- | File | Git hook | What it does |
8
- |---|---|---|
9
- | `pre_commit.py` | `pre-commit` | Runs immediate CODE_RULES and terminology validation over staged changes; exits 1 when any staged file has a blocking violation. CI runs package tests for package Python changes. |
10
- | `pre_push.py` | `pre-push` | Blocks a push that would land a non-`main` local branch onto remote `main` (or `master`), then runs the CODE_RULES gate. An existing branch's gate base is the merge base with the remote default branch; the gate process still diffs that base against checkout HEAD, so the surface matches the pushed tip only when HEAD is that tip. |
11
- | `pre_push_base_reference.py` | — | Resolves a usable gate base for `pre_push.py`: reads the pushed remote name from git's arguments, then turns a symbolic default-branch head into a reference that git can resolve |
12
- | `post_commit.py` | `post-commit` | Runs bookkeeping, then best-effort reminds the agent about its PR |
13
- | `pull_request_handoff.py` | — | Prints the full PR title and description handoff prompt |
14
- | `gate_utils.py` | — | Shared helpers: resolves the gate script path, checks that the path is a safe regular file |
15
- | `test_config.py` | — | Test configuration helpers |
16
- | `test_gate_utils.py` | — | Tests for `gate_utils.py` |
17
- | `test_pre_commit.py` | — | Tests for `pre_commit.py` |
18
- | `test_pre_push.py` | — | Tests for `pre_push.py` |
19
- | `test_pre_push_base_reference.py` | — | Tests for the gate base resolution in `pre_push.py` |
20
- | `conftest.py` | — | Puts this directory on `sys.path` and clears cached `config` modules, so each test module imports the hooks at the top of the file |
21
-
22
- ## Subdirectory
23
-
24
- | Directory | Role |
25
- |---|---|
26
- | `git_hooks_constants/` | Shared constants imported by the git-hook scripts |
27
-
28
- ## Conventions
29
-
30
- - The installer strips the `_` and `.py` suffix when copying into the live git-hooks path (e.g. `pre_commit.py` becomes `pre-commit`).
31
- - Constants (exit codes, argument names, error messages) live in `git_hooks_constants/` and are imported at the top of each script.
32
- - Run tests with `python -m pytest git-hooks/test_<name>.py`.
@@ -1,21 +1 @@
1
- # hooks/git-hooks/git_hooks_constants
2
1
 
3
- Shared constants imported by the git-hook scripts in `git-hooks/`. Centralizes exit codes, argument names, and error messages so every tunable lives in one place.
4
-
5
- ## Files
6
-
7
- | File | Contents |
8
- |---|---|
9
- | `__init__.py` | Exports all constants; marks this as a package so `from git_hooks_constants import ...` resolves |
10
-
11
- ## Key constants (defined in `__init__.py`)
12
-
13
- - `GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE` — exit code when the gate script cannot be found or launched
14
- - `GATE_SCRIPT_NOT_FOUND_MESSAGE` — error message when the gate script path does not exist
15
- - `INVOKE_GATE_FAILURE_MESSAGE` — error message when the gate subprocess fails to start
16
- - `STAGED_SCOPE_ARGUMENT` — CLI argument passed to the gate script to scope it to staged changes
17
-
18
- ## Conventions
19
-
20
- - Import with `from git_hooks_constants import <CONSTANT>` from within the `git-hooks/` directory.
21
- - Add new constants here rather than inline in the hook scripts.
@@ -1,105 +1 @@
1
- # hooks/hooks_constants
2
1
 
3
- Shared constant modules imported by hooks throughout the `hooks/` tree. Each file holds the tunables for one hook or one cross-cutting concern, keeping magic values out of the hook scripts themselves.
4
-
5
- ## Files
6
-
7
- | File | What it holds |
8
- |---|---|
9
- | `__init__.py` | Package marker (`# pragma: no-tdd-gate`) |
10
- | `any_type_config.py` | Config for the `Any`-type escape-hatch check |
11
- | `ask_user_question_shape.py` | Pure AskUserQuestion lean-block shape analyzer: grades question and option-description prose against shared chat-detail markers and sentence/word caps with no hook I/O |
12
- | `banned_identifiers_constants.py` | The set of banned short identifiers and banned function-name prefixes |
13
- | `bash_pre_tool_use_dispatcher_constants.py` | Permission outcomes, tool-name sets, and the ordered hosted-hook roster for the Bash PreToolUse dispatcher (also covers PowerShell-shared gates) |
14
- | `pre_tool_use_dispatcher_constants.py` | Shared Write, Edit, and MultiEdit tool-name set and the ordered hosted-hook roster for the Write/Edit/MultiEdit PreToolUse dispatcher |
15
- | `blocking_check_limits.py` | Max issue counts and preview lengths for blocking hooks |
16
- | `bot_mention_comment_blocker_constants.py` | Patterns for detecting bot @-mentions in PR comments |
17
- | `claude_md_orphan_file_blocker_constants.py` | Table patterns, file extensions, scan budget, and block-message text for the CLAUDE.md orphan-file blocker |
18
- | `code_rules_enforcer_constants.py` | File-extension sets, test-path patterns, advisory line thresholds, boolean-name prefixes |
19
- | `enter_worktree_prefetch_constants.py` | Tool name, origin-remote ref names, and git-command timeouts for the EnterWorktree origin-prefetch hook |
20
- | `env_var_table_code_drift_constants.py` | Table patterns, env-var-name and code-file recognizers, scan budget, and block-message text for the env-var-table code-drift blocker |
21
- | `code_rules_path_utils_constants.py` | Path-matching helpers used by the code-rules check modules |
22
- | `command_dispatch_constants.py` | Command-word regex, command-key access pattern, tokenization pattern, and anchors for the unanchored command-dispatch meta-gate |
23
- | `conventional_pr_title_gate_constants.py` | Bash tool name, gh executable basenames and pr create/edit subcommand tokens, title/repo flag names, semantic-title-CI workflow markers, the Conventional Commits type list and title pattern, the semantic-pull-request action `types:` input pattern, and block-message text for the conventional-PR-title gate |
24
- | `cursor_cli_python_misfire_blocker_constants.py` | Detection patterns and deny message for Cursor launches that mistreat a Python code-rules-gate script |
25
- | `dead_argparse_argument_constants.py` | Patterns for detecting unused argparse arguments |
26
- | `dead_config_field_constants.py` | Patterns for detecting unused `*Config` / `*Selectors` dataclass fields |
27
- | `dead_dataclass_field_constants.py` | Patterns for detecting unused dataclass fields |
28
- | `dead_module_constant_constants.py` | Patterns for detecting unexported `UPPER_SNAKE` constants in `*_constants.py` modules |
29
- | `destructive_command_environment_constants.py` | Environment keys and shared truthy values used by destructive-command hooks |
30
- | `destructive_command_segment_constants.py` | The list of destructive shell command patterns the blocker matches |
31
- | `docstring_rule_gate_count_blocker_constants.py` | Target rule basename, spelled-out-number lookup, count-clause and `check_*` validator patterns, and block-message text for the docstring-rule gate-count staleness blocker |
32
- | `duplicate_function_body_constants.py` | Hashing and comparison config for the duplicate-body check |
33
- | `duplicate_rmtree_helper_blocker_constants.py` | Sanctioned Windows-safe rmtree helper names, the definition pattern, and the exempt-path set for the duplicate-rmtree-helper blocker |
34
- | `dynamic_stderr_handler.py` | `DynamicStderrHandler` — a logging handler that resolves `sys.stderr` at emit time (for testability) |
35
- | `fable_spawn_gate_constants.py` | The spawn tool-name set, the fable model alias and the model-id segment split pattern, the `FABLE-SPAWN-AUTHORIZED` authorization token, the advisor-protocol document path, payload field names, the deny message, and the deny `additionalContext` recovery text for the fable-tier spawn gate |
36
- | `gh_pr_author_swap_constants.py` | Constants for the PR-author swap enforcement hooks |
37
- | `hardcoded_user_path_constants.py` | Patterns for detecting hardcoded home-directory paths |
38
- | `harness_scratchpad_constants.py` | Fixed path components (`claude` / `claude-` user-directory name and prefix, `scratchpad` leaf name), the PreToolUse session-id payload key, and the `CLAUDE_CODE_SESSION_ID` environment variable name that the code-rules and TDD gates use to recognize an existing harness session scratchpad directory |
39
- | `hedging_uncertainty_constants.py` | Sentence-boundary pattern, explicit uncertainty label patterns, hedge-term list separator, and positive corrective block text for OP-07C sentence-scoped hedging |
40
- | `hook_block_logger.py` | `log_hook_block()` — shared fail-safe logger every blocking hook calls to append a JSON record of each block decision to `~/.claude/logs/hook-blocks.log` |
41
- | `hook_prose_detector_consistency_constants.py` | Trigger patterns and corrective messages for the hook-prose consistency checker |
42
- | `hosted_hook_runner.py` | `run_hook_capturing_output()` — shared runner that runs one dispatcher-hosted hook in-process via runpy and returns its captured stdout and crash flag |
43
- | `inline_tuple_string_magic_constants.py` | Patterns for detecting magic strings in inline tuple literals |
44
- | `js_conventions_constants.py` | Banned identifier set, boolean-prefix pattern, and declaration/JSDoc patterns for the JavaScript convention checks |
45
- | `local_identity.py` | Loader for local machine values: NAS host, ssh user, and ssh port the ssh enforcer guards (`CLAUDE_NAS_*` / `~/.claude/local-identity.json` with placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`, keyed by owner/repo slug) read from the git-ignored local file whose path `CLAUDE_LOCAL_IDENTITY_PATH` may point elsewhere; also composes the ssh enforcer's two deny messages that quote the NAS values |
46
- | `messages.py` | Short user-facing notice strings shown when a Stop hook redirects agent behavior |
47
- | `multi_edit_reconstruction.py` | `apply_edits()` / `edits_for_tool()` — shared helpers that reconstruct the post-edit content of an Edit or MultiEdit, imported by the blockers that judge post-edit content |
48
- | `mypy_integration_constants.py` | Path markers (``.git``, ``.py``, ``pyproject.toml``) for mypy project-root resolution, plus detached-file `--follow-imports=skip` flags, subprocess timeout, and timeout skip message |
49
- | `mypy_validator_cache_constants.py` | Cache paths and tunables for the mypy_validator per-session caches |
50
- | `nas_ssh_binary_enforcer_constants.py` | Bash tool name, ssh-family basenames, OpenSSH binary path suffixes, and the batch-mode pattern for the NAS ssh binary enforcer; segment helpers come from `shell_command_segments.py` |
51
- | `open_questions_in_plans_blocker_constants.py` | Patterns for detecting unresolved open questions in plan documents |
52
- | `orphan_css_class_constants.py` | Scan radius and selector patterns for the orphan-CSS-class check |
53
- | `package_inventory_stale_blocker_constants.py` | Inventory document names, production code extensions, backtick token pattern, smallest inventory size, exempt names, scan budget, and block-message text for the package-inventory stale-entry blocker |
54
- | `paired_test_coverage_constants.py` | Test-directory name, stem-test filename affixes, test-file globs, exempt public-function names, scan budget, coverage threshold, and guidance text for the public-function paired-test coverage check |
55
- | `path_rewriter_constants.py` | Path rewriting patterns for the Everything-search path rewriter |
56
- | `pii_prevention_constants.py` | Patterns, allowlists, path exemptions, and deny-message text for `pii_prevention_blocker` |
57
- | `piped_pytest_blocker_constants.py` | Bash tool name, pytest program basenames and the python-interpreter basename pattern, the pipe and segment-reset operator token sets, and the deny message for the piped-pytest blocker; classification that consumes those program and wrapper constants lives in `pytest_invocation.py` |
58
- | `pytest_invocation.py` | Pure parsed-segment classifier for pytest runs through interpreters, shims, wrappers, and shell string-exec forms; no pipeline deny decision |
59
- | `prose_matcher_precision_constants.py` | Sample floor, keep/narrow precision floors, matcher ids, label decisions, advisory log path, emit caps, and context fingerprint length for OP-07B prose-matcher advisory telemetry |
60
- | `pre_tool_use_stdin.py` | `read_hook_input_dictionary_from_stdin()` — shared stdin parser for PreToolUse hooks |
61
- | `precommit_code_rules_gate_constants.py` | Scope argument and exit-code constants for the precommit gate |
62
- | project_paths_reader.py | Loads ~/.claude/project-paths.json and finds a home-bounded git root for registry checks |
63
- | `pyproject_config_discovery_constants.py` | Table names (``tool`` key, ``mypy``, ``ruff``) for resolving a validator's config from a pyproject.toml `[tool.<name>]` table |
64
- | `pytest_testpaths_orphan_blocker_constants.py` | Marker filename, section and key names, test-file pattern, search budget, and block-message text for the pytest unregistered-test-directory blocker |
65
- | `python_style_checks_constants.py` | Command-line argument count and blank-line count between top-level functions for the style validator |
66
- | `ruff_integration_constants.py` | ``NO_COLOR`` / ``FORCE_COLOR`` environment variable names for plain ruff diagnostics |
67
- | `send_user_file_open_locally_blocker_constants.py` | Tool name, proactive status, and the `Invoke-Item` block message for the open-locally attach blocker |
68
- | `sensitive_file_protector_constants.py` | Sensitive filename patterns, committed-template suffixes that earn an exemption, and the deny decision and message template for `sensitive_file_protector` |
69
- | `session_edit_stage_gate_constants.py` | Tracker filename prefix/suffix, JSON payload key, edit tool name set, session-id sanitize pattern, lock filename suffix and lock-acquire timing, git diff command, commit flag escapes, and deny-message template shared by the session edit stage gate trio |
70
- | `session_env_cleanup_constants.py` | Stale-age threshold and directory names for the session-env cleanup hook |
71
- | `session_start_injector.py` | Pure SessionStart context injector: normalize `source` (`startup`/`resume`/`clear`/`compact`), honor enable/timeout, return structured injection results for starter hooks |
72
- | `session_start_injector_constants.py` | Known SessionStart source values, injection status codes, enable env var, default timeout for the shared injector |
73
- | `test_session_start_injector.py` | Behavioral tests for every known source, disabled, timeout, and unknown-source paths |
74
- | `orchestrator_auto_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the orchestrator auto-starter |
75
- | `issue_tracker_session_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the repository-gated issue-tracker starter |
76
- | `session_handoff_blocker_constants.py` | Trigger phrases for the session-handoff blocker |
77
- | `setup_project_paths_constants.py` | Encoding policy, BOM marker, and registry meta-key used across multiple hooks |
78
- | `shell_command_pipeline.py` | Quote-aware shell pipeline parsing: operator-paired segments after line-continuation join, comment strip, heredoc body drop, and parenthesis-group join |
79
- | `shell_command_segments.py` | Shell tokenization helpers shared by the segment-walking blockers: segment splitting on control operators, a segment's effective leading program, and a token's basename |
80
- | `shell_substitution_blocker_constants.py` | Tool name, payload keys, the four substitution-detection patterns, the deny decision shape, and the corrective message for the shell-substitution blocker |
81
- | `stale_comment_reference_blocker_constants.py` | Identifier pattern, comment stopwords, and denial text for the stale-comment-reference blocker |
82
- | `state_description_blocker_constants.py` | The set of historical/comparative phrases the state-description blocker rejects, plus the docstring-extraction and mention-span patterns for its Python docstring scan |
83
- | `stop_dispatcher_constants.py` | Ordered hosted-hook roster and Stop block payload field names for the Stop-chain dispatcher |
84
- | `style_reminder_prompt_constants.py` | The style reminder text ("small words. few words. always. forever.") for the style_reminder_prompt hook |
85
- | `stuttering_check_config.py` | Config for the stuttering (repeated-phrase) check |
86
- | `stuttering_import_binding_constants.py` | Import-binding patterns for the stuttering check |
87
- | `subprocess_budget_completeness_constants.py` | Required argument names for the subprocess-budget completeness check |
88
- | `sys_path_insert_constants.py` | Patterns for detecting unguarded `sys.path.insert` calls |
89
- | `task_list_loop_starter_constants.py` | The one-line task-list instruction and the full session-start directive text for the task-list loop starter hook |
90
- | `test_layout_constants.py` | The named constants for the test-layout write-time checks |
91
- | `text_stripping.py` | `strip_code_and_quotes()` — shared helper that removes fenced code blocks, inline code, and blockquotes from prose, imported by the Stop-hook prose blockers |
92
- | `unscoped_search_blocker_constants.py` | Tool names, `find` and listing program basenames, Get-ChildItem option sets, unscoped-root patterns, the flag/value token stride, and the deny message for the unscoped-search blocker |
93
- | `unused_module_import_constants.py` | Patterns for detecting unused module-level imports |
94
- | `volatile_path_in_post_blocker_constants.py` | Volatile path markers, affected `gh` post subcommands, MCP body param names, and the corrective message for the volatile-path post blocker |
95
- | `windows_rmtree_blocker_constants.py` | The unsafe `shutil.rmtree` pattern and the safe replacement pattern |
96
- | `workflow_substitution_slot_blocker_constants.py` | Per-iteration token patterns for the workflow-slot blocker |
97
- | `working_style_prompt_constants.py` | The fixed multi-paragraph working-style prompt text for the SessionStart working_style_prompt hook |
98
-
99
- ## Conventions
100
-
101
- - Most files in this package are pure constants modules — no side effects, no I/O.
102
- - Hooks import from this package with `from hooks_constants.<module> import <CONSTANT>`.
103
- - Tests for these modules live beside them as `test_<module>.py`. Run with `python -m pytest hooks_constants/test_<name>.py`.
104
- - `dynamic_stderr_handler.py`, `pre_tool_use_stdin.py`, `multi_edit_reconstruction.py`, `hosted_hook_runner.py`, and `text_stripping.py` are utility modules (not pure constants) but live here because they hold logic shared across hook surfaces.
105
- - `local_identity.py` is a loader: it reads the environment or `~/.claude/local-identity.json` (its path overridable via `CLAUDE_LOCAL_IDENTITY_PATH`) to resolve private NAS values (with committed placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`).
@@ -72,7 +72,6 @@ ALL_BASH_HOSTED_HOOK_ENTRIES: tuple[BashHostedHookEntry, ...] = (
72
72
  ),
73
73
  BashHostedHookEntry("blocking/conventional_pr_title_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
74
74
  BashHostedHookEntry("blocking/block_main_commit.py", ALL_BASH_ONLY_TOOL_NAMES),
75
- BashHostedHookEntry("blocking/precommit_code_rules_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
76
75
  BashHostedHookEntry("blocking/session_edit_stage_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
77
76
  BashHostedHookEntry("blocking/test_preflight_check.py", ALL_BASH_ONLY_TOOL_NAMES),
78
77
  BashHostedHookEntry("blocking/windows_rmtree_blocker.py", ALL_BASH_ONLY_TOOL_NAMES),
@@ -32,6 +32,9 @@ ALL_HOOK_INFRASTRUCTURE_PATTERNS = {"/.claude/hooks/", "\\.claude\\hooks\\", "\\
32
32
  ALL_WORKFLOW_REGISTRY_PATTERNS = {"/workflow/", "\\workflow\\", "_tab.py", "/states.py", "\\states.py", "/modules.py", "\\modules.py"}
33
33
  ALL_MIGRATION_PATH_PATTERNS = {"/migrations/", "\\migrations\\"}
34
34
 
35
+ CONSTANTS_MODULE_SUFFIX: str = "_constants.py"
36
+ CONFIG_DIRECTORY_SEGMENT: str = "config"
37
+
35
38
  ADVISORY_LINE_THRESHOLD_SOFT = 400
36
39
  ADVISORY_LINE_THRESHOLD_HARD = 1000
37
40
 
@@ -1,11 +1,9 @@
1
1
  """User-facing notice messages for blocking hooks."""
2
2
 
3
- USER_FACING_NOTICE = "Agent was found guessing - sourcing opinions..."
4
3
  USER_FACING_TDD_NOTICE = "TDD gate held - writing the failing test first..."
5
4
  USER_FACING_ASKUSERQUESTION_NOTICE = (
6
5
  "Agent asked the user in prose - rerouting through AskUserQuestion..."
7
6
  )
8
- USER_FACING_INTENT_ENDING_NOTICE = "Agent ended on a promise - doing the work now..."
9
7
  USER_FACING_CONTEXT_REASSURANCE_NOTICE = (
10
8
  "Agent moved to wrap up early - continuing the work..."
11
9
  )
@@ -1,24 +1,10 @@
1
- """Constants for the precommit_code_rules_gate PreToolUse hook.
1
+ """Constants for the precommit_code_rules_gate library module.
2
2
 
3
- Command parsing, git timeouts, and the staged-gate invocation surface used
4
- to run the shared code_rules_gate engine before a git commit.
3
+ The git-repository-root resolution command and its timeout, used by
4
+ ``resolve_repository_root`` to find the repository a directory belongs to.
5
5
  """
6
6
 
7
- from pathlib import Path
8
-
9
- GIT_DASH_C_COMMIT_PATTERN: str = r"git\s+-C\s+[\"']?[^\"';&|]+?[\"']?\s+commit\b"
10
7
  GIT_COMMAND_TIMEOUT_SECONDS: int = 5
11
- GATE_TIMEOUT_SECONDS: int = 240
12
- GATE_RELATIVE_PATH: Path = Path("_shared") / "pr-loop" / "scripts" / "code_rules_gate.py"
13
- ALL_STAGED_PYTHON_FILES_COMMAND: tuple[str, ...] = (
14
- "git",
15
- "diff",
16
- "--cached",
17
- "--name-only",
18
- "--diff-filter=ACMR",
19
- "--",
20
- "*.py",
21
- )
22
8
  ALL_GIT_REPOSITORY_ROOT_COMMAND: tuple[str, ...] = (
23
9
  "git",
24
10
  "rev-parse",
@@ -18,8 +18,6 @@ DECISION_KEY = "decision"
18
18
  REASON_KEY = "reason"
19
19
 
20
20
  ALL_STOP_HOSTED_HOOK_PATHS: tuple[str, ...] = (
21
- "blocking/hedging_language_blocker.py",
22
21
  "blocking/question_to_user_enforcer.py",
23
- "blocking/intent_only_ending_blocker.py",
24
22
  "blocking/session_handoff_blocker.py",
25
23
  )
@@ -34,7 +34,6 @@ _EXPECTED_BASH_ORDER = (
34
34
  "blocking/pii_prevention_blocker.py",
35
35
  "blocking/conventional_pr_title_gate.py",
36
36
  "blocking/block_main_commit.py",
37
- "blocking/precommit_code_rules_gate.py",
38
37
  "blocking/session_edit_stage_gate.py",
39
38
  "blocking/test_preflight_check.py",
40
39
  "blocking/windows_rmtree_blocker.py",
@@ -17,6 +17,8 @@ if str(_HOOKS_ROOT) not in sys.path:
17
17
  sys.path.insert(0, str(_HOOKS_ROOT))
18
18
 
19
19
  from hooks_constants.code_rules_enforcer_constants import (
20
+ CONFIG_DIRECTORY_SEGMENT,
21
+ CONSTANTS_MODULE_SUFFIX,
20
22
  FUNCTION_WITH_JSDOC_PATTERN,
21
23
  JSDOC_RETURNS_STRUCTURED_OBJECT_PROMISE_PATTERN,
22
24
  RETURN_CALL_OPENING_PARENTHESIS_PATTERN,
@@ -91,3 +93,8 @@ def test_schema_property_key_pattern_matches_only_the_options_key() -> None:
91
93
  assert SCHEMA_OPTIONS_PROPERTY_KEY_PATTERN.search("{ label: 'x', schema : X }") is not None
92
94
  assert SCHEMA_OPTIONS_PROPERTY_KEY_PATTERN.search("{ agentType, phase }, HEAD_SCHEMA") is None
93
95
  assert SCHEMA_OPTIONS_PROPERTY_KEY_PATTERN.search("{ myschema: X }") is None
96
+
97
+
98
+ def test_constants_module_suffix_and_config_directory_segment_are_defined() -> None:
99
+ assert CONSTANTS_MODULE_SUFFIX == "_constants.py"
100
+ assert CONFIG_DIRECTORY_SEGMENT == "config"
@@ -3,9 +3,11 @@
3
3
  from hooks_constants import messages
4
4
 
5
5
 
6
- def test_user_facing_notice_is_nonempty_string() -> None:
7
- assert isinstance(messages.USER_FACING_NOTICE, str)
8
- assert messages.USER_FACING_NOTICE
6
+ def test_module_carries_no_hedging_or_intent_ending_notices() -> None:
7
+ """The hedging and intent-only-ending Stop hooks are removed; their
8
+ dedicated notices no longer live here."""
9
+ assert not hasattr(messages, "USER_FACING_NOTICE")
10
+ assert not hasattr(messages, "USER_FACING_INTENT_ENDING_NOTICE")
9
11
 
10
12
 
11
13
  def test_user_facing_tdd_notice_is_nonempty_string() -> None:
@@ -12,9 +12,7 @@ if _HOOKS_DIR not in sys.path:
12
12
  from hooks_constants.stop_dispatcher_constants import ALL_STOP_HOSTED_HOOK_PATHS # noqa: E402
13
13
 
14
14
  _EXPECTED_STOP_ORDER = (
15
- "blocking/hedging_language_blocker.py",
16
15
  "blocking/question_to_user_enforcer.py",
17
- "blocking/intent_only_ending_blocker.py",
18
16
  "blocking/session_handoff_blocker.py",
19
17
  )
20
18
 
@@ -1,18 +1 @@
1
- # hooks/lifecycle
2
1
 
3
- Hooks that run at session or config-change boundaries rather than on individual tool calls.
4
-
5
- ## Key files
6
-
7
- | File | Event | What it does |
8
- |---|---|---|
9
- | `config_change_guard.py` | PostToolUse (Write/Edit on `settings.json`) | Counts hooks in the edited `settings.json` and logs any change to `~/.claude/cache/config-change-audit.log`; alerts when the hook count drops below the last known value |
10
- | `enter_worktree_origin_prefetch.py` | PreToolUse (EnterWorktree) | Fetches origin's default branch before a worktree creation call, keeping the `refs/remotes/origin/<default-branch>` ref that `fresh` mode reads current; never blocks on fetch failure |
11
- | `session_end_cleanup.py` | SessionEnd | Purges stale cache entries from `~/.claude/cache/` (entries older than the configured threshold) and old backup files |
12
- | `test_config_change_guard.py` | — | Tests for `config_change_guard.py` |
13
- | `test_enter_worktree_origin_prefetch.py` | — | Tests for `enter_worktree_origin_prefetch.py` |
14
-
15
- ## Conventions
16
-
17
- - Constants for these hooks (stale-age threshold, cache directory, known-hook-count file, EnterWorktree prefetch tuning) live in `hooks_constants/session_env_cleanup_constants.py` and `hooks_constants/enter_worktree_prefetch_constants.py`.
18
- - Tests run with `python -m pytest lifecycle/test_<name>.py`.
@@ -1,20 +1 @@
1
- # hooks/observability
2
1
 
3
- PostToolUse hooks that record agent behavior for later review. These hooks do not block tool calls; they log or annotate them.
4
-
5
- ## Key files
6
-
7
- | File | Event | What it does |
8
- |---|---|---|
9
- | `instructions_loaded_logger.py` | PostToolUse (file load events) | Appends a JSONL record to `~/.claude/logs/instructions_loaded.jsonl` each time Claude Code loads a context file (CLAUDE.md, rules, skills), capturing the file path, load reason, memory type, and session ID |
10
- | `session_file_edit_tracker.py` | PostToolUse (Write/Edit/MultiEdit) | Records the resolved absolute path of each file edited this session into a per-session JSON file under the system temp directory, for the session edit stage gate to read at commit time |
11
- | `prose_matcher_advisory.py` | Advisory emit from prose matchers | Privacy-safe JSONL candidates (`matcher_id`, surface, context fingerprint, label) plus keep/narrow/drop/advisory classification against the sample floor |
12
- | `test_instructions_loaded_logger.py` | — | Tests for `instructions_loaded_logger.py` |
13
- | `test_session_file_edit_tracker.py` | — | Tests for `session_file_edit_tracker.py` |
14
- | `test_prose_matcher_advisory.py` | — | Tests for advisory emit and precision classification |
15
-
16
- ## Conventions
17
-
18
- - The log file is append-only; the hook creates the parent directory if needed.
19
- - Errors during logging are caught and written as error records rather than propagated — the hook never blocks the tool call.
20
- - Tests run with `python -m pytest observability/test_instructions_loaded_logger.py`.
@@ -1,38 +1 @@
1
- # hooks/session
2
1
 
3
- SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown. Also holds the UserPromptSubmit hook. It adds a style reminder to each message.
4
-
5
- The working-style projection uses `~/.claude/rules/asd-ste100-language.md` for
6
- user-facing word choice, sentence style, tone, punctuation, and prose form.
7
-
8
- ## Key files
9
-
10
- | File | Event | What it does |
11
- |---|---|---|
12
- | `session_env_cleanup.py` | SessionStart | Removes the current session's pre-existing `~/.claude/session-env/<session_id>/` directory and prunes sibling entries older than the stale-age threshold. Prevents `EEXIST` errors from non-recursive `mkdir` calls in the Bash tool on Windows. |
13
- | `gh_pr_author_session_cleanup.py` | SessionEnd | Clears any PR-author swap state left over from the current session |
14
- | `session_edit_tracker_cleanup.py` | SessionStart, SessionEnd | Deletes the tracker file for the running Claude Code conversation from the system temp directory — at start for a clean slate and at end for a clean exit. A tracker is read only by the conversation that wrote it, so a live idle tracker is kept while a peer cleans up |
15
- | `plugin_data_dir_cleanup.py` | SessionStart | Removes empty plugin data directories at startup to prevent `EEXIST` when Claude Code recreates them |
16
- | `untracked_repo_detector.py` | — | Retired legacy script; no longer registered |
17
- | `task_list_loop_starter.py` | SessionStart | Emits an `additionalContext` directive telling Claude to keep the task list current on a 10-minute cadence, starting the `/loop` skill when one is not already running. Writes nothing and runs no tools itself. |
18
- | `orchestrator_auto_starter.py` | SessionStart | Opt-in (`CLAUDE_ORCHESTRATOR_AUTO_STARTER_ENABLED`) consumer of the shared SessionStart injector; emits orchestrator skill context when enabled. Manual `/orchestrator` unchanged. |
19
- | `issue_tracker_session_starter.py` | SessionStart | Opt-in (`CLAUDE_ISSUE_TRACKER_SESSION_STARTER_ENABLED`) and repository-gated (git root in `~/.claude/project-paths.json`) issue-tracker skill context. |
20
- | `_path_setup.py` | — | Inserts the hooks directory on `sys.path` so SessionStart scripts import `hooks_constants` with top-level imports. |
21
- | `test_orchestrator_auto_starter.py` | — | Tests for `orchestrator_auto_starter.py` |
22
- | `test_issue_tracker_session_starter.py` | — | Tests for `issue_tracker_session_starter.py` |
23
- | `working_style_prompt.py` | SessionStart | Emits an `additionalContext` block with the fixed working-style prompt (running ledger, canonical language policy, outcome-first finish, scope discipline). Writes nothing and runs no tools itself. |
24
- | `style_reminder_prompt.py` | UserPromptSubmit | Adds the style reminder ("small words. few words. always. forever.") to every message, as `hookSpecificOutput.additionalContext`. Codex reads the same shape, so a manually wired Codex `hooks.json` can reuse this script too (see `docs/codex-compatibility.md`). Prints text and stops. |
25
- | `test_style_reminder_prompt.py` | — | Tests for `style_reminder_prompt.py` |
26
- | `test_gh_pr_author_session_cleanup.py` | — | Tests for `gh_pr_author_session_cleanup.py` |
27
- | `test_session_edit_tracker_cleanup.py` | — | Tests for `session_edit_tracker_cleanup.py` |
28
- | `test_session_env_cleanup.py` | — | Tests for `session_env_cleanup.py` |
29
- | `test_untracked_repo_detector.py` | — | Tests for `untracked_repo_detector.py` |
30
- | `test_task_list_loop_starter.py` | — | Tests for `task_list_loop_starter.py` |
31
- | `test__path_setup.py` | — | Tests for `_path_setup.py` |
32
- | `test_working_style_prompt.py` | — | Tests for `working_style_prompt.py` |
33
-
34
- ## Conventions
35
-
36
- - `session_env_cleanup.py` is Windows-specific in effect but safe to run on all platforms; it exits 0 when the target directory does not exist.
37
- - Constants (stale-age threshold, directory names) live in `hooks_constants/session_env_cleanup_constants.py`.
38
- - Tests run with `python -m pytest session/test_<name>.py`.
@@ -1,20 +1 @@
1
- # hooks/validation
2
1
 
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,52 +1 @@
1
- # hooks/validators
2
1
 
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
- | `system_temporary_roots.py` | Shared membership for OS temp roots (`gettempdir` plus `TEMP` / `TMP` / `TMPDIR` / `RUNNER_TEMP`); mypy walk stop and PreToolUse staging both call it |
17
- | `python_style_helpers.py` | Shared source-line splitting and function-discovery helpers imported by `python_style_checks.py` |
18
-
19
- ## Check modules
20
-
21
- | Module | What it checks |
22
- |---|---|
23
- | `abbreviation_checks.py` | Abbreviated names in Python code |
24
- | `code_quality_checks.py` | General code quality concerns (dead code, stub bodies, etc.) |
25
- | `comment_checks.py` | Inline comment presence and content |
26
- | `file_structure_checks.py` | File-level structural rules (line count, module layout) |
27
- | `git_checks.py` | Git-state checks (untracked files, merge conflicts) |
28
- | `magic_value_checks.py` | Magic numbers and strings |
29
- | `mypy_integration.py` | Runs mypy and converts its output to `Violation` objects; stops project-root walks at the system temp directory; detached gate files skip followed imports and time out as a skip (passed) |
30
- | `pr_reference_checks.py` | PR references in commit messages and changelogs |
31
- | `python_antipattern_checks.py` | Python-specific anti-patterns (bare `except`, `Any`, etc.) |
32
- | `python_style_checks.py` | Python style rules (naming, imports, type hints) |
33
- | `react_checks.py` | React/TSX-specific checks (class component patterns, PureComponent usage) |
34
- | `ruff_integration.py` | Runs ruff and converts its output to `Violation` objects |
35
- | `security_checks.py` | Security anti-patterns (hardcoded secrets, unsafe calls) |
36
- | `todo_checks.py` | TODO/FIXME markers without an associated issue reference |
37
- | `type_safety_checks.py` | Type-safety rules (no `Any`, no `cast`, no `# type: ignore`) |
38
- | `useless_test_checks.py` | Tests that check only existence or constant values |
39
-
40
- ## Subdirectory
41
-
42
- | Directory | Role |
43
- |---|---|
44
- | `config/` | Constants module (`directory_exemption_constants.py`) holding the exemption directory-segment names that `validate_proposed_file` staging keeps |
45
- | `test_files/` | Fixture files used by the validator tests — not checked-in test code |
46
-
47
- ## Conventions
48
-
49
- - Every check module exposes one or more functions that take file content or an AST and return a list of `Violation` objects.
50
- - Test files live beside the modules they test: `test_<module>.py`. Run with `python -m pytest validators/test_<name>.py`.
51
- - `conftest.py` provides shared test fixtures (sample files, fixture paths).
52
- - `README.md` in this directory documents the validator design and how to add a new check.
@@ -1,16 +1 @@
1
- # hooks/workflow
2
1
 
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,15 +1 @@
1
- # output-styles
2
1
 
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.
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "2.28.0",
3
+ "version": "2.29.0",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {