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
@@ -63,45 +63,14 @@ from code_rules_constants_config import ( # noqa: E402
63
63
  check_constants_outside_config_advisory,
64
64
  check_file_global_constants_use_count,
65
65
  )
66
- from code_rules_dead_argparse_argument import ( # noqa: E402
67
- check_dead_argparse_arguments,
68
- )
69
- from code_rules_dead_config_field import ( # noqa: E402
70
- check_dead_config_dataclass_fields,
71
- )
72
- from code_rules_dead_dataclass_field import ( # noqa: E402
73
- check_dead_dataclass_fields,
74
- )
75
- from code_rules_dead_module_constant import ( # noqa: E402
76
- check_dead_module_constants,
77
- )
78
- from code_rules_dead_split_branch import ( # noqa: E402
79
- check_dead_split_truthiness_branch,
80
- )
81
66
  from code_rules_docstrings import ( # noqa: E402
82
67
  check_class_docstring_names_public_methods,
83
68
  check_docstring_args_match_signature,
84
- check_docstring_args_single_line_scope_vs_span,
85
- check_docstring_cardinal_count_matches_constant_family,
86
- check_docstring_delegation_summary_enumeration_drift,
87
69
  check_docstring_documents_unreferenced_parameter,
88
- check_docstring_fallback_branch_coverage,
89
- check_docstring_field_runmode_outcome,
90
70
  check_docstring_format,
91
- check_docstring_length_constant_superlative_vs_exact_gate,
92
- check_docstring_names_absent_type_checking_gate,
93
71
  check_docstring_names_undefined_constant,
94
- check_docstring_no_consumer_claim,
95
- check_docstring_no_inline_literal_claim,
96
- check_docstring_no_network_claim_with_metadata_access,
97
72
  check_docstring_prose_wall_without_illustration,
98
- check_docstring_punctuation_mark_enumeration_coverage,
99
- check_docstring_raises_unraisable_largezipfile,
100
- check_docstring_returns_plural_cardinality,
101
73
  check_docstring_runon_sentence,
102
- check_docstring_step_enumeration_dispatch_coverage,
103
- check_docstring_tuple_enumeration_match,
104
- check_docstring_unguarded_malformed_payload_claim,
105
74
  check_module_docstring_names_public_checks,
106
75
  check_module_docstring_scope_omits_data_schema_constants,
107
76
  )
