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,113 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Shared constant modules imported by hooks throughout the `hooks/` tree. Each file holds the tunables for one hook or one cross-cutting concern, keeping magic values out of the hook scripts themselves.
|
|
4
|
-
|
|
5
|
-
## Files
|
|
6
|
-
|
|
7
|
-
| File | What it holds |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `__init__.py` | Package marker (`# pragma: no-tdd-gate`) |
|
|
10
|
-
| `any_type_config.py` | Config for the `Any`-type escape-hatch check |
|
|
11
|
-
| `ask_user_question_shape.py` | Pure AskUserQuestion lean-block shape analyzer: grades question and option-description prose against shared chat-detail markers and sentence/word caps with no hook I/O |
|
|
12
|
-
| `banned_identifiers_constants.py` | The set of banned short identifiers and banned function-name prefixes |
|
|
13
|
-
| `bash_pre_tool_use_dispatcher_constants.py` | Permission outcomes, tool-name sets, and the ordered hosted-hook roster for the Bash PreToolUse dispatcher (also covers PowerShell-shared gates) |
|
|
14
|
-
| `blocking_check_limits.py` | Max issue counts and preview lengths for blocking hooks |
|
|
15
|
-
| `bot_mention_comment_blocker_constants.py` | Patterns for detecting bot @-mentions in PR comments |
|
|
16
|
-
| `claude_md_orphan_file_blocker_constants.py` | Table patterns, file extensions, scan budget, and block-message text for the CLAUDE.md orphan-file blocker |
|
|
17
|
-
| `code_rules_enforcer_constants.py` | File-extension sets, test-path patterns, advisory line thresholds, boolean-name prefixes |
|
|
18
|
-
| `enter_worktree_prefetch_constants.py` | Tool name, origin-remote ref names, and git-command timeouts for the EnterWorktree origin-prefetch hook |
|
|
19
|
-
| `env_var_table_code_drift_constants.py` | Table patterns, env-var-name and code-file recognizers, scan budget, and block-message text for the env-var-table code-drift blocker |
|
|
20
|
-
| `code_rules_path_utils_constants.py` | Path-matching helpers used by the code-rules check modules |
|
|
21
|
-
| `code_verifier_spawn_preflight_gate_constants.py` | Subagent type, merge-tree command flags, timeouts, and deny-message text for the code-verifier spawn pre-flight gate |
|
|
22
|
-
| `command_dispatch_constants.py` | Command-word regex, command-key access pattern, tokenization pattern, and anchors for the unanchored command-dispatch meta-gate |
|
|
23
|
-
| `convergence_branch_constants.py` | Branch and worktree naming patterns for the convergence gate |
|
|
24
|
-
| `convergence_gate_blocker_constants.py` | The full-PR-URL and `--repo`/`-R` flag parse patterns that key the convergence gate to the PR its command names |
|
|
25
|
-
| `conventional_pr_title_gate_constants.py` | Bash tool name, gh executable basenames and pr create/edit subcommand tokens, title/repo flag names, semantic-title-CI workflow markers, the Conventional Commits type list and title pattern, the semantic-pull-request action `types:` input pattern, and block-message text for the conventional-PR-title gate |
|
|
26
|
-
| `dead_argparse_argument_constants.py` | Patterns for detecting unused argparse arguments |
|
|
27
|
-
| `dead_config_field_constants.py` | Patterns for detecting unused `*Config` / `*Selectors` dataclass fields |
|
|
28
|
-
| `dead_dataclass_field_constants.py` | Patterns for detecting unused dataclass fields |
|
|
29
|
-
| `dead_module_constant_constants.py` | Patterns for detecting unexported `UPPER_SNAKE` constants in `*_constants.py` modules |
|
|
30
|
-
| `destructive_command_segment_constants.py` | The list of destructive shell command patterns the blocker matches |
|
|
31
|
-
| `docstring_rule_gate_count_blocker_constants.py` | Target rule basename, spelled-out-number lookup, count-clause and `check_*` validator patterns, and block-message text for the docstring-rule gate-count staleness blocker |
|
|
32
|
-
| `duplicate_function_body_constants.py` | Hashing and comparison config for the duplicate-body check |
|
|
33
|
-
| `duplicate_rmtree_helper_blocker_constants.py` | Sanctioned Windows-safe rmtree helper names, the definition pattern, and the exempt-path set for the duplicate-rmtree-helper blocker |
|
|
34
|
-
| `dynamic_stderr_handler.py` | `DynamicStderrHandler` — a logging handler that resolves `sys.stderr` at emit time (for testability) |
|
|
35
|
-
| `eli11_reply_enforcer_constants.py` | Reply-shape thresholds (bullet cap, lead-line window, per-list-line word cap, overpacked list-line cap), the bullet / numbered-step / table-row / link-target / word patterns, the imperative instruction verbs, and the user-facing notice for the ELI11 reply-shape Stop hook |
|
|
36
|
-
| `fable_spawn_gate_constants.py` | The spawn tool-name set, the fable model alias and the model-id segment split pattern, the `FABLE-SPAWN-AUTHORIZED` authorization token, the advisor-protocol document path, payload field names, the deny message, and the deny `additionalContext` recovery text for the fable-tier spawn gate |
|
|
37
|
-
| `gh_pr_author_swap_constants.py` | Constants for the PR-author swap enforcement hooks |
|
|
38
|
-
| `hardcoded_user_path_constants.py` | Patterns for detecting hardcoded home-directory paths |
|
|
39
|
-
| `harness_scratchpad_constants.py` | Fixed path components (`claude` / `claude-` user-directory name and prefix, `scratchpad` leaf name), the PreToolUse session-id payload key, and the `CLAUDE_CODE_SESSION_ID` environment variable name that the code-rules and TDD gates use to recognize an existing harness session scratchpad directory |
|
|
40
|
-
| `hedging_uncertainty_constants.py` | Sentence-boundary pattern, explicit uncertainty label patterns, hedge-term list separator, and positive corrective block text for OP-07C sentence-scoped hedging |
|
|
41
|
-
| `hook_block_logger.py` | `log_hook_block()` — shared fail-safe logger every blocking hook calls to append a JSON record of each block decision to `~/.claude/logs/hook-blocks.log` |
|
|
42
|
-
| `hook_log_extractor_constants.py` | Neon table name, offset state file path, timeouts, and outcome-type mapping for the hook-log extractor |
|
|
43
|
-
| `hook_prose_detector_consistency_constants.py` | Trigger patterns and corrective messages for the hook-prose consistency checker |
|
|
44
|
-
| `hosted_hook_runner.py` | `run_hook_capturing_output()` — shared runner that runs one dispatcher-hosted hook in-process via runpy and returns its captured stdout and crash flag |
|
|
45
|
-
| `inline_tuple_string_magic_constants.py` | Patterns for detecting magic strings in inline tuple literals |
|
|
46
|
-
| `js_conventions_constants.py` | Banned identifier set, boolean-prefix pattern, and declaration/JSDoc patterns for the JavaScript convention checks |
|
|
47
|
-
| `local_identity.py` | Loader for local machine values: NAS host, ssh user, and ssh port the ssh enforcer guards (`CLAUDE_NAS_*` / `~/.claude/local-identity.json` with placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`, keyed by owner/repo slug) read from the git-ignored local file whose path `CLAUDE_LOCAL_IDENTITY_PATH` may point elsewhere; also composes the ssh enforcer's two deny messages that quote the NAS values |
|
|
48
|
-
| `messages.py` | Short user-facing notice strings shown when a Stop hook redirects agent behavior |
|
|
49
|
-
| `multi_edit_reconstruction.py` | `apply_edits()` / `edits_for_tool()` — shared helpers that reconstruct the post-edit content of an Edit or MultiEdit, imported by the blockers that judge post-edit content |
|
|
50
|
-
| `mypy_integration_constants.py` | Path markers (``.git``, ``.py``, ``pyproject.toml``) for mypy project-root resolution |
|
|
51
|
-
| `mypy_validator_cache_constants.py` | Cache paths and tunables for the mypy_validator per-session caches |
|
|
52
|
-
| `nas_ssh_binary_enforcer_constants.py` | Bash tool name, ssh-family basenames, OpenSSH binary path suffixes, and the batch-mode pattern for the NAS ssh binary enforcer; segment helpers come from `shell_command_segments.py` |
|
|
53
|
-
| `open_questions_in_plans_blocker_constants.py` | Patterns for detecting unresolved open questions in plan documents |
|
|
54
|
-
| `orphan_css_class_constants.py` | Scan radius and selector patterns for the orphan-CSS-class check |
|
|
55
|
-
| `package_inventory_stale_blocker_constants.py` | Inventory document names, production code extensions, backtick token pattern, smallest inventory size, exempt names, scan budget, and block-message text for the package-inventory stale-entry blocker |
|
|
56
|
-
| `paired_test_coverage_constants.py` | Test-directory name, stem-test filename affixes, test-file globs, exempt public-function names, scan budget, coverage threshold, and guidance text for the public-function paired-test coverage check |
|
|
57
|
-
| `path_rewriter_constants.py` | Path rewriting patterns for the Everything-search path rewriter |
|
|
58
|
-
| `pii_prevention_constants.py` | Patterns, allowlists, path exemptions, and deny-message text for `pii_prevention_blocker` |
|
|
59
|
-
| `piped_pytest_blocker_constants.py` | Bash tool name, pytest program basenames and the python-interpreter basename pattern, the pipe and segment-reset operator token sets, and the deny message for the piped-pytest blocker; classification that consumes those program and wrapper constants lives in `pytest_invocation.py` |
|
|
60
|
-
| `pytest_invocation.py` | Pure parsed-segment classifier for pytest runs through interpreters, shims, wrappers, and shell string-exec forms; no pipeline deny decision |
|
|
61
|
-
| `plain_language_blocker_constants.py` | The list of heavy words and their everyday replacements |
|
|
62
|
-
| `pr_converge_bugteam_enforcer_constants.py` | State keys and timing config for the bugteam-parallel enforcer |
|
|
63
|
-
| `pr_converge_bugteam_enforcer_state.py` | State-file helpers for the bugteam enforcer |
|
|
64
|
-
| `pr_description_enforcer_constants.py` | PR-description shape rules and command patterns |
|
|
65
|
-
| `pr_description_proof_of_work_constants.py` | Proof-part detection patterns, gh command tokens, and corrective messages for the proof-of-work comment audit |
|
|
66
|
-
| `prose_matcher_precision_constants.py` | Sample floor, keep/narrow precision floors, matcher ids, label decisions, advisory log path, emit caps, and context fingerprint length for OP-07B prose-matcher advisory telemetry |
|
|
67
|
-
| `pre_tool_use_stdin.py` | `read_hook_input_dictionary_from_stdin()` — shared stdin parser for PreToolUse hooks |
|
|
68
|
-
| `precommit_code_rules_gate_constants.py` | Scope argument and exit-code constants for the precommit gate |
|
|
69
|
-
| project_paths_reader.py | Loads ~/.claude/project-paths.json and finds a home-bounded git root for registry checks |
|
|
70
|
-
| `pyproject_config_discovery_constants.py` | Table names (``tool`` key, ``mypy``, ``ruff``) for resolving a validator's config from a pyproject.toml `[tool.<name>]` table |
|
|
71
|
-
| `pytest_testpaths_orphan_blocker_constants.py` | Marker filename, section and key names, test-file pattern, search budget, and block-message text for the pytest unregistered-test-directory blocker |
|
|
72
|
-
| `python_style_checks_constants.py` | Command-line argument count and blank-line count between top-level functions for the style validator |
|
|
73
|
-
| `reviewer_spawn_gate_constants.py` | Bash tool name, the sentinel marker, the Copilot and Bugbot trigger markers, the availability-script relative path and override env-var name, and the deny-message template for the reviewer-spawn gate |
|
|
74
|
-
| `ruff_integration_constants.py` | ``NO_COLOR`` / ``FORCE_COLOR`` environment variable names for plain ruff diagnostics |
|
|
75
|
-
| `send_user_file_open_locally_blocker_constants.py` | Tool name, proactive status, and the block message for the open-locally attach blocker |
|
|
76
|
-
| `sensitive_file_protector_constants.py` | Sensitive filename patterns, the committed-template suffixes that earn an exemption, the write/edit tool names, and the deny decision and message template for `sensitive_file_protector` |
|
|
77
|
-
| `session_edit_stage_gate_constants.py` | Tracker filename prefix/suffix, JSON payload key, edit tool name set, session-id sanitize pattern, lock filename suffix and lock-acquire timing, git diff command, commit flag escapes, and deny-message template shared by the session edit stage gate trio |
|
|
78
|
-
| `session_env_cleanup_constants.py` | Stale-age threshold and directory names for the session-env cleanup hook |
|
|
79
|
-
| `session_start_injector.py` | Pure SessionStart context injector: normalize `source` (`startup`/`resume`/`clear`/`compact`), honor enable/timeout, return structured injection results for starter hooks |
|
|
80
|
-
| `session_start_injector_constants.py` | Known SessionStart source values, injection status codes, enable env var, default timeout for the shared injector |
|
|
81
|
-
| `test_session_start_injector.py` | Behavioral tests for every known source, disabled, timeout, and unknown-source paths |
|
|
82
|
-
| `orchestrator_auto_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the orchestrator auto-starter |
|
|
83
|
-
| `issue_tracker_session_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the repository-gated issue-tracker starter |
|
|
84
|
-
| `session_handoff_blocker_constants.py` | Trigger phrases for the session-handoff blocker |
|
|
85
|
-
| `setup_project_paths_constants.py` | Encoding policy, BOM marker, and registry meta-key used across multiple hooks |
|
|
86
|
-
| `shell_command_pipeline.py` | Quote-aware shell pipeline parsing: operator-paired segments after line-continuation join, comment strip, heredoc body drop, and parenthesis-group join |
|
|
87
|
-
| `shell_command_segments.py` | Shell tokenization helpers shared by the segment-walking blockers: segment splitting on control operators, a segment's effective leading program, and a token's basename |
|
|
88
|
-
| `shell_substitution_blocker_constants.py` | Tool name, payload keys, the four substitution-detection patterns, the deny decision shape, and the corrective message for the shell-substitution blocker |
|
|
89
|
-
| `stale_comment_reference_blocker_constants.py` | Identifier pattern, comment stopwords, and denial text for the stale-comment-reference blocker |
|
|
90
|
-
| `state_description_blocker_constants.py` | The set of historical/comparative phrases the state-description blocker rejects, plus the docstring-extraction and mention-span patterns for its Python docstring scan |
|
|
91
|
-
| `stop_dispatcher_constants.py` | Ordered hosted-hook roster and Stop block payload field names for the Stop-chain dispatcher |
|
|
92
|
-
| `stuttering_check_config.py` | Config for the stuttering (repeated-phrase) check |
|
|
93
|
-
| `stuttering_import_binding_constants.py` | Import-binding patterns for the stuttering check |
|
|
94
|
-
| `subprocess_budget_completeness_constants.py` | Required argument names for the subprocess-budget completeness check |
|
|
95
|
-
| `sys_path_insert_constants.py` | Patterns for detecting unguarded `sys.path.insert` calls |
|
|
96
|
-
| `task_list_loop_starter_constants.py` | The one-line task-list instruction and the full session-start directive text for the task-list loop starter hook |
|
|
97
|
-
| `test_layout_constants.py` | The named constants for the test-layout write-time checks |
|
|
98
|
-
| `text_stripping.py` | `strip_code_and_quotes()` — shared helper that removes fenced code blocks, inline code, and blockquotes from prose, imported by the Stop-hook prose blockers |
|
|
99
|
-
| `unscoped_search_blocker_constants.py` | Tool names, `find` and listing program basenames, Get-ChildItem option sets, unscoped-root patterns, the flag/value token stride, and the deny message for the unscoped-search blocker |
|
|
100
|
-
| `unused_module_import_constants.py` | Patterns for detecting unused module-level imports |
|
|
101
|
-
| `volatile_path_in_post_blocker_constants.py` | Volatile path markers, affected `gh` post subcommands, MCP body param names, and the corrective message for the volatile-path post blocker |
|
|
102
|
-
| `windows_rmtree_blocker_constants.py` | The unsafe `shutil.rmtree` pattern and the safe replacement pattern |
|
|
103
|
-
| `workflow_substitution_slot_blocker_constants.py` | Per-iteration token patterns for the workflow-slot blocker |
|
|
104
|
-
| `working_style_prompt_constants.py` | The fixed multi-paragraph working-style prompt text for the SessionStart working_style_prompt hook |
|
|
105
|
-
|
|
106
|
-
## Conventions
|
|
107
|
-
|
|
108
|
-
- Most files in this package are pure constants modules — no side effects, no I/O.
|
|
109
|
-
- Hooks import from this package with `from hooks_constants.<module> import <CONSTANT>`.
|
|
110
|
-
- Tests for these modules live beside them as `test_<module>.py`. Run with `python -m pytest hooks_constants/test_<name>.py`.
|
|
111
|
-
- `dynamic_stderr_handler.py`, `pre_tool_use_stdin.py`, `multi_edit_reconstruction.py`, `hosted_hook_runner.py`, and `text_stripping.py` are utility modules (not pure constants) but live here because they hold logic shared across hook surfaces.
|
|
112
|
-
- `local_identity.py` is a loader: it reads the environment or `~/.claude/local-identity.json` (its path overridable via `CLAUDE_LOCAL_IDENTITY_PATH`) to resolve private NAS values (with committed placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`).
|
|
113
|
-
|
|
1
|
+
@AGENTS.md
|
|
@@ -67,21 +67,10 @@ ALL_BASH_HOSTED_HOOK_ENTRIES: tuple[BashHostedHookEntry, ...] = (
|
|
|
67
67
|
"blocking/pii_prevention_blocker.py", ALL_BASH_AND_POWERSHELL_TOOL_NAMES
|
|
68
68
|
),
|
|
69
69
|
BashHostedHookEntry("blocking/conventional_pr_title_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
70
|
-
BashHostedHookEntry("blocking/reviewer_spawn_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
71
70
|
BashHostedHookEntry("blocking/block_main_commit.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
72
71
|
BashHostedHookEntry("blocking/precommit_code_rules_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
73
72
|
BashHostedHookEntry("blocking/session_edit_stage_gate.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
74
|
-
BashHostedHookEntry("blocking/pr_description_enforcer.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
75
73
|
BashHostedHookEntry("blocking/test_preflight_check.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
76
|
-
BashHostedHookEntry("blocking/convergence_gate_blocker.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
77
74
|
BashHostedHookEntry("blocking/windows_rmtree_blocker.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
78
75
|
BashHostedHookEntry("blocking/gh_pr_author_enforcer.py", ALL_BASH_ONLY_TOOL_NAMES),
|
|
79
|
-
BashHostedHookEntry("blocking/code_review_push_gate.py", ALL_BASH_AND_POWERSHELL_TOOL_NAMES),
|
|
80
|
-
BashHostedHookEntry(
|
|
81
|
-
"blocking/code_review_pr_create_gate.py", ALL_BASH_AND_POWERSHELL_TOOL_NAMES
|
|
82
|
-
),
|
|
83
|
-
BashHostedHookEntry(
|
|
84
|
-
"blocking/code_review_stamp_directory_write_blocker.py",
|
|
85
|
-
ALL_BASH_AND_POWERSHELL_TOOL_NAMES,
|
|
86
|
-
),
|
|
87
76
|
)
|
|
@@ -11,16 +11,15 @@ into a retry prompt authorizes nothing.
|
|
|
11
11
|
claude-sonnet-4 -> ['claude', 'sonnet', '4'] ok: another tier
|
|
12
12
|
|
|
13
13
|
Every literal the gate body reads lives here. ``AGENT_TOOL_NAME`` and
|
|
14
|
-
``TASK_TOOL_NAME``
|
|
15
|
-
gates share one source for both tool names.
|
|
14
|
+
``TASK_TOOL_NAME`` name the spawn tools the gate evaluates.
|
|
16
15
|
"""
|
|
17
16
|
|
|
18
17
|
from __future__ import annotations
|
|
19
18
|
|
|
20
19
|
import re
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
AGENT_TOOL_NAME: str = "Agent"
|
|
22
|
+
TASK_TOOL_NAME: str = "Task"
|
|
24
23
|
|
|
25
24
|
ALL_SPAWN_TOOL_NAMES: frozenset[str] = frozenset({AGENT_TOOL_NAME, TASK_TOOL_NAME})
|
|
26
25
|
|
|
@@ -123,7 +123,7 @@ SUMMARY_COLUMN_HEADINGS: tuple[str, str, str, str] = (
|
|
|
123
123
|
"top_blocked_command_preview",
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
SUMMARY_ZERO_BLOCKED_EVENTS_MESSAGE: str = "Blocked events recorded in the last 24 hours: 0."
|
|
127
127
|
|
|
128
128
|
QUERY_NO_ROWS_RETURNED_MESSAGE: str = "No rows returned."
|
|
129
129
|
|
|
@@ -231,4 +231,3 @@ WINDOWS_CREATE_NEW_PROCESS_GROUP_FLAG: int = 0x00000200
|
|
|
231
231
|
|
|
232
232
|
LOCK_MAXIMUM_RETRY_COUNT: int = 30
|
|
233
233
|
LOCK_RETRY_SLEEP_SECONDS: float = 0.1
|
|
234
|
-
|
|
@@ -86,10 +86,6 @@ ALL_HOSTED_HOOK_ENTRIES: tuple[HostedHookEntry, ...] = (
|
|
|
86
86
|
script_relative_path="blocking/sensitive_file_protector.py",
|
|
87
87
|
applicable_tool_names=ALL_WRITE_AND_EDIT_TOOL_NAMES,
|
|
88
88
|
),
|
|
89
|
-
HostedHookEntry(
|
|
90
|
-
script_relative_path="blocking/code_review_stamp_directory_write_blocker.py",
|
|
91
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
92
|
-
),
|
|
93
89
|
HostedHookEntry(
|
|
94
90
|
script_relative_path="blocking/pii_prevention_blocker.py",
|
|
95
91
|
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
@@ -131,10 +127,6 @@ ALL_HOSTED_HOOK_ENTRIES: tuple[HostedHookEntry, ...] = (
|
|
|
131
127
|
script_relative_path="blocking/hook_prose_detector_consistency.py",
|
|
132
128
|
applicable_tool_names=ALL_WRITE_AND_EDIT_TOOL_NAMES,
|
|
133
129
|
),
|
|
134
|
-
HostedHookEntry(
|
|
135
|
-
script_relative_path="blocking/verified_commit_message_accuracy_blocker.py",
|
|
136
|
-
applicable_tool_names=ALL_WRITE_AND_EDIT_TOOL_NAMES,
|
|
137
|
-
),
|
|
138
130
|
HostedHookEntry(
|
|
139
131
|
script_relative_path="blocking/workflow_substitution_slot_blocker.py",
|
|
140
132
|
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
@@ -7,12 +7,7 @@ PROACTIVE_STATUS: str = "proactive"
|
|
|
7
7
|
CORRECTIVE_MESSAGE: str = (
|
|
8
8
|
"BLOCKED [open-locally]: SendUserFile attaches a file to the session, which "
|
|
9
9
|
"does not let the user see it while they are at the terminal. Open the file on "
|
|
10
|
-
"screen
|
|
11
|
-
" Start-Process pwsh -WindowStyle Hidden -ArgumentList "
|
|
12
|
-
"'-NoProfile','-File',\"$HOME\\.claude\\scripts\\Show-Asset.ps1\","
|
|
13
|
-
"'<path 1>','<path 2>'\n"
|
|
14
|
-
"Show-Asset.ps1 sizes each image window to the image and opens every other file "
|
|
15
|
-
"type in its default app. Pass every path the user named.\n"
|
|
10
|
+
"screen with its native Windows app. Open every path the user named.\n"
|
|
16
11
|
"The one allowed attach is a phone push: when the user has stepped away and you "
|
|
17
12
|
'want the file to reach their phone, call SendUserFile with status "proactive".'
|
|
18
13
|
)
|
|
@@ -11,8 +11,9 @@ TASK_LIST_MAINTENANCE_INSTRUCTION = "build or update the task list using the tas
|
|
|
11
11
|
|
|
12
12
|
TASK_LIST_LOOP_DIRECTIVE = (
|
|
13
13
|
"TASK LIST MAINTENANCE: Keep this session's task list current on a 10-minute "
|
|
14
|
-
"cadence.
|
|
15
|
-
"
|
|
14
|
+
"cadence. Reuse the active task-list maintenance loop when available. Start "
|
|
15
|
+
"Claude Code's built-in /loop skill with a 10-minute interval when this session "
|
|
16
|
+
"needs its first loop: "
|
|
16
17
|
f'/loop 10m "{TASK_LIST_MAINTENANCE_INSTRUCTION}". Run that instruction once '
|
|
17
|
-
"immediately, then let the loop refresh the list every 10 minutes."
|
|
18
|
+
"immediately when starting the loop, then let the loop refresh the list every 10 minutes."
|
|
18
19
|
)
|
|
@@ -32,26 +32,17 @@ _EXPECTED_BASH_ORDER = (
|
|
|
32
32
|
"blocking/volatile_path_in_post_blocker.py",
|
|
33
33
|
"blocking/pii_prevention_blocker.py",
|
|
34
34
|
"blocking/conventional_pr_title_gate.py",
|
|
35
|
-
"blocking/reviewer_spawn_gate.py",
|
|
36
35
|
"blocking/block_main_commit.py",
|
|
37
36
|
"blocking/precommit_code_rules_gate.py",
|
|
38
37
|
"blocking/session_edit_stage_gate.py",
|
|
39
|
-
"blocking/pr_description_enforcer.py",
|
|
40
38
|
"blocking/test_preflight_check.py",
|
|
41
|
-
"blocking/convergence_gate_blocker.py",
|
|
42
39
|
"blocking/windows_rmtree_blocker.py",
|
|
43
40
|
"blocking/gh_pr_author_enforcer.py",
|
|
44
|
-
"blocking/code_review_push_gate.py",
|
|
45
|
-
"blocking/code_review_pr_create_gate.py",
|
|
46
|
-
"blocking/code_review_stamp_directory_write_blocker.py",
|
|
47
41
|
)
|
|
48
42
|
|
|
49
43
|
_POWERSHELL_APPLICABLE = (
|
|
50
44
|
"blocking/unscoped_search_blocker.py",
|
|
51
45
|
"blocking/pii_prevention_blocker.py",
|
|
52
|
-
"blocking/code_review_push_gate.py",
|
|
53
|
-
"blocking/code_review_pr_create_gate.py",
|
|
54
|
-
"blocking/code_review_stamp_directory_write_blocker.py",
|
|
55
46
|
)
|
|
56
47
|
|
|
57
48
|
|
|
@@ -70,7 +61,7 @@ def test_every_hook_applies_to_the_bash_tool() -> None:
|
|
|
70
61
|
|
|
71
62
|
|
|
72
63
|
def test_powershell_applicable_hooks_include_the_shared_gates() -> None:
|
|
73
|
-
"""PowerShell runs the unscoped-search and PII gates
|
|
64
|
+
"""PowerShell runs the shared unscoped-search and PII gates."""
|
|
74
65
|
powershell_hooks = tuple(
|
|
75
66
|
each_entry.script_relative_path
|
|
76
67
|
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
|
|
@@ -86,22 +77,6 @@ def test_powershell_hooks_carry_the_shared_tool_set() -> None:
|
|
|
86
77
|
assert each_entry.applicable_tool_names == ALL_BASH_AND_POWERSHELL_TOOL_NAMES
|
|
87
78
|
|
|
88
79
|
|
|
89
|
-
def test_code_review_gate_family_registered_for_bash_and_powershell() -> None:
|
|
90
|
-
"""The three code-review shell gates run on both Bash and PowerShell."""
|
|
91
|
-
code_review_gate_paths = (
|
|
92
|
-
"blocking/code_review_push_gate.py",
|
|
93
|
-
"blocking/code_review_pr_create_gate.py",
|
|
94
|
-
"blocking/code_review_stamp_directory_write_blocker.py",
|
|
95
|
-
)
|
|
96
|
-
entry_by_path = {
|
|
97
|
-
each_entry.script_relative_path: each_entry
|
|
98
|
-
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
|
|
99
|
-
}
|
|
100
|
-
for each_gate_path in code_review_gate_paths:
|
|
101
|
-
assert each_gate_path in entry_by_path
|
|
102
|
-
assert entry_by_path[each_gate_path].applicable_tool_names == (
|
|
103
|
-
ALL_BASH_AND_POWERSHELL_TOOL_NAMES
|
|
104
|
-
)
|
|
105
80
|
|
|
106
81
|
|
|
107
82
|
def test_every_roster_path_points_at_an_existing_hook() -> None:
|
|
@@ -63,11 +63,6 @@ def test_duplicate_rmtree_helper_blocker_runs_via_runpy() -> None:
|
|
|
63
63
|
assert entry.native_module_name is None
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def test_code_review_stamp_write_blocker_registered_for_all_file_tools() -> None:
|
|
67
|
-
entry = _entry_for("blocking/code_review_stamp_directory_write_blocker.py")
|
|
68
|
-
assert entry is not None
|
|
69
|
-
assert {"Write", "Edit", "MultiEdit"} <= entry.applicable_tool_names
|
|
70
|
-
|
|
71
66
|
|
|
72
67
|
def test_windows_rmtree_blocker_still_registered() -> None:
|
|
73
68
|
entry = _entry_for("blocking/windows_rmtree_blocker.py")
|
|
@@ -7,24 +7,33 @@ __all__ = [
|
|
|
7
7
|
]
|
|
8
8
|
|
|
9
9
|
WORKING_STYLE_PROMPT = (
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
10
|
+
"Document each task in a location that remains easy to find later. Keep a "
|
|
11
|
+
"running scratch text ledger as you work. Write in plain English. Keep responses "
|
|
12
|
+
"focused, brief, and concise. Keep disclaimers and caveats short while giving "
|
|
13
|
+
"the main answer most of the response. Give a high-level explanation by default "
|
|
14
|
+
"and provide depth when the request calls for it. "
|
|
15
|
+
"Before your first tool call, state your next action in one sentence. While "
|
|
16
|
+
"working, give brief updates when you find important information or change "
|
|
17
|
+
"direction. Finish with the outcome in the first sentence, then provide "
|
|
18
|
+
"supporting detail for readers who want it. "
|
|
19
|
+
"Match written-document length to the task. Cover the substance and keep every "
|
|
20
|
+
"section, summary, and phrase useful. "
|
|
21
|
+
"Deliver the requested work at its intended scope. Make routine judgment calls "
|
|
22
|
+
"yourself. Ask for direction when different interpretations would produce "
|
|
23
|
+
"materially different work. When a request seems mistaken or a better approach "
|
|
24
|
+
"exists, state the concern briefly and continue with the requested task. Finish "
|
|
25
|
+
"the complete task and keep actions within the requested scope. "
|
|
26
|
+
"When a request has multiple reasonable interpretations, state your understanding "
|
|
27
|
+
"and the assumptions that shape the work. Ask one focused clarification question "
|
|
28
|
+
"when the ambiguity changes the outcome, scope, audience, format, or risk. Use a "
|
|
29
|
+
"clearly stated low-risk assumption when the intended result remains stable. "
|
|
30
|
+
"Pause for the user's choice before making a high-impact decision. "
|
|
31
|
+
"Use positive prose throughout every generated text surface, including "
|
|
32
|
+
"documentation, comments, user-facing messages, sub-agent prompts, labels, "
|
|
33
|
+
"plans, and instructions. Write each point as one direct affirmative statement "
|
|
34
|
+
"that presents only the intended action, fact, reason, or outcome. Use current, "
|
|
35
|
+
"immediately relevant context and omit historical clutter. Use plain language, "
|
|
36
|
+
"full terms, and simple descriptive names that communicate their meaning "
|
|
37
|
+
"immediately. Keep all text concise, clear, direct, and focused entirely on "
|
|
38
|
+
"useful information."
|
|
30
39
|
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# hooks/lifecycle
|
|
2
|
+
|
|
3
|
+
Hooks that run at session or config-change boundaries rather than on individual tool calls.
|
|
4
|
+
|
|
5
|
+
## Key files
|
|
6
|
+
|
|
7
|
+
| File | Event | What it does |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `config_change_guard.py` | PostToolUse (Write/Edit on `settings.json`) | Counts hooks in the edited `settings.json` and logs any change to `~/.claude/cache/config-change-audit.log`; alerts when the hook count drops below the last known value |
|
|
10
|
+
| `enter_worktree_origin_prefetch.py` | PreToolUse (EnterWorktree) | Fetches origin's default branch before a worktree creation call, keeping the `refs/remotes/origin/<default-branch>` ref that `fresh` mode reads current; never blocks on fetch failure |
|
|
11
|
+
| `session_end_cleanup.py` | SessionEnd | Purges stale cache entries from `~/.claude/cache/` (entries older than the configured threshold) and old backup files |
|
|
12
|
+
| `test_config_change_guard.py` | — | Tests for `config_change_guard.py` |
|
|
13
|
+
| `test_enter_worktree_origin_prefetch.py` | — | Tests for `enter_worktree_origin_prefetch.py` |
|
|
14
|
+
|
|
15
|
+
## Conventions
|
|
16
|
+
|
|
17
|
+
- Constants for these hooks (stale-age threshold, cache directory, known-hook-count file, EnterWorktree prefetch tuning) live in `hooks_constants/session_env_cleanup_constants.py` and `hooks_constants/enter_worktree_prefetch_constants.py`.
|
|
18
|
+
- Tests run with `python -m pytest lifecycle/test_<name>.py`.
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Hooks that run at session or config-change boundaries rather than on individual tool calls.
|
|
4
|
-
|
|
5
|
-
## Key files
|
|
6
|
-
|
|
7
|
-
| File | Event | What it does |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `config_change_guard.py` | PostToolUse (Write/Edit on `settings.json`) | Counts hooks in the edited `settings.json` and logs any change to `~/.claude/cache/config-change-audit.log`; alerts when the hook count drops below the last known value |
|
|
10
|
-
| `enter_worktree_origin_prefetch.py` | PreToolUse (EnterWorktree) | Fetches origin's default branch before a worktree creation call, keeping the `refs/remotes/origin/<default-branch>` ref that `fresh` mode reads current; never blocks on fetch failure |
|
|
11
|
-
| `pr_converge_bugteam_skill_tracker.py` | PreToolUse (Skill) | Tracks which bugteam skill runs have completed within a pr-converge loop, so the enforcer can verify parallel execution |
|
|
12
|
-
| `session_end_cleanup.py` | SessionEnd | Purges stale cache entries from `~/.claude/cache/` (entries older than the configured threshold) and old backup files |
|
|
13
|
-
| `test_config_change_guard.py` | — | Tests for `config_change_guard.py` |
|
|
14
|
-
| `test_enter_worktree_origin_prefetch.py` | — | Tests for `enter_worktree_origin_prefetch.py` |
|
|
15
|
-
| `test_pr_converge_bugteam_skill_tracker.py` | — | Tests for `pr_converge_bugteam_skill_tracker.py` |
|
|
16
|
-
|
|
17
|
-
## Conventions
|
|
18
|
-
|
|
19
|
-
- Constants for these hooks (stale-age threshold, cache directory, known-hook-count file, EnterWorktree prefetch tuning) live in `hooks_constants/session_env_cleanup_constants.py`, `hooks_constants/pr_converge_bugteam_enforcer_constants.py`, and `hooks_constants/enter_worktree_prefetch_constants.py`.
|
|
20
|
-
- Tests run with `python -m pytest lifecycle/test_<name>.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# hooks/observability
|
|
2
|
+
|
|
3
|
+
PostToolUse hooks that record agent behavior for later review. These hooks do not block tool calls; they log or annotate them.
|
|
4
|
+
|
|
5
|
+
## Key files
|
|
6
|
+
|
|
7
|
+
| File | Event | What it does |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `instructions_loaded_logger.py` | PostToolUse (file load events) | Appends a JSONL record to `~/.claude/logs/instructions_loaded.jsonl` each time Claude Code loads a context file (CLAUDE.md, rules, skills), capturing the file path, load reason, memory type, and session ID |
|
|
10
|
+
| `session_file_edit_tracker.py` | PostToolUse (Write/Edit/MultiEdit) | Records the resolved absolute path of each file edited this session into a per-session JSON file under the system temp directory, for the session edit stage gate to read at commit time |
|
|
11
|
+
| `prose_matcher_advisory.py` | Advisory emit from prose matchers | Privacy-safe JSONL candidates (`matcher_id`, surface, context fingerprint, label) plus keep/narrow/drop/advisory classification against the sample floor |
|
|
12
|
+
| `test_instructions_loaded_logger.py` | — | Tests for `instructions_loaded_logger.py` |
|
|
13
|
+
| `test_session_file_edit_tracker.py` | — | Tests for `session_file_edit_tracker.py` |
|
|
14
|
+
| `test_prose_matcher_advisory.py` | — | Tests for advisory emit and precision classification |
|
|
15
|
+
|
|
16
|
+
## Conventions
|
|
17
|
+
|
|
18
|
+
- The log file is append-only; the hook creates the parent directory if needed.
|
|
19
|
+
- Errors during logging are caught and written as error records rather than propagated — the hook never blocks the tool call.
|
|
20
|
+
- Tests run with `python -m pytest observability/test_instructions_loaded_logger.py`.
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
PostToolUse hooks that record agent behavior for later review. These hooks do not block tool calls; they log or annotate them.
|
|
4
|
-
|
|
5
|
-
## Key files
|
|
6
|
-
|
|
7
|
-
| File | Event | What it does |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `instructions_loaded_logger.py` | PostToolUse (file load events) | Appends a JSONL record to `~/.claude/logs/instructions_loaded.jsonl` each time Claude Code loads a context file (CLAUDE.md, rules, skills), capturing the file path, load reason, memory type, and session ID |
|
|
10
|
-
| `session_file_edit_tracker.py` | PostToolUse (Write/Edit/MultiEdit) | Records the resolved absolute path of each file edited this session into a per-session JSON file under the system temp directory, for the session edit stage gate to read at commit time |
|
|
11
|
-
| `prose_matcher_advisory.py` | Advisory emit from prose matchers | Privacy-safe JSONL candidates (`matcher_id`, surface, context fingerprint, label) plus keep/narrow/drop/advisory classification against the sample floor |
|
|
12
|
-
| `test_instructions_loaded_logger.py` | — | Tests for `instructions_loaded_logger.py` |
|
|
13
|
-
| `test_session_file_edit_tracker.py` | — | Tests for `session_file_edit_tracker.py` |
|
|
14
|
-
| `test_prose_matcher_advisory.py` | — | Tests for advisory emit and precision classification |
|
|
15
|
-
|
|
16
|
-
## Conventions
|
|
17
|
-
|
|
18
|
-
- The log file is append-only; the hook creates the parent directory if needed.
|
|
19
|
-
- Errors during logging are caught and written as error records rather than propagated — the hook never blocks the tool call.
|
|
20
|
-
- Tests run with `python -m pytest observability/test_instructions_loaded_logger.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# hooks/session
|
|
2
|
+
|
|
3
|
+
SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown.
|
|
4
|
+
|
|
5
|
+
## Key files
|
|
6
|
+
|
|
7
|
+
| File | Event | What it does |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `session_env_cleanup.py` | SessionStart | Removes the current session's pre-existing `~/.claude/session-env/<session_id>/` directory and prunes sibling entries older than the stale-age threshold. Prevents `EEXIST` errors from non-recursive `mkdir` calls in the Bash tool on Windows. |
|
|
10
|
+
| `gh_pr_author_session_cleanup.py` | SessionEnd | Clears any PR-author swap state left over from the current session |
|
|
11
|
+
| `session_edit_tracker_cleanup.py` | SessionStart, SessionEnd | Deletes the tracker file for the running Claude Code conversation from the system temp directory — at start for a clean slate and at end for a clean exit. A tracker is read only by the conversation that wrote it, so a live idle tracker is kept while a peer cleans up |
|
|
12
|
+
| `plugin_data_dir_cleanup.py` | SessionStart | Removes empty plugin data directories at startup to prevent `EEXIST` when Claude Code recreates them |
|
|
13
|
+
| `untracked_repo_detector.py` | SessionStart | Detects when the session cwd is inside a git repository that is not registered in `~/.claude/project-paths.json` and logs a warning |
|
|
14
|
+
| `task_list_loop_starter.py` | SessionStart | Emits an `additionalContext` directive telling Claude to keep the task list current on a 10-minute cadence, starting the `/loop` skill when one is not already running. Writes nothing and runs no tools itself. |
|
|
15
|
+
| `orchestrator_auto_starter.py` | SessionStart | Opt-in (`CLAUDE_ORCHESTRATOR_AUTO_STARTER_ENABLED`) consumer of the shared SessionStart injector; emits orchestrator skill context when enabled. Manual `/orchestrator` unchanged. |
|
|
16
|
+
| `issue_tracker_session_starter.py` | SessionStart | Opt-in (`CLAUDE_ISSUE_TRACKER_SESSION_STARTER_ENABLED`) and repository-gated (git root in `~/.claude/project-paths.json`) issue-tracker skill context. |
|
|
17
|
+
| `_path_setup.py` | — | Inserts the hooks directory on `sys.path` so SessionStart scripts import `hooks_constants` with top-level imports. |
|
|
18
|
+
| `test_orchestrator_auto_starter.py` | — | Tests for `orchestrator_auto_starter.py` |
|
|
19
|
+
| `test_issue_tracker_session_starter.py` | — | Tests for `issue_tracker_session_starter.py` |
|
|
20
|
+
| `working_style_prompt.py` | SessionStart | Emits an `additionalContext` block with the fixed working-style prompt (running ledger, plain English, outcome-first finish, scope discipline). Writes nothing and runs no tools itself. |
|
|
21
|
+
| `test_gh_pr_author_session_cleanup.py` | — | Tests for `gh_pr_author_session_cleanup.py` |
|
|
22
|
+
| `test_session_edit_tracker_cleanup.py` | — | Tests for `session_edit_tracker_cleanup.py` |
|
|
23
|
+
| `test_session_env_cleanup.py` | — | Tests for `session_env_cleanup.py` |
|
|
24
|
+
| `test_untracked_repo_detector.py` | — | Tests for `untracked_repo_detector.py` |
|
|
25
|
+
| `test_task_list_loop_starter.py` | — | Tests for `task_list_loop_starter.py` |
|
|
26
|
+
| `test__path_setup.py` | — | Tests for `_path_setup.py` |
|
|
27
|
+
| `test_working_style_prompt.py` | — | Tests for `working_style_prompt.py` |
|
|
28
|
+
|
|
29
|
+
## Conventions
|
|
30
|
+
|
|
31
|
+
- `session_env_cleanup.py` is Windows-specific in effect but safe to run on all platforms; it exits 0 when the target directory does not exist.
|
|
32
|
+
- Constants (stale-age threshold, directory names) live in `hooks_constants/session_env_cleanup_constants.py`.
|
|
33
|
+
- Tests run with `python -m pytest session/test_<name>.py`.
|
package/hooks/session/CLAUDE.md
CHANGED
|
@@ -1,33 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown.
|
|
4
|
-
|
|
5
|
-
## Key files
|
|
6
|
-
|
|
7
|
-
| File | Event | What it does |
|
|
8
|
-
|---|---|---|
|
|
9
|
-
| `session_env_cleanup.py` | SessionStart | Removes the current session's pre-existing `~/.claude/session-env/<session_id>/` directory and prunes sibling entries older than the stale-age threshold. Prevents `EEXIST` errors from non-recursive `mkdir` calls in the Bash tool on Windows. |
|
|
10
|
-
| `gh_pr_author_session_cleanup.py` | SessionEnd | Clears any PR-author swap state left over from the current session |
|
|
11
|
-
| `session_edit_tracker_cleanup.py` | SessionStart, SessionEnd | Deletes the tracker file for the running Claude Code conversation from the system temp directory — at start for a clean slate and at end for a clean exit. A tracker is read only by the conversation that wrote it, so a live idle tracker is kept while a peer cleans up |
|
|
12
|
-
| `plugin_data_dir_cleanup.py` | SessionStart | Removes empty plugin data directories at startup to prevent `EEXIST` when Claude Code recreates them |
|
|
13
|
-
| `untracked_repo_detector.py` | SessionStart | Detects when the session cwd is inside a git repository that is not registered in `~/.claude/project-paths.json` and logs a warning |
|
|
14
|
-
| `task_list_loop_starter.py` | SessionStart | Emits an `additionalContext` directive telling Claude to keep the task list current on a 10-minute cadence, starting the `/loop` skill when one is not already running. Writes nothing and runs no tools itself. |
|
|
15
|
-
| `orchestrator_auto_starter.py` | SessionStart | Opt-in (`CLAUDE_ORCHESTRATOR_AUTO_STARTER_ENABLED`) consumer of the shared SessionStart injector; emits orchestrator skill context when enabled. Manual `/orchestrator` unchanged. |
|
|
16
|
-
| `issue_tracker_session_starter.py` | SessionStart | Opt-in (`CLAUDE_ISSUE_TRACKER_SESSION_STARTER_ENABLED`) and repository-gated (git root in `~/.claude/project-paths.json`) issue-tracker skill context. |
|
|
17
|
-
| `_path_setup.py` | — | Inserts the hooks directory on `sys.path` so SessionStart scripts import `hooks_constants` with top-level imports. |
|
|
18
|
-
| `test_orchestrator_auto_starter.py` | — | Tests for `orchestrator_auto_starter.py` |
|
|
19
|
-
| `test_issue_tracker_session_starter.py` | — | Tests for `issue_tracker_session_starter.py` |
|
|
20
|
-
| `working_style_prompt.py` | SessionStart | Emits an `additionalContext` block with the fixed working-style prompt (running ledger, plain English, outcome-first finish, scope discipline). Writes nothing and runs no tools itself. |
|
|
21
|
-
| `test_gh_pr_author_session_cleanup.py` | — | Tests for `gh_pr_author_session_cleanup.py` |
|
|
22
|
-
| `test_session_edit_tracker_cleanup.py` | — | Tests for `session_edit_tracker_cleanup.py` |
|
|
23
|
-
| `test_session_env_cleanup.py` | — | Tests for `session_env_cleanup.py` |
|
|
24
|
-
| `test_untracked_repo_detector.py` | — | Tests for `untracked_repo_detector.py` |
|
|
25
|
-
| `test_task_list_loop_starter.py` | — | Tests for `task_list_loop_starter.py` |
|
|
26
|
-
| `test__path_setup.py` | — | Tests for `_path_setup.py` |
|
|
27
|
-
| `test_working_style_prompt.py` | — | Tests for `working_style_prompt.py` |
|
|
28
|
-
|
|
29
|
-
## Conventions
|
|
30
|
-
|
|
31
|
-
- `session_env_cleanup.py` is Windows-specific in effect but safe to run on all platforms; it exits 0 when the target directory does not exist.
|
|
32
|
-
- Constants (stale-age threshold, directory names) live in `hooks_constants/session_env_cleanup_constants.py`.
|
|
33
|
-
- Tests run with `python -m pytest session/test_<name>.py`.
|
|
1
|
+
@AGENTS.md
|
|
@@ -34,6 +34,7 @@ if hooks_parent_directory not in sys.path:
|
|
|
34
34
|
sys.path.insert(0, hooks_parent_directory)
|
|
35
35
|
|
|
36
36
|
from _gh_pr_author_swap_utils import ( # noqa: E402
|
|
37
|
+
_build_restore_failure_message,
|
|
37
38
|
_delete_state_file,
|
|
38
39
|
_lstat_indicates_attacker_planted,
|
|
39
40
|
_read_original_account,
|
|
@@ -142,8 +143,12 @@ def _restore_stale_state_file(state_file: Path) -> None:
|
|
|
142
143
|
_delete_state_file(state_file)
|
|
143
144
|
else:
|
|
144
145
|
_write_line(
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
_build_restore_failure_message(
|
|
147
|
+
"gh-pr-author-cleanup",
|
|
148
|
+
original_account,
|
|
149
|
+
state_file,
|
|
150
|
+
"stale state file",
|
|
151
|
+
),
|
|
147
152
|
sys.stderr,
|
|
148
153
|
)
|
|
149
154
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"""SessionStart hook — start a task-list maintenance loop for the session.
|
|
3
3
|
|
|
4
4
|
At session start this hook emits an ``additionalContext`` directive asking Claude
|
|
5
|
-
to keep the session's task list current on a 10-minute cadence
|
|
6
|
-
``/loop`` skill when
|
|
7
|
-
|
|
5
|
+
to keep the session's task list current on a 10-minute cadence. Claude reuses the
|
|
6
|
+
active ``/loop`` skill when available and starts the skill for the session's first
|
|
7
|
+
task-list maintenance loop.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
@@ -343,7 +343,8 @@ def test_restore_stale_state_file_logs_when_switch_fails(
|
|
|
343
343
|
|
|
344
344
|
captured_streams = capsys.readouterr()
|
|
345
345
|
assert state_file.exists()
|
|
346
|
-
assert "[gh-pr-author-cleanup]
|
|
346
|
+
assert "[gh-pr-author-cleanup] Restore the gh account" in captured_streams.err
|
|
347
|
+
assert "gh account switch requires attention" in captured_streams.err
|
|
347
348
|
assert "'jl-cmd'" in captured_streams.err
|
|
348
349
|
assert str(state_file) in captured_streams.err
|
|
349
350
|
|