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.
- package/.agents/agents/AGENTS.md +0 -31
- package/.agents/agents/clean-coder.md +1 -1
- package/.agents/agents/test_agent_frontmatter.py +3 -1
- package/.agents/skills/AGENTS.md +0 -70
- package/.agents/skills/_shared/AGENTS.md +0 -44
- package/.agents/skills/_shared/advisor/AGENTS.md +0 -8
- package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -57
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -8
- package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -34
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -23
- package/.agents/skills/autoconverge/AGENTS.md +0 -35
- package/.agents/skills/autoconverge/reference/AGENTS.md +0 -15
- package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -25
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -15
- package/.agents/skills/everything-search/AGENTS.md +0 -16
- package/.agents/skills/fresh-branch/AGENTS.md +0 -13
- package/.agents/skills/grok-spawn/AGENTS.md +0 -27
- package/.agents/skills/orchestrator/.claude/CLAUDE.md +1 -0
- package/.agents/skills/orchestrator/AGENTS.md +1 -0
- package/.agents/skills/orchestrator/SKILL.md +44 -53
- package/.agents/skills/orchestrator/reference/.claude/CLAUDE.md +1 -0
- package/.agents/skills/orchestrator/reference/AGENTS.md +1 -0
- package/.agents/skills/orchestrator/reference/consult-the-orchestrator.md +70 -0
- package/.agents/skills/orchestrator/reference/executor-consult-block.md +62 -0
- package/.agents/skills/orchestrator/reference/host-detect.md +15 -0
- package/.agents/skills/orchestrator/test_orchestrator_skill_contract.py +62 -0
- package/.agents/skills/orchestrator-refresh/SKILL.md +16 -34
- package/.agents/skills/rebase/AGENTS.md +0 -31
- package/.agents/skills/session-log/AGENTS.md +0 -31
- package/.agents/skills/session-tidy/AGENTS.md +0 -35
- package/.agents/skills/skill-builder/AGENTS.md +0 -48
- package/.agents/skills/skill-builder/references/AGENTS.md +0 -24
- package/.agents/skills/skill-builder/templates/AGENTS.md +0 -13
- package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -18
- package/.agents/skills/task-build/AGENTS.md +0 -28
- package/.agents/skills/update/AGENTS.md +0 -37
- package/.agents/skills-archived/AGENTS.md +0 -44
- package/.agents/skills-archived/anthropic-plan/AGENTS.md +0 -33
- package/.agents/skills-archived/anthropic-plan/scripts/AGENTS.md +0 -10
- package/.agents/skills-archived/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +0 -15
- package/.agents/skills-archived/anthropic-plan/templates/AGENTS.md +0 -12
- package/.agents/skills-archived/anthropic-plan/workflow/AGENTS.md +0 -13
- package/.agents/skills-archived/auditing-claude-config/AGENTS.md +0 -20
- package/.agents/skills-archived/bugteam/AGENTS.md +0 -29
- package/.agents/skills-archived/bugteam/reference/AGENTS.md +0 -19
- package/.agents/skills-archived/bugteam/reference/obstacles/AGENTS.md +0 -23
- package/.agents/skills-archived/bugteam/scripts/AGENTS.md +0 -29
- package/.agents/skills-archived/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/codex-review/AGENTS.md +0 -45
- package/.agents/skills-archived/codex-review/reference/AGENTS.md +0 -14
- package/.agents/skills-archived/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/codex-review/test_skill_scaffold.py +13 -3
- package/.agents/skills-archived/copilot-review/AGENTS.md +0 -17
- package/.agents/skills-archived/pr-converge/AGENTS.md +0 -31
- package/.agents/skills-archived/pr-converge/pr_converge_skill_constants/AGENTS.md +0 -25
- package/.agents/skills-archived/pr-converge/reference/AGENTS.md +0 -27
- package/.agents/skills-archived/pr-converge/reference/obstacles/AGENTS.md +0 -22
- package/.agents/skills-archived/pr-converge/scripts/AGENTS.md +0 -45
- package/.agents/skills-archived/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
- package/.agents/skills-archived/pr-converge/workflows/AGENTS.md +0 -15
- package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
- package/.agents/skills-archived/recall/AGENTS.md +0 -29
- package/.agents/skills-archived/remember/AGENTS.md +0 -30
- package/AGENTS.md +0 -112
- package/_shared/AGENTS.md +0 -16
- package/_shared/advisor/AGENTS.md +0 -21
- package/_shared/advisor/advisor-protocol.md +4 -1
- package/_shared/advisor/reference/consult-format.md +4 -2
- package/_shared/pr-loop/AGENTS.md +0 -27
- package/_shared/pr-loop/scripts/AGENTS.md +0 -49
- package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +0 -41
- package/_shared/pr-loop/scripts/codex_review_scripts_constants/AGENTS.md +0 -17
- package/_shared/pr-loop/scripts/pr_converge_scripts_constants/AGENTS.md +0 -17
- package/_shared/pr-loop/scripts/pr_converge_skill_constants/AGENTS.md +0 -25
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +0 -25
- package/_shared/pr-loop/scripts/tests/AGENTS.md +0 -43
- package/_shared/process-tree/AGENTS.md +0 -40
- package/audit-rubrics/AGENTS.md +0 -42
- package/audit-rubrics/category_rubrics/AGENTS.md +0 -36
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +16 -29
- package/audit-rubrics/prompts/AGENTS.md +0 -36
- package/audit-rubrics/prompts/category-o-docstring-vs-impl-drift.md +2 -2
- package/bin/AGENTS.md +0 -118
- package/bin/install.test.mjs +1 -1
- package/commands/AGENTS.md +0 -14
- package/docs/AGENTS.md +0 -31
- package/docs/CODE_RULES.md +3 -3
- package/docs/agent-spawn-protocol.md +1 -1
- package/docs/references/AGENTS.md +0 -16
- package/docs/references/prose-style-enforcement.md +5 -9
- package/hooks/AGENTS.md +0 -27
- package/hooks/advisory/AGENTS.md +0 -15
- package/hooks/blocking/AGENTS.md +0 -122
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +0 -27
- package/hooks/blocking/code_rules_docstrings.py +10 -2138
- package/hooks/blocking/code_rules_enforcer.py +0 -121
- package/hooks/blocking/code_rules_imports_logging.py +1 -236
- package/hooks/blocking/code_rules_shared.py +23 -0
- package/hooks/blocking/code_rules_test_layout.py +8 -8
- package/hooks/blocking/config/AGENTS.md +0 -9
- package/hooks/blocking/config/prose_style_enforcement_constants.py +4 -2
- package/hooks/blocking/config/test_prose_style_enforcement_constants.py +5 -1
- package/hooks/blocking/inventory_intent_records/AGENTS.md +0 -25
- package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +0 -25
- package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +0 -23
- package/hooks/blocking/precommit_code_rules_gate.py +8 -43
- package/hooks/blocking/state_description_blocker.py +1 -7
- package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +0 -29
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +0 -8
- package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +11 -112
- package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_split_entry_1.py +1 -18
- package/hooks/blocking/test_code_rules_shared.py +12 -0
- package/hooks/blocking/test_precommit_code_rules_gate.py +32 -179
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -1
- package/hooks/blocking/test_state_description_blocker.py +6 -4
- package/hooks/blocking/test_stop_dispatcher.py +5 -29
- package/hooks/git-hooks/AGENTS.md +0 -31
- package/hooks/git-hooks/git_hooks_constants/AGENTS.md +0 -20
- package/hooks/hooks_constants/AGENTS.md +0 -104
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +3 -0
- package/hooks/hooks_constants/messages.py +0 -2
- package/hooks/hooks_constants/precommit_code_rules_gate_constants.py +3 -17
- package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -2
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +7 -0
- package/hooks/hooks_constants/test_messages.py +5 -3
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -2
- package/hooks/lifecycle/AGENTS.md +0 -17
- package/hooks/observability/AGENTS.md +0 -19
- package/hooks/session/AGENTS.md +0 -37
- package/hooks/validation/AGENTS.md +0 -19
- package/hooks/validators/AGENTS.md +0 -51
- package/hooks/workflow/AGENTS.md +0 -15
- package/output-styles/AGENTS.md +0 -14
- package/package.json +1 -1
- package/rules/AGENTS.md +0 -58
- package/rules/claims-as-quotes.md +0 -10
- package/rules/code-standards.md +6 -6
- package/rules/explore-thoroughly.md +0 -1
- package/rules/failure-blast-radius.md +0 -8
- package/rules/falsify-before-green.md +0 -8
- package/rules/file-global-constants.md +2 -2
- package/rules/filesystem-search.md +1 -1
- package/rules/git-workflow.md +1 -9
- package/rules/hedging-claims.md +2 -6
- package/rules/long-horizon-autonomy.md +1 -1
- package/rules/measurement-denominators.md +0 -9
- package/rules/research-mode.md +0 -6
- package/rules/verify-before-asking.md +0 -5
- package/rules/verify-runtime-state.md +0 -5
- package/scripts/AGENTS.md +0 -55
- package/scripts/codex_compat_materializer.py +0 -12
- package/scripts/dev_env_scripts_constants/AGENTS.md +0 -20
- package/scripts/sync_to_cursor/AGENTS.md +0 -22
- package/scripts/sync_to_cursor/rules.py +0 -10
- package/scripts/tests/AGENTS.md +0 -34
- package/scripts/tests/test_engine.py +0 -1
- package/scripts/tests/test_rules.py +0 -1
- package/scripts/tests/test_sync_to_cursor.py +0 -1
- package/system-prompts/AGENTS.md +0 -24
- package/system-prompts/software-engineer.xml +3 -3
- package/hooks/blocking/code_rules_dead_argparse_argument.py +0 -554
- package/hooks/blocking/code_rules_dead_config_field.py +0 -568
- package/hooks/blocking/code_rules_dead_dataclass_field.py +0 -348
- package/hooks/blocking/code_rules_dead_module_constant.py +0 -757
- package/hooks/blocking/code_rules_dead_split_branch.py +0 -225
- package/hooks/blocking/code_rules_mock_completeness.py +0 -295
- package/hooks/blocking/code_rules_scope_binding.py +0 -151
- package/hooks/blocking/code_rules_unused_imports.py +0 -197
- package/hooks/blocking/hedging_language_blocker.py +0 -221
- package/hooks/blocking/intent_only_ending_blocker.py +0 -148
- package/hooks/blocking/test_code_rules_enforcer_dead_argparse_argument.py +0 -534
- package/hooks/blocking/test_code_rules_enforcer_dead_config_field.py +0 -846
- package/hooks/blocking/test_code_rules_enforcer_dead_dataclass_field.py +0 -507
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +0 -679
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_alias.py +0 -133
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant_read_cap.py +0 -103
- package/hooks/blocking/test_code_rules_enforcer_dead_split_branch.py +0 -105
- package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +0 -425
- package/hooks/blocking/test_code_rules_enforcer_docstring_cardinal_family.py +0 -176
- package/hooks/blocking/test_code_rules_enforcer_docstring_delegation_summary.py +0 -385
- package/hooks/blocking/test_code_rules_enforcer_docstring_fallback_branch.py +0 -398
- package/hooks/blocking/test_code_rules_enforcer_docstring_field_runmode_outcome.py +0 -129
- package/hooks/blocking/test_code_rules_enforcer_docstring_inline_literal_claim.py +0 -93
- package/hooks/blocking/test_code_rules_enforcer_docstring_length_constant_superlative.py +0 -198
- package/hooks/blocking/test_code_rules_enforcer_docstring_mark_glyph_enumeration.py +0 -262
- package/hooks/blocking/test_code_rules_enforcer_docstring_no_consumer.py +0 -93
- package/hooks/blocking/test_code_rules_enforcer_docstring_no_network.py +0 -115
- package/hooks/blocking/test_code_rules_enforcer_docstring_raises_largezipfile.py +0 -226
- package/hooks/blocking/test_code_rules_enforcer_docstring_returns_plural_cardinality.py +0 -207
- package/hooks/blocking/test_code_rules_enforcer_docstring_step_dispatch.py +0 -262
- package/hooks/blocking/test_code_rules_enforcer_docstring_type_checking_gate.py +0 -164
- package/hooks/blocking/test_code_rules_enforcer_docstring_unguarded_payload.py +0 -188
- package/hooks/blocking/test_code_rules_enforcer_import_block_sort.py +0 -157
- package/hooks/blocking/test_code_rules_enforcer_split_mocks_1.py +0 -303
- package/hooks/blocking/test_code_rules_enforcer_split_mocks_2.py +0 -111
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +0 -656
- package/hooks/blocking/test_hedging_language_blocker.py +0 -261
- package/hooks/blocking/test_intent_only_ending_blocker.py +0 -209
- package/hooks/hooks_constants/dead_argparse_argument_constants.py +0 -28
- package/hooks/hooks_constants/dead_config_field_constants.py +0 -39
- package/hooks/hooks_constants/dead_dataclass_field_constants.py +0 -25
- package/hooks/hooks_constants/dead_module_constant_constants.py +0 -30
- package/hooks/hooks_constants/hedging_uncertainty_constants.py +0 -42
- package/hooks/hooks_constants/test_dispatcher_constants_docstrings.py +0 -44
- package/rules/conservative-action.md +0 -17
- package/rules/context7.md +0 -8
- package/rules/few-words.md +0 -3
- 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
|
-
"""
|
|
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
|
-
|
|
14
|
-
|
|
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
|
|
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
|
|
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
|
|
82
|
-
|
|
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
|
-
|
|
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
|
|
10
|
-
|
|
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
|
|
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
|
-
```
|