@@ -113,7 +82,6 @@ from code_rules_duplicate_body import ( # noqa: E402
113
82
  from code_rules_imports_logging import ( # noqa: E402
114
83
  advise_file_line_count,
115
84
  check_e2e_test_naming,
116
- check_import_block_sorted,
117
85
  check_imports_at_top,
118
86
  check_js_bare_flag_return_directive,
119
87
  check_js_resume_task_enumeration_coverage,
@@ -134,9 +102,6 @@ from code_rules_magic_values import ( # noqa: E402
134
102
  check_fstring_structural_literals,
135
103
  check_magic_values,
136
104
  )
137
- from code_rules_mock_completeness import ( # noqa: E402
138
- check_incomplete_mocks,
139
- )
140
105
  from code_rules_naming_collection import ( # noqa: E402
141
106
  check_collection_prefix,
142
107
  check_loop_variable_naming,
@@ -203,9 +168,6 @@ from code_rules_typeddict_stub import ( # noqa: E402
203
168
  check_typed_dict_encode_decode,
204
169
  check_zero_payload_function_alias,
205
170
  )
206
- from code_rules_unused_imports import ( # noqa: E402
207
- check_unused_module_level_imports,
208
- )
209
171
  from codex_apply_patch import ( # noqa: E402
210
172
  CodexPatchError,
211
173
  CodexPatchFile,
@@ -355,14 +317,6 @@ def validate_content(
355
317
  if not is_test_file(file_path):
356
318
  all_issues.extend(check_comment_changes(old_content, content, file_path))
357
319
  all_issues.extend(check_imports_at_top(content))
358
- all_issues.extend(
359
- check_import_block_sorted(
360
- effective_content,
361
- file_path,
362
- all_changed_lines,
363
- defer_scope_to_caller,
364
- )
365
- )
366
320
  all_issues.extend(check_logging_fstrings(content))
367
321
  all_issues.extend(check_logging_printf_tokens(content, file_path))
368
322
  all_issues.extend(check_logging_adjacent_string_literals(content, file_path))
@@ -440,21 +394,6 @@ def validate_content(
440
394
  all_issues.extend(
441
395
  check_docstring_documents_unreferenced_parameter(effective_content, file_path)
442
396
  )
443
- all_issues.extend(check_docstring_fallback_branch_coverage(effective_content, file_path))
444
- all_issues.extend(check_docstring_no_consumer_claim(effective_content, file_path))
445
- all_issues.extend(
446
- check_docstring_no_network_claim_with_metadata_access(
447
- effective_content, file_path
448
- )
449
- )
450
- all_issues.extend(
451
- check_docstring_unguarded_malformed_payload_claim(
452
- effective_content, file_path
453
- )
454
- )
455
- all_issues.extend(
456
- check_docstring_no_inline_literal_claim(effective_content, file_path)
457
- )
458
397
  all_issues.extend(
459
398
  check_class_docstring_names_public_methods(effective_content, file_path)
460
399
  )
@@ -482,52 +421,9 @@ def validate_content(
482
421
  effective_content, file_path
483
422
  )
484
423
  )
485
- all_issues.extend(
486
- check_docstring_tuple_enumeration_match(effective_content, file_path)
487
- )
488
- all_issues.extend(
489
- check_docstring_punctuation_mark_enumeration_coverage(
490
- effective_content, file_path
491
- )
492
- )
493
- all_issues.extend(
494
- check_docstring_step_enumeration_dispatch_coverage(
495
- effective_content, file_path
496
- )
497
- )
498
- all_issues.extend(
499
- check_docstring_returns_plural_cardinality(effective_content, file_path)
500
- )
501
- all_issues.extend(
502
- check_docstring_length_constant_superlative_vs_exact_gate(
503
- effective_content, file_path
504
- )
505
- )
506
- all_issues.extend(
507
- check_docstring_field_runmode_outcome(effective_content, file_path)
508
- )
509
- all_issues.extend(
510
- check_docstring_raises_unraisable_largezipfile(effective_content, file_path)
511
- )
512
- all_issues.extend(
513
- check_docstring_cardinal_count_matches_constant_family(
514
- effective_content, file_path
515
- )
516
- )
517
424
  all_issues.extend(
518
425
  check_docstring_names_undefined_constant(effective_content, file_path)
519
426
  )
520
- all_issues.extend(
521
- check_docstring_names_absent_type_checking_gate(effective_content, file_path)
522
- )
523
- all_issues.extend(
524
- check_docstring_args_single_line_scope_vs_span(effective_content, file_path)
525
- )
526
- all_issues.extend(
527
- check_docstring_delegation_summary_enumeration_drift(
528
- effective_content, file_path
529
- )
530
- )
531
427
  all_issues.extend(
532
428
  check_boolean_naming(
533
429
  effective_content,
@@ -563,22 +459,6 @@ def validate_content(
563
459
  all_issues.extend(check_stuttering_collection_prefix(content, file_path))
564
460
  all_issues.extend(check_hardcoded_user_paths(content, file_path))
565
461
  all_issues.extend(check_sys_path_insert_deduplication_guard(content, file_path))
566
- all_issues.extend(
567
- check_unused_module_level_imports(content, file_path, full_file_content)
568
- )
569
- all_issues.extend(
570
- check_dead_dataclass_fields(content, file_path, full_file_content)
571
- )
572
- all_issues.extend(
573
- check_dead_argparse_arguments(content, file_path, full_file_content)
574
- )
575
- all_issues.extend(
576
- check_dead_config_dataclass_fields(content, file_path, full_file_content)
577
- )
578
- all_issues.extend(
579
- check_dead_module_constants(content, file_path, full_file_content)
580
- )
581
- all_issues.extend(check_dead_split_truthiness_branch(content, file_path))
582
462
  all_issues.extend(check_library_print(content, file_path))
583
463
  all_issues.extend(check_parameter_annotations(content, file_path))
584
464
  all_issues.extend(check_known_pytest_fixture_annotations(content, file_path))
@@ -640,7 +520,6 @@ def validate_content(
640
520
  )
641
521
  all_issues.extend(check_whitespace_indentation_magic(content, file_path))
642
522
  all_issues.extend(check_orphan_css_classes(effective_content, file_path))
643
- check_incomplete_mocks(content, file_path)
644
523
  check_duplicated_format_patterns(content, file_path)
645
524
  advise_cross_skill_duplicate_helper(effective_content, file_path)
646
525
 
@@ -1,9 +1,7 @@
1
- """Imports-at-top, import-block-sorted, logging f-string, logging printf-token, win32gui None, naive datetime construction, E2E spec naming, JS resume-task enumeration coverage, JS returns-object schema-less branch, JS sibling return-object key drift, JS bare-flag return-directive, file-length advisory, and library-print checks."""
1
+ """Import and logging convention checks: check_imports_at_top, check_logging_fstrings, check_logging_printf_tokens, check_logging_adjacent_string_literals, check_windows_api_none, check_naive_datetime_construction, check_e2e_test_naming, check_js_resume_task_enumeration_coverage, check_js_returns_object_schemaless_branch, check_js_sibling_return_object_key_drift, check_js_bare_flag_return_directive, and check_library_print."""
2
2
 
3
3
  import ast
4
- import json
5
4
  import re
6
- import subprocess
7
5
  import sys
8
6
  from pathlib import Path
9
7
 
@@ -28,14 +26,9 @@ from code_rules_shared import ( # noqa: E402
28
26
  from hooks_constants.blocking_check_limits import ( # noqa: E402
29
27
  ALL_ALWAYS_NAIVE_DATETIME_CONSTRUCTORS,
30
28
  ALL_FORMAT_LOGGER_FUNCTION_NAMES,
31
- ALL_IMPORT_BLOCK_SORT_RUFF_COMMAND_PREFIX,
32
- ALL_RUFF_STANDALONE_CONFIG_FILENAMES,
33
29
  DATETIME_CLASS_ATTRIBUTE_NAME,
34
30
  FROMTIMESTAMP_POSITIONAL_TIMEZONE_ARGUMENT_COUNT,
35
- IMPORT_BLOCK_SORT_RUFF_TIMEOUT_SECONDS,
36
- IMPORT_BLOCK_SORT_RULE_CODE,
37
31
  MAX_E2E_TEST_NAMING_ISSUES,
38
- MAX_IMPORT_BLOCK_SORT_ISSUES,
39
32
  MAX_JS_BARE_FLAG_RETURN_DIRECTIVE_ISSUES,
40
33
  MAX_JS_RESUME_TASK_ENUMERATION_ISSUES,
41
34
  MAX_JS_RETURNS_OBJECT_SCHEMALESS_ISSUES,
@@ -51,9 +44,6 @@ from hooks_constants.blocking_check_limits import ( # noqa: E402
51
44
  NAIVE_DATETIME_TIMEZONE_KEYWORD,
52
45
  NAIVE_DATETIME_UTCFROMTIMESTAMP_CONSTRUCTOR,
53
46
  NAIVE_DATETIME_UTCNOW_CONSTRUCTOR,
54
- RUFF_PYPROJECT_CONFIG_FILENAME,
55
- RUFF_PYPROJECT_TOOL_TABLE_MARKER,
56
- RUFF_STDIN_ENCODING,
57
47
  SIBLING_RETURN_OBJECT_EXACT_MISSING_KEY_COUNT,
58
48
  SIBLING_RETURN_OBJECT_SINGLE_AGREED_MISSING_KEY_COUNT,
59
49
  )
@@ -234,231 +224,6 @@ def check_imports_at_top(content: str) -> list[str]:
234
224
  return issues
235
225
 
236
226
 
237
- def check_import_block_sorted(
238
- content: str,
239
- file_path: str,
240
- all_changed_lines: set[int] | None = None,
241
- defer_scope_to_caller: bool = False,
242
- ) -> list[str]:
243
- """Flag a Python import block left un-sorted per isort rules (ruff I001).
244
-
245
- ruff/isort treats a contiguous run of ``import`` and ``from`` statements as
246
- one sortable unit. An edit that re-touches such a block pulls the whole block
247
- into the gate's scope, so a pre-existing mis-ordering in an untouched line of
248
- that block becomes a quality-gate failure (``check.ps1`` runs ruff over
249
- ``hooks/blocking``). This catches that drift at Write/Edit time by delegating
250
- to ruff itself, the same sorter the quality gate uses, so the two surfaces
251
- never disagree.
252
-
253
- The check resolves *file_path* to an absolute path and runs ruff against
254
- *content* on stdin under that path, so ruff walks parents to find the repo's
255
- ``[tool.ruff]`` config. Without a discoverable config ruff falls back to
256
- default isort first-party grouping, which orders sibling imports differently
257
- and produces false positives, so the check fails open when no ruff config is
258
- found above the file. Non-Python files and test files are exempt. When ruff
259
- is not installed, times out, or returns output the parser cannot read, the
260
- check also fails open and reports nothing — a missing or slow tool never
261
- blocks a write.
262
-
263
- An I001 finding covers the whole sortable block, so each finding carries a
264
- span from the block's anchor line (``location.row``) through its last line
265
- (``end_location.row``) scoped through the shared
266
- ``_scope_violations_to_changed_lines`` helper. On a terminal diff-scoped Edit
267
- a finding is returned when any line in that block span is among
268
- ``all_changed_lines``, so an edit touching any line of an unsorted block
269
- blocks while an edit far from the block does not. On a new-file or full-file
270
- write (``all_changed_lines`` None) every finding is in scope;
271
- ``defer_scope_to_caller`` returns every finding so the commit/push gate
272
- scopes by added line through its own ``Line N:`` partitioning.
273
-
274
- Args:
275
- content: The full file content the Write or Edit would leave on disk.
276
- file_path: The destination path, used both to gate by extension and to
277
- give ruff the filename it needs for config discovery.
278
- all_changed_lines: Post-edit line numbers the current edit touched, or
279
- None to treat the whole file as in scope. When provided, a finding
280
- blocks only when any line of its block span is among the changed
281
- lines.
282
- defer_scope_to_caller: When True, return every finding so the commit/push
283
- gate's ``Line N:`` partitioning scopes by added line.
284
-
285
- Returns:
286
- One issue string per detected I001 finding, capped at
287
- ``MAX_IMPORT_BLOCK_SORT_ISSUES``; an empty list when the block sorts
288
- cleanly, every finding falls outside the changed lines, or the check
289
- fails open.
290
- """
291
- if get_file_extension(file_path) not in ALL_PYTHON_EXTENSIONS:
292
- return []
293
- if is_test_file(file_path):
294
- return []
295
-
296
- absolute_file_path = Path(file_path).resolve()
297
- if not _ruff_config_discoverable(absolute_file_path):
298
- return []
299
-
300
- ruff_findings = _run_ruff_import_sort_check(content, str(absolute_file_path))
301
- if ruff_findings is None:
302
- return []
303
-
304
- span_end_line_offset = 1
305
- all_violations_in_finding_order: list[tuple[range, str]] = []
306
- for each_finding in ruff_findings:
307
- if each_finding.get("code") != IMPORT_BLOCK_SORT_RULE_CODE:
308
- continue
309
- line_number = _finding_line_number(each_finding.get("location"))
310
- block_end_line_number = _finding_block_end_line_number(
311
- each_finding.get("end_location"), line_number
312
- )
313
- span_range = range(line_number, block_end_line_number + span_end_line_offset)
314
- message = (
315
- f"Line {line_number}: Import block is un-sorted (ruff I001) - "
316
- f"run 'ruff check --fix' to sort the block before writing"
317
- )
318
- all_violations_in_finding_order.append((span_range, message))
319
- if len(all_violations_in_finding_order) >= MAX_IMPORT_BLOCK_SORT_ISSUES:
320
- break
321
-
322
- return _scope_violations_to_changed_lines(
323
- all_violations_in_finding_order,
324
- all_changed_lines,
325
- defer_scope_to_caller,
326
- )
327
-
328
-
329
- def _run_ruff_import_sort_check(content: str, file_path: str) -> list[dict[str, object]] | None:
330
- """Run ruff's I001 check over *content* and return its parsed JSON findings.
331
-
332
- Args:
333
- content: The file content fed to ruff on stdin.
334
- file_path: The filename ruff is told the stdin content belongs to, so it
335
- discovers the surrounding ``[tool.ruff]`` config.
336
-
337
- Returns:
338
- The list of ruff finding dictionaries, or ``None`` when ruff is absent,
339
- times out, or emits output that is not the expected JSON list.
340
- """
341
- ruff_command = [
342
- *ALL_IMPORT_BLOCK_SORT_RUFF_COMMAND_PREFIX,
343
- "--stdin-filename",
344
- file_path,
345
- "-",
346
- ]
347
- try:
348
- completed_process = subprocess.run(
349
- ruff_command,
350
- input=content.encode(RUFF_STDIN_ENCODING),
351
- capture_output=True,
352
- timeout=IMPORT_BLOCK_SORT_RUFF_TIMEOUT_SECONDS,
353
- check=False,
354
- )
355
- except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
356
- return None
357
-
358
- try:
359
- ruff_stdout = completed_process.stdout.decode(RUFF_STDIN_ENCODING)
360
- except UnicodeDecodeError:
361
- return None
362
-
363
- try:
364
- parsed_findings = json.loads(ruff_stdout)
365
- except json.JSONDecodeError:
366
- return None
367
-
368
- if not isinstance(parsed_findings, list):
369
- return None
370
- return [each_finding for each_finding in parsed_findings if isinstance(each_finding, dict)]
371
-
372
-
373
- def _ruff_config_discoverable(absolute_file_path: Path) -> bool:
374
- """Return whether a ruff config sits above *absolute_file_path*.
375
-
376
- Walks the file's parent directories looking for a standalone ``ruff.toml`` /
377
- ``.ruff.toml`` or a ``pyproject.toml`` that declares a ``[tool.ruff`` table.
378
- ruff uses this same nearest-ancestor walk to resolve its settings; mirroring
379
- it lets the check confirm ruff will see the project's isort configuration
380
- rather than its built-in defaults before trusting an I001 finding.
381
-
382
- Args:
383
- absolute_file_path: The resolved path of the file under validation.
384
-
385
- Returns:
386
- True when a ruff config is found in the file's directory or any ancestor;
387
- False when the walk reaches the filesystem root without one.
388
- """
389
- for each_directory in absolute_file_path.parents:
390
- for each_standalone_name in ALL_RUFF_STANDALONE_CONFIG_FILENAMES:
391
- if (each_directory / each_standalone_name).is_file():
392
- return True
393
- pyproject_path = each_directory / RUFF_PYPROJECT_CONFIG_FILENAME
394
- if _pyproject_declares_ruff_table(pyproject_path):
395
- return True
396
- return False
397
-
398
-
399
- def _pyproject_declares_ruff_table(pyproject_path: Path) -> bool:
400
- """Return whether *pyproject_path* exists and declares a ``[tool.ruff`` table.
401
-
402
- Args:
403
- pyproject_path: The candidate ``pyproject.toml`` path to inspect.
404
-
405
- Returns:
406
- True when the file exists and its text contains the ``[tool.ruff`` table
407
- marker; False when the file is absent or unreadable.
408
- """
409
- if not pyproject_path.is_file():
410
- return False
411
- try:
412
- pyproject_text = pyproject_path.read_text(encoding=RUFF_STDIN_ENCODING)
413
- except OSError:
414
- return False
415
- return RUFF_PYPROJECT_TOOL_TABLE_MARKER in pyproject_text
416
-
417
-
418
- def _finding_line_number(location: object) -> int:
419
- """Return the source line a ruff finding's location anchors to.
420
-
421
- Args:
422
- location: The ``location`` value from one ruff JSON finding, expected to
423
- be a mapping carrying an integer ``row``; any other shape yields a
424
- zero line number.
425
-
426
- Returns:
427
- The ``row`` value as an integer, or a zero line number when the location
428
- is absent or carries no readable row.
429
- """
430
- if not isinstance(location, dict):
431
- return 0
432
- row = location.get("row")
433
- if not isinstance(row, int):
434
- return 0
435
- return row
436
-
437
-
438
- def _finding_block_end_line_number(end_location: object, anchor_line_number: int) -> int:
439
- """Return the last source line a ruff finding's block spans.
440
-
441
- ruff anchors an I001 finding at its block's first line and records the
442
- block's last line in ``end_location.row``, so the two together bound the
443
- whole sortable run. The end row falls back to the anchor line when the
444
- ``end_location`` is absent or carries no readable row, or when it would land
445
- above the anchor — keeping the span to at least the anchor line itself.
446
-
447
- Args:
448
- end_location: The ``end_location`` value from one ruff JSON finding,
449
- expected to be a mapping carrying an integer ``row``.
450
- anchor_line_number: The finding's block-anchor line, used as the floor
451
- for the returned end line.
452
-
453
- Returns:
454
- The block's last line as an integer, never below *anchor_line_number*.
455
- """
456
- if not isinstance(end_location, dict):
457
- return anchor_line_number
458
- row = end_location.get("row")
459
- if not isinstance(row, int) or row < anchor_line_number:
460
- return anchor_line_number
461
- return row
462
227
 
463
228
 
464
229
  def _update_triple_quote_state_for_line(
@@ -19,6 +19,8 @@ from hooks_constants.code_rules_enforcer_constants import (
19
19
  ALL_WORKFLOW_REGISTRY_PATTERNS,
20
20
  CLAUDE_JOB_DIR_ENVIRONMENT_VARIABLE_NAME,
21
21
  CLAUDE_JOB_DIR_SCRATCH_SUBDIRECTORY,
22
+ CONFIG_DIRECTORY_SEGMENT,
23
+ CONSTANTS_MODULE_SUFFIX,
22
24
  EPHEMERAL_EXEMPT_DISABLE_ENVIRONMENT_VARIABLE_NAME,
23
25
  LEADING_DRIVE_LETTER_PATTERN,
24
26
  STRICT_TEST_FILE_BASENAME_PATTERN,
@@ -447,6 +449,27 @@ def is_ephemeral_path(file_path: str, hook_payload: dict | None = None) -> bool:
447
449
  return is_under_session_scratchpad(file_path, hook_payload or {})
448
450
 
449
451
 
452
+ def _is_dedicated_constants_module(file_path: str) -> bool:
453
+ """Return whether a path is a dedicated constants module.
454
+
455
+ A dedicated constants module is one whose filename ends in
456
+ ``_constants.py`` or whose path includes a ``config`` directory segment.
457
+ These modules export named values to importers, so a same-file reference
458
+ count cannot prove one of their constants dead.
459
+
460
+ Args:
461
+ file_path: The destination path of the write.
462
+
463
+ Returns:
464
+ True for a constants-suffixed module or a module under ``config/``.
465
+ """
466
+ normalized_path = file_path.replace("\\", "/").lower()
467
+ if normalized_path.endswith(CONSTANTS_MODULE_SUFFIX):
468
+ return True
469
+ path_segments = normalized_path.split("/")
470
+ return CONFIG_DIRECTORY_SEGMENT in path_segments[:-1]
471
+
472
+
450
473
  def is_migration_file(file_path: str) -> bool:
451
474
  """Check if file is a Django migration (must be self-contained)."""
452
475
  path_lower = file_path.lower().replace("\\", "/")
@@ -10,15 +10,14 @@ test functions, which exports nothing, so a single-file scan proves a constant
10
10
  no other line reads is dead. A ``conftest.py``, a shared helper module reached
11
11
  only through the ``tests/`` directory gate, and a dedicated constants or
12
12
  ``config/`` module all export their constants to importer modules, so the
13
- cross-module ``check_dead_module_constants`` governs their constants and the
14
- dead-constant check leaves them alone.
13
+ audit lane governs their constants cross-module (see
14
+ rules/file-global-constants.md) and this write-time check leaves them alone.
15
15
  """
16
16
 
17
17
  import ast
18
18
  from typing import TypeGuard
19
19
 
20
- from code_rules_dead_module_constant import _is_dedicated_constants_module
21
- from code_rules_shared import is_strict_test_file
20
+ from code_rules_shared import _is_dedicated_constants_module, is_strict_test_file
22
21
  from hooks_constants.test_layout_constants import (
23
22
  CLASS_METHOD_FIRST_PARAMETER_NAME,
24
23
  DEAD_TEST_CONSTANT_GUIDANCE,
@@ -55,7 +54,7 @@ def _is_dead_constant_scan_target(file_path: str) -> bool:
55
54
  constant no other line reads is dead. A ``conftest.py``, a shared helper
56
55
  module reached only through the ``tests/`` directory gate, and a dedicated
57
56
  constants or ``config/`` module all export to importer modules, where the
58
- cross-module ``check_dead_module_constants`` governs their constants.
57
+ cross-module audit lane governs their constants (see rules/file-global-constants.md).
59
58
 
60
59
  Args:
61
60
  file_path: The destination path of the write.
@@ -78,8 +77,8 @@ def _is_private_constant_name(name: str) -> bool:
78
77
  EXPECTED_TOTAL -> public constant, left alone
79
78
 
80
79
  Only a leading-underscore name qualifies. A public module constant exports
81
- to importer modules, so the cross-module ``check_dead_module_constants``
82
- governs it and this single-file scan leaves it alone.
80
+ to importer modules, so the cross-module audit lane governs it (see
81
+ rules/file-global-constants.md) and this single-file scan leaves it alone.
83
82
  """
84
83
  if not name.startswith(PRIVATE_NAME_PREFIX):
85
84
  return False
@@ -164,7 +163,8 @@ def check_dead_test_module_constant(content: str, file_path: str) -> list[str]:
164
163
  dead scaffolding an edit stranded. A public constant, a ``conftest.py``, a
165
164
  shared helper module under ``tests/``, and a dedicated constants or
166
165
  ``config/`` module all export to importer modules, so the cross-module
167
- ``check_dead_module_constants`` judges those and this check skips them.
166
+ audit lane judges those (see rules/file-global-constants.md) and this
167
+ check skips them.
168
168
 
169
169
  Args:
170
170
  content: The post-edit file content under validation.
@@ -1,10 +1 @@
1
- # hooks/blocking/config
2
1
 
3
- A Python package that holds shared constants for blocking hooks. Opinionated prose-style gates import from here.
4
-
5
- ## Key files
6
-
7
- | File | Contents |
8
- |---|---|
9
- | `__init__.py` | Declares this as a regular package (not a namespace package) so it resolves first on `sys.path` |
10
- | `prose_style_enforcement_constants.py` | `CLAUDE_PROSE_STYLE_ENFORCEMENT` opt-in (default off) for opinionated prose gates |
@@ -6,8 +6,10 @@
6
6
  (unset) -> PROSE_STYLE_ENFORCEMENT_ENABLED False
7
7
 
8
8
  Structural AskUserQuestion lean-block validation stays always on. The flag
9
- arms only opinionated prose gates (heavy-word swaps, hedging, historical
10
- state phrasing, intent-only endings, hook prose-detector consistency).
9
+ arms only two opinionated prose gates: `plain_language_blocker.py` (heavy-word
10
+ swaps) and `hook_prose_detector_consistency.py`. Historical-state phrasing
11
+ (`state_description_blocker.py`) runs unconditionally and does not read this
12
+ flag.
11
13
  """
12
14
 
13
15
  from __future__ import annotations
@@ -1,4 +1,8 @@
1
- """Tests for the prose-style enforcement opt-in flag (default off)."""
1
+ """Tests for the prose-style enforcement opt-in flag.
2
+
3
+ Gates ``plain_language_blocker.py`` and ``hook_prose_detector_consistency.py``;
4
+ default off.
5
+ """
2
6
 
3
7
  from __future__ import annotations
4
8
 
@@ -1,26 +1 @@
1
- # inventory_intent_records
2
1
 
3
- The shared pending-intent store that lets `package_inventory_stale_blocker.py`
4
- and `claude_md_orphan_file_blocker.py` add a new file and its inventory row in
5
- one change, in either order. When one blocker denies, it records a note; the
6
- sibling blocker reads that note to allow the matching second write.
7
-
8
- ## Modules
9
-
10
- | File | Purpose |
11
- |---|---|
12
- | `records.py` | Read, record, peek, and consume the per-session file and row intents; a missing or corrupt store reads as no notes |
13
- | `__init__.py` | Package marker |
14
-
15
- ## Subdirectories
16
-
17
- | Entry | Description |
18
- |---|---|
19
- | `config/` | The records-file name shape, the freshness window, the list keys, and the note field names (`intent_records_constants.py`) |
20
- | `tests/` | pytest suite for the records store |
21
-
22
- ## Running tests
23
-
24
- ```bash
25
- python -m pytest packages/claude-dev-env/hooks/blocking/inventory_intent_records/tests/
26
- ```
@@ -1,26 +1 @@
1
- # package_inventory_stale_blocker_parts
2
1
 
3
- The concern modules `package_inventory_stale_blocker.py` wires together to block a
4
- new production file its package inventory omits. The entry hook imports them and
5
- re-exports their surface for the test suite.
6
-
7
- ## Modules
8
-
9
- | File | Purpose |
10
- |---|---|
11
- | `inventory_detection.py` | Surveys a directory's `README.md`/`CLAUDE.md`/`SKILL.md`, collects the filenames they name, and reports whether a maintained inventory omits the file being written |
12
- | `decision.py` | Builds the deny payload naming the omitted file and closing with the retry hint, and emits the decision JSON |
13
- | `__init__.py` | Package marker |
14
-
15
- ## Subdirectories
16
-
17
- | Entry | Description |
18
- |---|---|
19
- | `config/` | The retry hint the deny reason closes with and the inventory-name join separator (`inventory_blocker_constants.py`) |
20
- | `tests/` | pytest suite with one test module per module above |
21
-
22
- ## Running tests
23
-
24
- ```bash
25
- python -m pytest packages/claude-dev-env/hooks/blocking/package_inventory_stale_blocker_parts/tests/
26
- ```
@@ -1,24 +1 @@
1
- # pii_prevention_blocker_parts
2
1
 
3
- The concern modules `pii_prevention_blocker.py` wires together. The entry hook
4
- imports them and re-exports their surface for the test suite.
5
-
6
- ## Modules
7
-
8
- | File | Purpose |
9
- |---|---|
10
- | `repository_exemption.py` | Resolves a commit's origin owner/repo slug, decides whether the repository skips the staged PII scan, and resolves the exact values that repository allows past the scan |
11
- | `repository_resolution.py` | Reads the repository a commit command targets — composing multiple `-C` values and a leading `cd`/`pushd` — and builds the deny reason naming the path when the repository root does not resolve |
12
- | `__init__.py` | Package marker |
13
-
14
- ## Subdirectories
15
-
16
- | Entry | Description |
17
- |---|---|
18
- | `config/` | The repository-resolution deny-message template and the session-cwd label (`repository_resolution_constants.py`) |
19
-
20
- ## Running tests
21
-
22
- ```bash
23
- python -m pytest packages/claude-dev-env/hooks/blocking/tests/
24
- ```