claude-dev-env 2.12.0 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +61 -0
- package/CLAUDE.md +1 -57
- package/_shared/AGENTS.md +15 -0
- package/_shared/CLAUDE.md +1 -15
- package/_shared/advisor/AGENTS.md +22 -0
- package/_shared/advisor/CLAUDE.md +1 -22
- package/_shared/pr-loop/AGENTS.md +27 -0
- package/_shared/pr-loop/CLAUDE.md +1 -27
- package/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
- package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +42 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +1 -42
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +26 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -26
- package/_shared/pr-loop/scripts/test_code_rules_gate.py +0 -26
- package/_shared/pr-loop/scripts/tests/AGENTS.md +44 -0
- package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -44
- package/_shared/process-tree/AGENTS.md +41 -0
- package/_shared/process-tree/CLAUDE.md +1 -41
- package/agents/AGENTS.md +31 -0
- package/agents/CLAUDE.md +1 -32
- package/agents/clean-coder.md +6 -6
- package/agents/pr-description-writer.md +11 -81
- package/agents/test_agent_frontmatter.py +4 -4
- package/audit-rubrics/AGENTS.md +43 -0
- package/audit-rubrics/CLAUDE.md +1 -43
- package/audit-rubrics/category_rubrics/AGENTS.md +37 -0
- package/audit-rubrics/category_rubrics/CLAUDE.md +1 -37
- package/audit-rubrics/prompts/AGENTS.md +37 -0
- package/audit-rubrics/prompts/CLAUDE.md +1 -37
- package/bin/AGENTS.md +112 -0
- package/bin/CLAUDE.md +1 -112
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +6 -7
- package/bin/install.mjs +71 -13
- package/bin/install.prune.test.mjs +26 -0
- package/bin/install.settings-defaults.test.mjs +60 -33
- package/bin/install.test.mjs +36 -4
- package/commands/AGENTS.md +23 -0
- package/commands/CLAUDE.md +1 -23
- package/commands/hook-log-extract.md +3 -3
- package/commands/sr-loop.md +9 -5
- package/docs/AGENTS.md +32 -0
- package/docs/CLAUDE.md +1 -33
- package/docs/CODE_RULES.md +1 -1
- package/docs/imagegen.md +22 -0
- package/docs/references/AGENTS.md +17 -0
- package/docs/references/CLAUDE.md +1 -18
- package/hooks/AGENTS.md +31 -0
- package/hooks/CLAUDE.md +1 -31
- package/hooks/_gh_pr_author_swap_utils.py +14 -0
- package/hooks/advisory/AGENTS.md +16 -0
- package/hooks/advisory/CLAUDE.md +1 -16
- package/hooks/blocking/AGENTS.md +123 -0
- package/hooks/blocking/CLAUDE.md +1 -148
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +28 -0
- package/hooks/blocking/claude_md_orphan_file_blocker_parts/CLAUDE.md +1 -28
- package/hooks/blocking/code_rules_banned_identifiers.py +1 -1
- package/hooks/blocking/code_rules_dead_module_constant.py +149 -37
- package/hooks/blocking/code_rules_probe_chains.py +6 -2
- package/hooks/blocking/config/AGENTS.md +10 -0
- package/hooks/blocking/config/CLAUDE.md +1 -22
- package/hooks/blocking/conventional_pr_title_gate.py +1 -2
- package/hooks/blocking/gh_pr_author_restore.py +7 -2
- package/hooks/blocking/intent_only_ending_blocker.py +11 -16
- package/hooks/blocking/inventory_intent_records/AGENTS.md +26 -0
- package/hooks/blocking/inventory_intent_records/CLAUDE.md +1 -26
- package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +26 -0
- package/hooks/blocking/package_inventory_stale_blocker_parts/CLAUDE.md +1 -26
- package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +24 -0
- package/hooks/blocking/pii_prevention_blocker_parts/CLAUDE.md +1 -24
- package/hooks/blocking/send_user_file_open_locally_blocker.py +1 -1
- package/hooks/blocking/stop_dispatcher.py +4 -4
- package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +30 -0
- package/hooks/blocking/tdd_enforcer_parts/CLAUDE.md +1 -30
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -3
- package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +171 -0
- package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
- package/hooks/blocking/test_gh_pr_author_restore.py +2 -1
- package/hooks/blocking/test_intent_only_ending_blocker.py +4 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +6 -7
- package/hooks/blocking/test_send_user_file_open_locally_blocker.py +4 -3
- package/hooks/blocking/test_shared_stdin_adoption.py +0 -2
- package/hooks/diagnostic/AGENTS.md +43 -0
- package/hooks/diagnostic/CLAUDE.md +1 -43
- package/hooks/diagnostic/hook_log_extractor.py +4 -38
- package/hooks/diagnostic/hook_log_stop_wrapper.py +6 -155
- package/hooks/diagnostic/migrations/AGENTS.md +16 -0
- package/hooks/diagnostic/migrations/CLAUDE.md +1 -16
- package/hooks/diagnostic/queries/AGENTS.md +19 -0
- package/hooks/diagnostic/queries/CLAUDE.md +1 -19
- package/hooks/diagnostic/test_hook_log_extractor.py +10 -23
- package/hooks/diagnostic/test_hook_log_stop_wrapper.py +3 -331
- package/hooks/git-hooks/AGENTS.md +31 -0
- package/hooks/git-hooks/CLAUDE.md +1 -31
- package/hooks/git-hooks/git_hooks_constants/AGENTS.md +21 -0
- package/hooks/git-hooks/git_hooks_constants/CLAUDE.md +1 -21
- package/hooks/git-hooks/git_hooks_constants/__init__.py +4 -12
- package/hooks/git-hooks/pre_push.py +49 -118
- package/hooks/git-hooks/test_pre_push.py +111 -137
- package/hooks/hooks.json +0 -35
- package/hooks/hooks_constants/AGENTS.md +104 -0
- package/hooks/hooks_constants/CLAUDE.md +1 -113
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -11
- package/hooks/hooks_constants/convergence_branch_constants.py +0 -1
- package/hooks/hooks_constants/fable_spawn_gate_constants.py +3 -4
- package/hooks/hooks_constants/hook_log_extractor_constants.py +1 -2
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -8
- package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +1 -6
- package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/task_list_loop_starter_constants.py +4 -3
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +1 -26
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +0 -5
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
- package/hooks/hooks_constants/working_style_prompt_constants.py +29 -20
- package/hooks/lifecycle/AGENTS.md +18 -0
- package/hooks/lifecycle/CLAUDE.md +1 -20
- package/hooks/observability/AGENTS.md +20 -0
- package/hooks/observability/CLAUDE.md +1 -20
- package/hooks/session/AGENTS.md +33 -0
- package/hooks/session/CLAUDE.md +1 -33
- package/hooks/session/gh_pr_author_session_cleanup.py +7 -2
- package/hooks/session/task_list_loop_starter.py +3 -3
- package/hooks/session/test_gh_pr_author_session_cleanup.py +2 -1
- package/hooks/session/test_task_list_loop_starter.py +10 -2
- package/hooks/session/test_working_style_prompt.py +9 -4
- package/hooks/validation/AGENTS.md +20 -0
- package/hooks/validation/CLAUDE.md +1 -20
- package/hooks/validators/AGENTS.md +51 -0
- package/hooks/validators/CLAUDE.md +1 -51
- package/hooks/validators/health_check.py +52 -19
- package/hooks/validators/python_style_checks.py +1 -1
- package/hooks/validators/test_health_check.py +112 -27
- package/hooks/workflow/AGENTS.md +16 -0
- package/hooks/workflow/CLAUDE.md +1 -16
- package/installable-surfaces.manifest.json +1 -0
- package/output-styles/AGENTS.md +15 -0
- package/output-styles/CLAUDE.md +1 -15
- package/package.json +2 -1
- package/rules/AGENTS.md +61 -0
- package/rules/CLAUDE.md +1 -63
- package/rules/code-standards.md +5 -9
- package/rules/doc-prose-cuts.md +1 -1
- package/rules/gh-cli-conventions.md +0 -1
- package/rules/git-workflow.md +1 -3
- package/scripts/AGENTS.md +62 -0
- package/scripts/CLAUDE.md +1 -63
- package/scripts/_code_review_test_support.py +0 -95
- package/scripts/codex_compat_materializer.py +4 -0
- package/scripts/dev_env_scripts_constants/AGENTS.md +21 -0
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -21
- package/scripts/dev_env_scripts_constants/code_review_constants.py +9 -98
- package/scripts/dev_env_scripts_constants/test_code_review_constants.py +1 -44
- package/scripts/invoke_code_review.py +8 -451
- package/scripts/sync_to_cursor/AGENTS.md +23 -0
- package/scripts/sync_to_cursor/CLAUDE.md +1 -23
- package/scripts/test_invoke_code_review.py +5 -61
- package/scripts/test_invoke_code_review_cli.py +1 -45
- package/scripts/test_invoke_code_review_contract.py +1 -118
- package/scripts/test_validate_instruction_pairs.py +90 -0
- package/scripts/test_verify_installable_package.py +5 -1
- package/scripts/tests/AGENTS.md +33 -0
- package/scripts/tests/CLAUDE.md +1 -33
- package/scripts/tests/test_codex_compat_materializer.py +36 -1
- package/scripts/validate_instruction_pairs.py +183 -0
- package/settings.json +1 -10
- package/skills/AGENTS.md +72 -0
- package/skills/CLAUDE.md +1 -64
- package/skills/_shared/AGENTS.md +44 -0
- package/skills/_shared/CLAUDE.md +1 -44
- package/skills/_shared/advisor/AGENTS.md +9 -0
- package/skills/_shared/advisor/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/AGENTS.md +50 -0
- package/skills/_shared/pr-loop/CLAUDE.md +1 -50
- package/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
- package/skills/_shared/pr-loop/prompts/CLAUDE.md +1 -9
- package/skills/_shared/pr-loop/scripts/AGENTS.md +35 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -35
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +24 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -24
- package/skills/anthropic-plan/AGENTS.md +34 -0
- package/skills/anthropic-plan/CLAUDE.md +1 -34
- package/skills/anthropic-plan/scripts/AGENTS.md +11 -0
- package/skills/anthropic-plan/scripts/CLAUDE.md +1 -11
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +16 -0
- package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +1 -16
- package/skills/anthropic-plan/templates/AGENTS.md +13 -0
- package/skills/anthropic-plan/templates/CLAUDE.md +1 -13
- package/skills/anthropic-plan/workflow/AGENTS.md +14 -0
- package/skills/anthropic-plan/workflow/CLAUDE.md +1 -14
- package/skills/auditing-claude-config/AGENTS.md +21 -0
- package/skills/auditing-claude-config/CLAUDE.md +1 -21
- package/skills/autoconverge/AGENTS.md +36 -0
- package/skills/autoconverge/CLAUDE.md +1 -36
- package/skills/autoconverge/reference/AGENTS.md +16 -0
- package/skills/autoconverge/reference/CLAUDE.md +1 -16
- package/skills/autoconverge/reference/convergence.md +7 -7
- package/skills/autoconverge/reference/gotchas.md +3 -10
- package/skills/autoconverge/workflow/AGENTS.md +26 -0
- package/skills/autoconverge/workflow/CLAUDE.md +1 -26
- package/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +16 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +1 -16
- package/skills/autoconverge/workflow/converge.contract.test.mjs +53 -1388
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +4 -3
- package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +33 -493
- package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +15 -97
- package/skills/autoconverge/workflow/converge.mjs +201 -238
- package/skills/autoconverge/workflow/converge.precatch.test.mjs +1 -1
- package/skills/bugteam/AGENTS.md +30 -0
- package/skills/bugteam/CLAUDE.md +1 -30
- package/skills/bugteam/CONSTRAINTS.md +1 -1
- package/skills/bugteam/SKILL.md +9 -0
- package/skills/bugteam/reference/AGENTS.md +20 -0
- package/skills/bugteam/reference/CLAUDE.md +1 -20
- package/skills/bugteam/reference/audit-and-teammates.md +10 -6
- package/skills/bugteam/reference/obstacles/AGENTS.md +24 -0
- package/skills/bugteam/reference/obstacles/CLAUDE.md +1 -24
- package/skills/bugteam/scripts/AGENTS.md +30 -0
- package/skills/bugteam/scripts/CLAUDE.md +1 -30
- package/skills/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +18 -0
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +1 -18
- package/skills/bugteam/test_skill_additions.py +9 -0
- package/skills/closeout/reference/handoff-prompt-template.md +1 -1
- package/skills/codex-review/AGENTS.md +46 -0
- package/skills/codex-review/CLAUDE.md +1 -46
- package/skills/codex-review/reference/AGENTS.md +15 -0
- package/skills/codex-review/reference/CLAUDE.md +1 -15
- package/skills/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
- package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +1 -18
- package/skills/codex-review/test_skill_scaffold.py +3 -3
- package/skills/comments/SKILL.md +65 -0
- package/skills/copilot-review/AGENTS.md +18 -0
- package/skills/copilot-review/CLAUDE.md +1 -18
- package/skills/descriptions/SKILL.md +51 -0
- package/skills/emergencies/SKILL.md +42 -0
- package/skills/everything-search/AGENTS.md +17 -0
- package/skills/everything-search/CLAUDE.md +1 -17
- package/skills/fresh-branch/AGENTS.md +14 -0
- package/skills/fresh-branch/CLAUDE.md +1 -14
- package/skills/grok-spawn/AGENTS.md +28 -0
- package/skills/grok-spawn/CLAUDE.md +1 -28
- package/skills/orchestrator/SKILL.md +2 -4
- package/skills/plan-to-pr/SKILL.md +6 -7
- package/skills/plan-to-pr/reference/final-validation-tasks.md +1 -1
- package/skills/plan-to-pr/reference/process-inventory.md +2 -2
- package/skills/plan-to-pr/reference/review-loop.md +2 -2
- package/skills/plan-to-pr/reference/run-record.schema.json +1 -1
- package/skills/plan-to-pr/reference/task-seeds.md +1 -1
- package/skills/plan-to-pr/reference/task-ticket.md +3 -4
- package/skills/plan-to-pr/scripts/config/constants.py +1 -2
- package/skills/plan-to-pr/scripts/test_validate_protocol.py +1 -1
- package/skills/plan-to-pr/test_skill_contract.py +2 -2
- package/skills/pr-converge/AGENTS.md +32 -0
- package/skills/pr-converge/CLAUDE.md +1 -32
- package/skills/pr-converge/SKILL.md +13 -16
- package/skills/pr-converge/pr_converge_skill_constants/AGENTS.md +26 -0
- package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +1 -26
- package/skills/pr-converge/reference/AGENTS.md +28 -0
- package/skills/pr-converge/reference/CLAUDE.md +1 -28
- package/skills/pr-converge/reference/obstacles/AGENTS.md +23 -0
- package/skills/pr-converge/reference/obstacles/CLAUDE.md +1 -23
- package/skills/pr-converge/reference/progress-checklist.md +6 -5
- package/skills/pr-converge/reference/state-schema.md +1 -27
- package/skills/pr-converge/scripts/AGENTS.md +46 -0
- package/skills/pr-converge/scripts/CLAUDE.md +1 -46
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -18
- package/skills/pr-converge/workflows/AGENTS.md +16 -0
- package/skills/pr-converge/workflows/CLAUDE.md +1 -16
- package/skills/pr-loop-cloud-transport/SKILL.md +1 -1
- package/skills/pr-loop-cloud-transport/reference/identity-and-hooks.md +3 -3
- package/skills/pr-loop-lifecycle/SKILL.md +1 -1
- package/skills/pr-loop-lifecycle/reference/teardown-publish-permissions.md +1 -1
- package/skills/prototype/SKILL.md +4 -4
- package/skills/prototype/reference/honest-limitations.md +5 -5
- package/skills/prototype/reference/promotion-tasks.md +2 -2
- package/skills/prototype/workflows/promotion.md +4 -6
- package/skills/rebase/AGENTS.md +32 -0
- package/skills/rebase/CLAUDE.md +1 -32
- package/skills/recall/AGENTS.md +30 -0
- package/skills/recall/CLAUDE.md +1 -30
- package/skills/remember/AGENTS.md +31 -0
- package/skills/remember/CLAUDE.md +1 -31
- package/skills/reviews/SKILL.md +85 -0
- package/skills/session-log/AGENTS.md +32 -0
- package/skills/session-log/CLAUDE.md +1 -32
- package/skills/session-tidy/AGENTS.md +36 -0
- package/skills/session-tidy/CLAUDE.md +1 -36
- package/skills/skill-builder/AGENTS.md +49 -0
- package/skills/skill-builder/CLAUDE.md +1 -49
- package/skills/skill-builder/references/AGENTS.md +25 -0
- package/skills/skill-builder/references/CLAUDE.md +1 -25
- package/skills/skill-builder/references/deterministic-elements.md +1 -1
- package/skills/skill-builder/templates/AGENTS.md +14 -0
- package/skills/skill-builder/templates/CLAUDE.md +1 -14
- package/skills/skill-builder/workflows/AGENTS.md +19 -0
- package/skills/skill-builder/workflows/CLAUDE.md +1 -19
- package/skills/small-cl/SKILL.md +52 -0
- package/skills/task-build/AGENTS.md +29 -0
- package/skills/task-build/CLAUDE.md +1 -29
- package/skills/update/AGENTS.md +38 -0
- package/skills/update/CLAUDE.md +1 -38
- package/system-prompts/AGENTS.md +17 -0
- package/system-prompts/CLAUDE.md +1 -17
- package/system-prompts/software-engineer.xml +3 -3
- package/agents/code-verifier.md +0 -74
- package/docs/PR_DESCRIPTION_GUIDE.md +0 -157
- package/docs/references/code-review-enforcement.md +0 -132
- package/hooks/blocking/code_review_enforcement_config_bootstrap.py +0 -53
- package/hooks/blocking/code_review_gate_deny.py +0 -74
- package/hooks/blocking/code_review_pr_create_gate.py +0 -198
- package/hooks/blocking/code_review_push_gate.py +0 -145
- package/hooks/blocking/code_review_stamp_directory_write_blocker.py +0 -348
- package/hooks/blocking/code_review_stamp_store.py +0 -233
- package/hooks/blocking/code_review_stamp_write_blocker_parts/__init__.py +0 -7
- package/hooks/blocking/code_review_stamp_write_blocker_parts/conftest.py +0 -15
- package/hooks/blocking/code_review_stamp_write_blocker_parts/obfuscated_stamp_path_reference.py +0 -212
- package/hooks/blocking/code_review_stamp_write_blocker_parts/split_directory_change_into_stamp.py +0 -138
- package/hooks/blocking/code_review_stamp_write_blocker_parts/test_obfuscated_stamp_path_reference.py +0 -49
- package/hooks/blocking/code_review_stamp_write_blocker_parts/test_split_directory_change_into_stamp.py +0 -38
- package/hooks/blocking/code_verifier_spawn_preflight_gate.py +0 -483
- package/hooks/blocking/config/code_review_enforcement_constants.py +0 -143
- package/hooks/blocking/config/test_code_review_enforcement_constants.py +0 -166
- package/hooks/blocking/config/verified_commit_constants.py +0 -160
- package/hooks/blocking/config/verified_commit_context_constants.py +0 -21
- package/hooks/blocking/config/verified_commit_gate_output_constants.py +0 -14
- package/hooks/blocking/conftest.py +0 -123
- package/hooks/blocking/convergence_gate_blocker.py +0 -310
- package/hooks/blocking/pr_converge_bugteam_enforcer.py +0 -170
- package/hooks/blocking/pr_description_body_audit.py +0 -148
- package/hooks/blocking/pr_description_command_parser.py +0 -237
- package/hooks/blocking/pr_description_enforcer.py +0 -227
- package/hooks/blocking/pr_description_pr_number.py +0 -155
- package/hooks/blocking/pr_description_proof_of_work.py +0 -385
- package/hooks/blocking/pr_description_readability.py +0 -364
- package/hooks/blocking/reviewer_spawn_gate.py +0 -182
- package/hooks/blocking/test_code_review_enforcement_config_bootstrap.py +0 -62
- package/hooks/blocking/test_code_review_gate_deny.py +0 -54
- package/hooks/blocking/test_code_review_pr_create_gate.py +0 -199
- package/hooks/blocking/test_code_review_push_gate.py +0 -205
- package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +0 -199
- package/hooks/blocking/test_code_review_stamp_store.py +0 -205
- package/hooks/blocking/test_code_verifier_spawn_preflight_gate.py +0 -710
- package/hooks/blocking/test_code_verifier_tools_contract.py +0 -28
- package/hooks/blocking/test_convergence_gate_blocker.py +0 -428
- package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +0 -311
- package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +0 -184
- package/hooks/blocking/test_pr_description_enforcer.py +0 -221
- package/hooks/blocking/test_pr_description_enforcer_body_audit.py +0 -247
- package/hooks/blocking/test_pr_description_enforcer_body_rules.py +0 -493
- package/hooks/blocking/test_pr_description_enforcer_command_parser.py +0 -366
- package/hooks/blocking/test_pr_description_enforcer_pr_number.py +0 -159
- package/hooks/blocking/test_pr_description_enforcer_proof_gate.py +0 -175
- package/hooks/blocking/test_pr_description_enforcer_readability.py +0 -443
- package/hooks/blocking/test_pr_description_proof_of_work.py +0 -313
- package/hooks/blocking/test_reviewer_spawn_gate.py +0 -230
- package/hooks/blocking/test_verdict_directory_write_blocker.py +0 -804
- package/hooks/blocking/test_verification_verdict_store.py +0 -974
- package/hooks/blocking/test_verified_commit_config_bootstrap.py +0 -67
- package/hooks/blocking/test_verified_commit_docs_delta.py +0 -176
- package/hooks/blocking/test_verified_commit_gate.py +0 -581
- package/hooks/blocking/test_verified_commit_gate_additional_context.py +0 -134
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +0 -131
- package/hooks/blocking/test_verifier_verdict_minter.py +0 -299
- package/hooks/blocking/tests/test_verified_commit_gate.py +0 -41
- package/hooks/blocking/verdict_directory_write_blocker.py +0 -687
- package/hooks/blocking/verification_verdict_store.py +0 -1039
- package/hooks/blocking/verified_commit_config_bootstrap.py +0 -63
- package/hooks/blocking/verified_commit_gate.py +0 -113
- package/hooks/blocking/verified_commit_gate_parts/CLAUDE.md +0 -28
- package/hooks/blocking/verified_commit_gate_parts/__init__.py +0 -1
- package/hooks/blocking/verified_commit_gate_parts/command_tokenization.py +0 -174
- package/hooks/blocking/verified_commit_gate_parts/deny_payload.py +0 -53
- package/hooks/blocking/verified_commit_gate_parts/deny_reason.py +0 -80
- package/hooks/blocking/verified_commit_gate_parts/directory_resolution.py +0 -170
- package/hooks/blocking/verified_commit_gate_parts/gated_invocations.py +0 -217
- package/hooks/blocking/verified_commit_gate_parts/tests/conftest.py +0 -10
- package/hooks/blocking/verified_commit_gate_parts/tests/test_command_tokenization.py +0 -94
- package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_payload.py +0 -17
- package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_reason.py +0 -38
- package/hooks/blocking/verified_commit_gate_parts/tests/test_directory_resolution.py +0 -71
- package/hooks/blocking/verified_commit_gate_parts/tests/test_gated_invocations.py +0 -96
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +0 -167
- package/hooks/blocking/verifier_verdict_minter.py +0 -280
- package/hooks/hooks_constants/code_verifier_spawn_preflight_gate_constants.py +0 -64
- package/hooks/hooks_constants/convergence_gate_blocker_constants.py +0 -53
- package/hooks/hooks_constants/pr_converge_bugteam_enforcer_constants.py +0 -55
- package/hooks/hooks_constants/pr_converge_bugteam_enforcer_state.py +0 -67
- package/hooks/hooks_constants/pr_description_enforcer_constants.py +0 -167
- package/hooks/hooks_constants/pr_description_proof_of_work_constants.py +0 -107
- package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +0 -41
- package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +0 -292
- package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +0 -198
- package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +0 -283
- package/rules/proof-of-work-pr-comments.md +0 -22
- package/rules/verified-commit-gate-skip.md +0 -4
- package/scripts/Show-Asset.ps1 +0 -106
|
@@ -1,345 +1,17 @@
|
|
|
1
|
-
"""Tests for
|
|
1
|
+
"""Tests for the disabled hook_log_stop_wrapper Stop hook."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
|
-
import subprocess
|
|
7
5
|
import sys
|
|
8
|
-
import time
|
|
9
6
|
from pathlib import Path
|
|
10
7
|
|
|
11
|
-
import pytest
|
|
12
|
-
|
|
13
8
|
_HOOKS_ROOT = Path(__file__).resolve().parent.parent
|
|
14
9
|
if str(_HOOKS_ROOT) not in sys.path:
|
|
15
10
|
sys.path.insert(0, str(_HOOKS_ROOT))
|
|
16
11
|
|
|
17
12
|
from diagnostic import hook_log_stop_wrapper
|
|
18
|
-
from hooks_constants.hook_log_extractor_constants import (
|
|
19
|
-
BWS_ACCESS_TOKEN_ENV_VAR,
|
|
20
|
-
BWS_EXECUTABLE_NAME,
|
|
21
|
-
FLAG_INCREMENTAL,
|
|
22
|
-
STOP_WRAPPER_DEBOUNCE_SECONDS,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _redirect_timestamp_path(
|
|
27
|
-
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
28
|
-
) -> Path:
|
|
29
|
-
timestamp_file = tmp_path / "stop_wrapper_last_run.txt"
|
|
30
|
-
monkeypatch.setattr(
|
|
31
|
-
hook_log_stop_wrapper,
|
|
32
|
-
"_last_run_timestamp_path",
|
|
33
|
-
lambda: timestamp_file,
|
|
34
|
-
)
|
|
35
|
-
return timestamp_file
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def test_main_returns_zero_when_extractor_spawn_raises(
|
|
39
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
40
|
-
tmp_path: Path,
|
|
41
|
-
) -> None:
|
|
42
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
43
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
44
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
45
|
-
|
|
46
|
-
def _raise(*_args: object, **_kwargs: object) -> None:
|
|
47
|
-
raise RuntimeError("boom")
|
|
48
13
|
|
|
49
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _raise)
|
|
50
14
|
|
|
15
|
+
def test_main_returns_zero_without_side_effects() -> None:
|
|
16
|
+
"""Disabled main exits success and does no work."""
|
|
51
17
|
assert hook_log_stop_wrapper.main() == 0
|
|
52
|
-
assert not timestamp_file.exists()
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_main_writes_timestamp_before_spawn_to_narrow_toctou_window(
|
|
56
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
57
|
-
tmp_path: Path,
|
|
58
|
-
) -> None:
|
|
59
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
60
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
61
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
62
|
-
|
|
63
|
-
timestamp_file_existed_at_spawn_time: list[bool] = []
|
|
64
|
-
|
|
65
|
-
def _capture_timestamp_state(*_args: object, **_kwargs: object) -> object:
|
|
66
|
-
timestamp_file_existed_at_spawn_time.append(timestamp_file.exists())
|
|
67
|
-
return object()
|
|
68
|
-
|
|
69
|
-
monkeypatch.setattr(
|
|
70
|
-
hook_log_stop_wrapper.subprocess, "Popen", _capture_timestamp_state
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
hook_log_stop_wrapper.main()
|
|
74
|
-
|
|
75
|
-
assert timestamp_file_existed_at_spawn_time == [True]
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def test_main_removes_timestamp_when_spawn_fails_to_allow_retry(
|
|
79
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
80
|
-
tmp_path: Path,
|
|
81
|
-
) -> None:
|
|
82
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
83
|
-
timestamp_file.parent.mkdir(parents=True, exist_ok=True)
|
|
84
|
-
stale_timestamp = time.time() - STOP_WRAPPER_DEBOUNCE_SECONDS - 1
|
|
85
|
-
timestamp_file.write_text(str(stale_timestamp))
|
|
86
|
-
|
|
87
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
88
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
89
|
-
|
|
90
|
-
def _raise(*_args: object, **_kwargs: object) -> None:
|
|
91
|
-
raise RuntimeError("boom")
|
|
92
|
-
|
|
93
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _raise)
|
|
94
|
-
|
|
95
|
-
assert hook_log_stop_wrapper.main() == 0
|
|
96
|
-
assert not timestamp_file.exists()
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def test_main_uses_bws_when_token_and_binary_present(
|
|
100
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
101
|
-
tmp_path: Path,
|
|
102
|
-
) -> None:
|
|
103
|
-
_redirect_timestamp_path(monkeypatch, tmp_path)
|
|
104
|
-
monkeypatch.setenv(BWS_ACCESS_TOKEN_ENV_VAR, "secret-value")
|
|
105
|
-
monkeypatch.setattr(
|
|
106
|
-
hook_log_stop_wrapper.shutil,
|
|
107
|
-
"which",
|
|
108
|
-
lambda _name: "/usr/local/bin/bws",
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
captured_commands: list[list[str]] = []
|
|
112
|
-
|
|
113
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
114
|
-
captured_commands.append(list(command_list))
|
|
115
|
-
return object()
|
|
116
|
-
|
|
117
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
118
|
-
|
|
119
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
120
|
-
|
|
121
|
-
assert exit_code == 0
|
|
122
|
-
assert len(captured_commands) == 1
|
|
123
|
-
assert captured_commands[0][0] == BWS_EXECUTABLE_NAME
|
|
124
|
-
assert FLAG_INCREMENTAL in captured_commands[0]
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def test_main_skips_bws_when_token_missing(
|
|
128
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
129
|
-
tmp_path: Path,
|
|
130
|
-
) -> None:
|
|
131
|
-
_redirect_timestamp_path(monkeypatch, tmp_path)
|
|
132
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
133
|
-
monkeypatch.setattr(
|
|
134
|
-
hook_log_stop_wrapper.shutil,
|
|
135
|
-
"which",
|
|
136
|
-
lambda _name: "/usr/local/bin/bws",
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
captured_commands: list[list[str]] = []
|
|
140
|
-
|
|
141
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
142
|
-
captured_commands.append(list(command_list))
|
|
143
|
-
return object()
|
|
144
|
-
|
|
145
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
146
|
-
|
|
147
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
148
|
-
|
|
149
|
-
assert exit_code == 0
|
|
150
|
-
assert len(captured_commands) == 1
|
|
151
|
-
assert BWS_EXECUTABLE_NAME not in captured_commands[0]
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def test_main_skips_bws_when_binary_missing(
|
|
155
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
156
|
-
tmp_path: Path,
|
|
157
|
-
) -> None:
|
|
158
|
-
_redirect_timestamp_path(monkeypatch, tmp_path)
|
|
159
|
-
monkeypatch.setenv(BWS_ACCESS_TOKEN_ENV_VAR, "secret-value")
|
|
160
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
161
|
-
|
|
162
|
-
captured_commands: list[list[str]] = []
|
|
163
|
-
|
|
164
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
165
|
-
captured_commands.append(list(command_list))
|
|
166
|
-
return object()
|
|
167
|
-
|
|
168
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
169
|
-
|
|
170
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
171
|
-
|
|
172
|
-
assert exit_code == 0
|
|
173
|
-
assert len(captured_commands) == 1
|
|
174
|
-
assert BWS_EXECUTABLE_NAME not in captured_commands[0]
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def test_main_skips_spawn_when_recent_timestamp_within_debounce_window(
|
|
178
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
179
|
-
tmp_path: Path,
|
|
180
|
-
) -> None:
|
|
181
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
182
|
-
timestamp_file.parent.mkdir(parents=True, exist_ok=True)
|
|
183
|
-
timestamp_file.write_text(str(time.time()))
|
|
184
|
-
|
|
185
|
-
captured_commands: list[list[str]] = []
|
|
186
|
-
|
|
187
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
188
|
-
captured_commands.append(list(command_list))
|
|
189
|
-
return object()
|
|
190
|
-
|
|
191
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
192
|
-
|
|
193
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
194
|
-
|
|
195
|
-
assert exit_code == 0
|
|
196
|
-
assert len(captured_commands) == 0
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
def test_main_spawns_when_timestamp_older_than_debounce_window(
|
|
200
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
201
|
-
tmp_path: Path,
|
|
202
|
-
) -> None:
|
|
203
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
204
|
-
timestamp_file.parent.mkdir(parents=True, exist_ok=True)
|
|
205
|
-
stale_timestamp = time.time() - STOP_WRAPPER_DEBOUNCE_SECONDS - 1
|
|
206
|
-
timestamp_file.write_text(str(stale_timestamp))
|
|
207
|
-
|
|
208
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
209
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
210
|
-
|
|
211
|
-
captured_commands: list[list[str]] = []
|
|
212
|
-
|
|
213
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
214
|
-
captured_commands.append(list(command_list))
|
|
215
|
-
return object()
|
|
216
|
-
|
|
217
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
218
|
-
|
|
219
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
220
|
-
|
|
221
|
-
assert exit_code == 0
|
|
222
|
-
assert len(captured_commands) == 1
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
def test_main_writes_current_timestamp_to_file(
|
|
226
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
227
|
-
tmp_path: Path,
|
|
228
|
-
) -> None:
|
|
229
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
230
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
231
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
232
|
-
monkeypatch.setattr(
|
|
233
|
-
hook_log_stop_wrapper.subprocess,
|
|
234
|
-
"Popen",
|
|
235
|
-
lambda *_args, **_kwargs: object(),
|
|
236
|
-
)
|
|
237
|
-
|
|
238
|
-
timestamp_before_call = time.time()
|
|
239
|
-
hook_log_stop_wrapper.main()
|
|
240
|
-
timestamp_after_call = time.time()
|
|
241
|
-
|
|
242
|
-
assert timestamp_file.exists()
|
|
243
|
-
written_timestamp = float(timestamp_file.read_text().strip())
|
|
244
|
-
assert timestamp_before_call <= written_timestamp <= timestamp_after_call
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def test_main_passes_devnull_streams_to_detached_spawn(
|
|
248
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
249
|
-
tmp_path: Path,
|
|
250
|
-
) -> None:
|
|
251
|
-
_redirect_timestamp_path(monkeypatch, tmp_path)
|
|
252
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
253
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
254
|
-
|
|
255
|
-
captured_kwargs: dict[str, object] = {}
|
|
256
|
-
|
|
257
|
-
def _fake_popen(command_list: list[str], **kwargs: object) -> object:
|
|
258
|
-
captured_kwargs.update(kwargs)
|
|
259
|
-
return object()
|
|
260
|
-
|
|
261
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
262
|
-
|
|
263
|
-
hook_log_stop_wrapper.main()
|
|
264
|
-
|
|
265
|
-
assert captured_kwargs.get("stdin") is hook_log_stop_wrapper.subprocess.DEVNULL
|
|
266
|
-
assert captured_kwargs.get("stdout") is hook_log_stop_wrapper.subprocess.DEVNULL
|
|
267
|
-
assert captured_kwargs.get("stderr") is hook_log_stop_wrapper.subprocess.DEVNULL
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
def test_main_recovers_when_timestamp_file_is_corrupted(
|
|
271
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
272
|
-
tmp_path: Path,
|
|
273
|
-
) -> None:
|
|
274
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
275
|
-
timestamp_file.parent.mkdir(parents=True, exist_ok=True)
|
|
276
|
-
timestamp_file.write_text("not-a-float")
|
|
277
|
-
|
|
278
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
279
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
280
|
-
|
|
281
|
-
captured_commands: list[list[str]] = []
|
|
282
|
-
|
|
283
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
284
|
-
captured_commands.append(list(command_list))
|
|
285
|
-
return object()
|
|
286
|
-
|
|
287
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
288
|
-
|
|
289
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
290
|
-
|
|
291
|
-
assert exit_code == 0
|
|
292
|
-
assert len(captured_commands) == 1
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
def test_main_treats_future_timestamp_as_not_debounced(
|
|
296
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
297
|
-
tmp_path: Path,
|
|
298
|
-
) -> None:
|
|
299
|
-
timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
|
|
300
|
-
timestamp_file.parent.mkdir(parents=True, exist_ok=True)
|
|
301
|
-
far_future_timestamp = time.time() + 3600
|
|
302
|
-
timestamp_file.write_text(str(far_future_timestamp))
|
|
303
|
-
|
|
304
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
305
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
306
|
-
|
|
307
|
-
captured_commands: list[list[str]] = []
|
|
308
|
-
|
|
309
|
-
def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
|
|
310
|
-
captured_commands.append(list(command_list))
|
|
311
|
-
return object()
|
|
312
|
-
|
|
313
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
314
|
-
|
|
315
|
-
exit_code = hook_log_stop_wrapper.main()
|
|
316
|
-
|
|
317
|
-
assert exit_code == 0
|
|
318
|
-
assert len(captured_commands) == 1
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
def test_main_passes_hidden_startupinfo_on_windows(
|
|
322
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
323
|
-
tmp_path: Path,
|
|
324
|
-
) -> None:
|
|
325
|
-
_redirect_timestamp_path(monkeypatch, tmp_path)
|
|
326
|
-
monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
|
|
327
|
-
monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
|
|
328
|
-
|
|
329
|
-
captured_kwargs: dict[str, object] = {}
|
|
330
|
-
|
|
331
|
-
def _fake_popen(command_list: list[str], **kwargs: object) -> object:
|
|
332
|
-
captured_kwargs.update(kwargs)
|
|
333
|
-
return object()
|
|
334
|
-
|
|
335
|
-
monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
|
|
336
|
-
|
|
337
|
-
hook_log_stop_wrapper.main()
|
|
338
|
-
|
|
339
|
-
if os.name == "nt":
|
|
340
|
-
startup_info = captured_kwargs.get("startupinfo")
|
|
341
|
-
assert startup_info is not None
|
|
342
|
-
assert startup_info.dwFlags & subprocess.STARTF_USESHOWWINDOW
|
|
343
|
-
assert startup_info.wShowWindow == subprocess.SW_HIDE
|
|
344
|
-
else:
|
|
345
|
-
assert captured_kwargs.get("start_new_session") is True
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# hooks/git-hooks
|
|
2
|
+
|
|
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 the CODE_RULES gate (`precommit_code_rules_gate.py`) over staged changes; exits 1 when any staged file has a blocking violation |
|
|
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 after a commit lands; performs any post-commit bookkeeping |
|
|
13
|
+
| `gate_utils.py` | — | Shared helpers: resolves the gate script path, checks that the path is a safe regular file |
|
|
14
|
+
| `test_config.py` | — | Test configuration helpers |
|
|
15
|
+
| `test_gate_utils.py` | — | Tests for `gate_utils.py` |
|
|
16
|
+
| `test_pre_commit.py` | — | Tests for `pre_commit.py` |
|
|
17
|
+
| `test_pre_push.py` | — | Tests for `pre_push.py` |
|
|
18
|
+
| `test_pre_push_base_reference.py` | — | Tests for the gate base resolution in `pre_push.py` |
|
|
19
|
+
| `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 |
|
|
20
|
+
|
|
21
|
+
## Subdirectory
|
|
22
|
+
|
|
23
|
+
| Directory | Role |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `git_hooks_constants/` | Shared constants imported by the git-hook scripts |
|
|
26
|
+
|
|
27
|
+
## Conventions
|
|
28
|
+
|
|
29
|
+
- The installer strips the `_` and `.py` suffix when copying into the live git-hooks path (e.g. `pre_commit.py` becomes `pre-commit`).
|
|
30
|
+
- Constants (exit codes, argument names, error messages) live in `git_hooks_constants/` and are imported at the top of each script.
|
|
31
|
+
- Run tests with `python -m pytest git-hooks/test_<name>.py`.
|
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 the CODE_RULES gate (`precommit_code_rules_gate.py`) over staged changes; exits 1 when any staged file has a blocking violation |
|
|
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 after a commit lands; performs any post-commit bookkeeping |
|
|
13
|
-
| `gate_utils.py` | — | Shared helpers: resolves the gate script path, checks that the path is a safe regular file |
|
|
14
|
-
| `test_config.py` | — | Test configuration helpers |
|
|
15
|
-
| `test_gate_utils.py` | — | Tests for `gate_utils.py` |
|
|
16
|
-
| `test_pre_commit.py` | — | Tests for `pre_commit.py` |
|
|
17
|
-
| `test_pre_push.py` | — | Tests for `pre_push.py` |
|
|
18
|
-
| `test_pre_push_base_reference.py` | — | Tests for the gate base resolution in `pre_push.py` |
|
|
19
|
-
| `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 |
|
|
20
|
-
|
|
21
|
-
## Subdirectory
|
|
22
|
-
|
|
23
|
-
| Directory | Role |
|
|
24
|
-
|---|---|
|
|
25
|
-
| `git_hooks_constants/` | Shared constants imported by the git-hook scripts |
|
|
26
|
-
|
|
27
|
-
## Conventions
|
|
28
|
-
|
|
29
|
-
- The installer strips the `_` and `.py` suffix when copying into the live git-hooks path (e.g. `pre_commit.py` becomes `pre-commit`).
|
|
30
|
-
- Constants (exit codes, argument names, error messages) live in `git_hooks_constants/` and are imported at the top of each script.
|
|
31
|
-
- Run tests with `python -m pytest git-hooks/test_<name>.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# hooks/git-hooks/git_hooks_constants
|
|
2
|
+
|
|
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,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
+
@AGENTS.md
|
|
@@ -49,12 +49,9 @@ NO_PARSEABLE_STDIN_LINES_MESSAGE: str = (
|
|
|
49
49
|
NO_PARSEABLE_STDIN_LINES_SENTINEL: str = "__no_parseable_stdin_lines__"
|
|
50
50
|
UNRESOLVABLE_MERGE_BASE_SENTINEL: str = "__unresolvable_merge_base__"
|
|
51
51
|
UNRESOLVABLE_MERGE_BASE_MESSAGE: str = (
|
|
52
|
-
"claude-dev-env pre-push:
|
|
53
|
-
"and
|
|
54
|
-
"
|
|
55
|
-
"default branch hold unrelated histories, or when a default-branch ref "
|
|
56
|
-
"resolved and merge-base still could not name a shared commit "
|
|
57
|
-
"(for example a shallow clone missing the connecting history)."
|
|
52
|
+
"claude-dev-env pre-push: CODE_RULES validation is pending because the pushed "
|
|
53
|
+
"object and default branch have no shared merge base. Restore shared history "
|
|
54
|
+
"or provide a reachable default branch, then run the push again."
|
|
58
55
|
)
|
|
59
56
|
LOCAL_BRANCH_REFERENCE_PREFIX: str = "refs/heads/"
|
|
60
57
|
ORIGIN_HEAD_SYMBOLIC_REFERENCE: str = "refs/remotes/origin/HEAD"
|
|
@@ -63,6 +60,7 @@ ALL_DEFAULT_BRANCH_FALLBACK_REFERENCES: tuple[str, ...] = (
|
|
|
63
60
|
"refs/remotes/origin/main",
|
|
64
61
|
"refs/remotes/origin/master",
|
|
65
62
|
)
|
|
63
|
+
REMOTE_BRANCH_REFERENCE_TEMPLATE: str = "refs/remotes/{remote}/{branch}"
|
|
66
64
|
ALL_GIT_SYMBOLIC_REFERENCE_COMMAND_PREFIX: tuple[str, ...] = (
|
|
67
65
|
"git",
|
|
68
66
|
"symbolic-ref",
|
|
@@ -76,12 +74,6 @@ ALL_GIT_VERIFY_REFERENCE_COMMAND_PREFIX: tuple[str, ...] = (
|
|
|
76
74
|
)
|
|
77
75
|
ALL_GIT_MERGE_BASE_COMMAND_PREFIX: tuple[str, ...] = ("git", "merge-base")
|
|
78
76
|
GIT_REFERENCE_QUERY_TIMEOUT_SECONDS: int = 15
|
|
79
|
-
CODE_REVIEW_PUSH_GATE_PATH_OVERRIDE_ENV_VAR: str = "CODE_REVIEW_PUSH_GATE_PATH"
|
|
80
|
-
CODE_REVIEW_PUSH_GATE_MODULE_NAME: str = "code_review_push_gate"
|
|
81
|
-
CODE_REVIEW_PUSH_GATE_SCRIPT_FILENAME: str = "code_review_push_gate.py"
|
|
82
|
-
CODE_REVIEW_DENY_REASON_FUNCTION_NAME: str = "deny_reason_for_directory"
|
|
83
|
-
BLOCKING_DIRECTORY_NAME: str = "blocking"
|
|
84
|
-
CODE_REVIEW_STAMP_BLOCK_EXIT_CODE: int = 1
|
|
85
77
|
ALL_PROTECTED_BRANCH_PUSH_NAMES: tuple[str, ...] = ("main", "master")
|
|
86
78
|
PROTECTED_BRANCH_PUSH_BLOCK_EXIT_CODE: int = 1
|
|
87
79
|
PROTECTED_BRANCH_PUSH_BLOCK_MESSAGE: str = (
|