claude-dev-env 4.3.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents/pr-description-writer.md +2 -2
- package/.agents/agents/test_agent_frontmatter.py +2 -2
- package/.agents/agents/test_pr_description_writer_style.py +1 -3
- package/.agents/skills/e-code-review/SKILL.md +12 -12
- package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
- package/.agents/skills/e-code-review/reference/fix.md +15 -17
- package/.agents/skills/e-code-review/reference/loop.md +35 -39
- package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
- package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
- package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
- package/.agents/skills/issue-tracker/SKILL.md +5 -4
- package/.agents/skills/pull-request/SKILL.md +11 -13
- package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
- package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
- package/.agents/skills/pull-request/scripts/pull_request.py +35 -44
- package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
- package/.agents/skills/pull-request/scripts/test_pull_request.py +35 -3
- package/.agents/skills/session-continuity/README.md +189 -0
- package/.agents/skills/session-continuity/SKILL.md +114 -0
- package/.agents/skills/session-continuity/continuity.mjs +375 -0
- package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
- package/.agents/skills/skill-builder/SKILL.md +3 -196
- package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
- package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
- package/bin/cde.mjs +36 -8
- package/bin/cde.test.mjs +48 -0
- package/bin/ever-shipped-skills.mjs +2 -20
- package/bin/ever-shipped-skills.test.mjs +8 -0
- package/bin/expand_home_directory_tokens.mjs +4 -5
- package/bin/expand_home_directory_tokens.test.mjs +128 -0
- package/bin/git_hooks_installer.mjs +22 -3
- package/bin/git_hooks_installer.test.mjs +159 -5
- package/bin/install-session-continuity.mjs +78 -0
- package/bin/install-session-continuity.test.mjs +42 -0
- package/bin/install.agents-home.test.mjs +15 -13
- package/bin/install.codex-rules.test.mjs +5 -2
- package/bin/install.cursor-rules.test.mjs +5 -2
- package/bin/install.mjs +506 -63
- package/bin/install.policy-lint.test.mjs +130 -0
- package/bin/install.profiles.test.mjs +10 -0
- package/bin/install.prune.test.mjs +286 -37
- package/bin/install.pstack-plugin.test.mjs +114 -0
- package/bin/install.test.mjs +537 -120
- package/bin/install.transaction.test.mjs +3 -3
- package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
- package/docs/CODE_RULES.md +1 -1
- package/hooks/advisory/pr_done_reminder.py +342 -0
- package/hooks/advisory/test_pr_done_reminder.py +249 -0
- package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
- package/hooks/blocking/code_rules_banned_identifiers.py +3 -0
- package/hooks/blocking/code_rules_paired_test.py +22 -15
- package/hooks/blocking/precommit_code_rules_gate.py +5 -8
- package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
- package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
- package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
- package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
- package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
- package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +43 -342
- package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
- package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
- package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
- package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
- package/hooks/git-hooks/post_commit.py +33 -0
- package/hooks/git-hooks/pre_commit.py +18 -49
- package/hooks/git-hooks/pre_push.py +45 -541
- package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
- package/hooks/git-hooks/test_native_hook_support.py +129 -0
- package/hooks/git-hooks/test_native_policy_commit.py +120 -0
- package/hooks/git-hooks/test_post_commit.py +43 -0
- package/hooks/git-hooks/test_pre_commit.py +38 -148
- package/hooks/git-hooks/test_pre_push.py +48 -1631
- package/hooks/git-hooks/test_verification_notice.py +60 -0
- package/hooks/git-hooks/test_verification_start.py +173 -0
- package/hooks/git-hooks/verification_notice.py +192 -0
- package/hooks/git-hooks/verification_notice_context.py +253 -0
- package/hooks/git-hooks/verification_notice_state.py +237 -0
- package/hooks/git-hooks/verification_start.py +100 -0
- package/hooks/hooks.json +1 -120
- package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
- package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
- package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
- package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
- package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
- package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
- package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
- package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
- package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
- package/hooks/validators/run_all_validators.py +5 -1
- package/hooks/validators/security_checks.py +57 -2
- package/hooks/validators/test_hook_timing_harness.py +2 -5
- package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
- package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
- package/hooks/validators/test_security_checks.py +57 -0
- package/package.json +2 -2
- package/rules/confirm-implementation-forks.md +2 -0
- package/rules/durable-post-artifacts.md +2 -1
- package/rules/git-workflow.md +18 -6
- package/rules/pstack-host-mapping.md +48 -0
- package/rules/vault-context.md +3 -5
- package/rules/verify-runtime-state.md +7 -0
- package/scripts/audit-hooks-cli.mjs +5 -0
- package/scripts/audit-hooks.mjs +72 -16
- package/scripts/automatic_advisory/__init__.py +1 -0
- package/scripts/automatic_advisory/checkout.py +51 -0
- package/scripts/automatic_advisory/cli.py +334 -0
- package/scripts/automatic_advisory/config/__init__.py +1 -0
- package/scripts/automatic_advisory/config/constants.py +93 -0
- package/scripts/automatic_advisory/config/timing.py +4 -0
- package/scripts/automatic_advisory/configuration.py +197 -0
- package/scripts/automatic_advisory/execution.py +350 -0
- package/scripts/automatic_advisory/git.py +69 -0
- package/scripts/automatic_advisory/model.py +107 -0
- package/scripts/automatic_advisory/process_host.py +32 -0
- package/scripts/automatic_advisory/publisher.py +84 -0
- package/scripts/automatic_advisory/runner.py +399 -0
- package/scripts/automatic_advisory/state.py +116 -0
- package/scripts/automatic_advisory/window_flags.py +41 -0
- package/scripts/automatic_advisory/windows_job.py +122 -0
- package/scripts/check.ps1 +0 -1
- package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
- package/scripts/ci/installer-lifecycle.test.mjs +26 -0
- package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
- package/scripts/codex_compat_materializer.py +99 -13
- package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
- package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
- package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
- package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
- package/scripts/local_report_cli.py +184 -0
- package/scripts/local_report_core.py +247 -0
- package/scripts/local_report_publisher.py +12 -0
- package/scripts/local_report_validation.py +357 -0
- package/scripts/local_verification/__init__.py +23 -0
- package/scripts/local_verification/check_runner.py +364 -0
- package/scripts/local_verification/check_support.py +99 -0
- package/scripts/local_verification/cli.py +158 -0
- package/scripts/local_verification/command_runner.py +84 -0
- package/scripts/local_verification/config/__init__.py +1 -0
- package/scripts/local_verification/config/constants.py +89 -0
- package/scripts/local_verification/config/timing.py +1 -0
- package/scripts/local_verification/git_state.py +146 -0
- package/scripts/local_verification/manifest.py +224 -0
- package/scripts/local_verification/model.py +174 -0
- package/scripts/local_verification/runner.py +234 -0
- package/scripts/policy_lint/adapter_detectors.py +13 -6
- package/scripts/policy_lint/adapter_pairing.py +58 -3
- package/scripts/policy_lint/adapters.py +7 -4
- package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
- package/scripts/policy_lint/config/constants.py +5 -0
- package/scripts/policy_lint/engine.py +48 -4
- package/scripts/policy_lint/model.py +1 -0
- package/scripts/policy_lint/registry.py +1 -1
- package/scripts/policy_lint/selection.py +2 -1
- package/scripts/policy_lint/selection_git.py +2 -0
- package/scripts/pr_verification/__init__.py +1 -0
- package/scripts/pr_verification/branch_refs.py +114 -0
- package/scripts/pr_verification/config/__init__.py +1 -0
- package/scripts/pr_verification/config/constants.py +84 -0
- package/scripts/pr_verification/config/timing.py +5 -0
- package/scripts/pr_verification/github.py +137 -0
- package/scripts/pr_verification/github_api.py +376 -0
- package/scripts/pr_verification/github_labels.py +88 -0
- package/scripts/pr_verification/github_parsing.py +182 -0
- package/scripts/pr_verification/github_transport.py +91 -0
- package/scripts/pr_verification/lock.py +122 -0
- package/scripts/pr_verification/model.py +43 -0
- package/scripts/pr_verification/requirements.txt +1 -0
- package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
- package/scripts/shared_tree_paths.py +32 -3
- package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
- package/scripts/test_shared_tree_paths.py +33 -0
- package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
- package/scripts/tests/test-audit-hooks.mjs +94 -2
- package/scripts/tests/test_automatic_advisory.py +376 -0
- package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
- package/scripts/tests/test_automatic_advisory_polling.py +216 -0
- package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
- package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
- package/scripts/tests/test_automatic_advisory_settings.py +48 -0
- package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
- package/scripts/tests/test_closed_pr_label.py +157 -0
- package/scripts/tests/test_codex_compat_materializer.py +189 -6
- package/scripts/tests/test_github_labels.py +101 -0
- package/scripts/tests/test_github_transport.py +125 -0
- package/scripts/tests/test_local_report_publisher.py +396 -0
- package/scripts/tests/test_local_report_publisher_cli.py +85 -0
- package/scripts/tests/test_local_verification.py +348 -0
- package/scripts/tests/test_local_verification_cli.py +98 -0
- package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
- package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
- package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
- package/scripts/tests/test_policy_lint_rules_pairing.py +163 -0
- package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
- package/scripts/tests/test_policy_lint_selection.py +25 -2
- package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
- package/scripts/tests/test_pr_verification_github.py +392 -0
- package/scripts/tests/test_pr_verification_lock.py +168 -0
- package/scripts/tests/test_rules.py +3 -7
- package/scripts/tests/test_verification_notice.py +347 -0
- package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
- package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
- package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
- package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
- package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
- package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
- package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
- package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
- package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
- package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
- package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
- package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
- package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
- package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
- package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
- package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
- package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
- package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
- package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
- package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
- package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
- package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
- package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
- package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
- package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
- package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
- package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
- package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
- package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
- package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
- package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
- package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
- package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
- package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
- package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
- package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
- package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
- package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
- package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
- package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
- package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/SKILL.md +0 -431
- package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
- package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
- package/.agents/skills/autoconverge/reference/convergence.md +0 -219
- package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
- package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
- package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
- package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
- package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
- package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
- package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
- package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
- package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
- package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
- package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
- package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
- package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
- package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
- package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
- package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
- package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
- package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
- package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
- package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
- package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
- package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
- package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
- package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
- package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
- package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
- package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
- package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
- package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
- package/.agents/skills/hitl/SKILL.md +0 -45
- package/.agents/skills/pr-cleanup/SKILL.md +0 -140
- package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
- package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
- package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
- package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
- package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
- package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
- package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
- package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
- package/.agents/skills/pr-refinement/SKILL.md +0 -31
- package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
- package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
- package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
- package/.agents/skills/pr-small-cl/SKILL.md +0 -52
- package/.agents/skills/pr-title-description/SKILL.md +0 -96
- package/.agents/skills/prototype/SKILL.md +0 -85
- package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
- package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
- package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
- package/.agents/skills/prototype/scripts/conftest.py +0 -15
- package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
- package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
- package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
- package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
- package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
- package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
- package/.agents/skills/prototype/workflows/promotion.md +0 -25
- package/.agents/skills/prototype/workflows/sandbox.md +0 -35
- package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
- package/.agents/skills/rebase/AGENTS.md +0 -1
- package/.agents/skills/rebase/SKILL.md +0 -178
- package/.agents/skills/review-router/SKILL.md +0 -51
- package/.agents/skills/review-router/reference/route-policy.json +0 -7
- package/.agents/skills/review-router/reference/task-seeds.md +0 -1
- package/.agents/skills/review-router/scripts/conftest.py +0 -4
- package/.agents/skills/review-router/scripts/review_router.py +0 -50
- package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
- package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
- package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
- package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
- package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
- package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
- package/.agents/skills/review-tier/SKILL.md +0 -56
- package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
- package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
- package/.agents/skills/review-tier/scripts/conftest.py +0 -4
- package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
- package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
- package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
- package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
- package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
- package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
- package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-log/AGENTS.md +0 -1
- package/.agents/skills/session-log/SKILL.md +0 -170
- package/.agents/skills/session-log/templates/frontmatter.md +0 -40
- package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
- package/.agents/skills/session-tidy/AGENTS.md +0 -1
- package/.agents/skills/session-tidy/SKILL.md +0 -191
- package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
- package/.agents/skills/skill-builder/references/description-field.md +0 -111
- package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
- package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
- package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
- package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
- package/.agents/skills/skill-builder/references/skill-types.md +0 -232
- package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
- package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
- package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
- package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
- package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
- package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
- package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
- package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
- package/.agents/skills/update/.claude/CLAUDE.md +0 -1
- package/.agents/skills/update/AGENTS.md +0 -1
- package/.agents/skills/update/SKILL.md +0 -190
- package/_shared/pr-loop/AGENTS.md +0 -1
- package/_shared/pr-loop/audit-contract.md +0 -183
- package/_shared/pr-loop/audit-reply-template.md +0 -151
- package/_shared/pr-loop/code-rules-gate.md +0 -65
- package/_shared/pr-loop/fix-protocol.md +0 -60
- package/_shared/pr-loop/gh-payloads.md +0 -75
- package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
- package/_shared/pr-loop/precatch-rubric.md +0 -66
- package/_shared/pr-loop/preflight-proposal.md +0 -56
- package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
- package/_shared/pr-loop/state-schema.md +0 -45
- package/_shared/pr-loop/worker-spawn.md +0 -189
- package/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
- package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
- package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
- package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
- package/hooks/blocking/destructive_command_blocker.py +0 -2073
- package/hooks/blocking/fable_spawn_gate.py +0 -187
- package/hooks/blocking/luna_fast_mode_gate.py +0 -160
- package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
- package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
- package/hooks/blocking/pii_prevention_blocker.py +0 -365
- package/hooks/blocking/piped_pytest_blocker.py +0 -1223
- package/hooks/blocking/question_to_user_enforcer.py +0 -130
- package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
- package/hooks/blocking/sensitive_file_protector.py +0 -167
- package/hooks/blocking/session_edit_stage_gate.py +0 -684
- package/hooks/blocking/session_handoff_blocker.py +0 -182
- package/hooks/blocking/shell_substitution_blocker.py +0 -350
- package/hooks/blocking/test_ask_user_question_shape.py +0 -69
- package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
- package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
- package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
- package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
- package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
- package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
- package/hooks/blocking/test_fable_spawn_gate.py +0 -381
- package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
- package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
- package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
- package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
- package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
- package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
- package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
- package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
- package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
- package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
- package/hooks/blocking/test_sensitive_file_protector.py +0 -365
- package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
- package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
- package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
- package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
- package/hooks/blocking/test_session_handoff_blocker.py +0 -318
- package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
- package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
- package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
- package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
- package/hooks/blocking/unscoped_search_blocker.py +0 -391
- package/hooks/blocking/write_existing_file_blocker.py +0 -124
- package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
- package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
- package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
- package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
- package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
- package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
- package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
- package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
- package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
- /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
- /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Constants for the PreToolUse dispatcher that hosts Write/Edit/MultiEdit hooks.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The roster keeps action-boundary checks, repository checks, and checks without
|
|
4
|
+
a proven local replacement. File-policy rules with a staged replacement run
|
|
5
|
+
through cde lint in native pre-commit. Their detectors stay importable for that
|
|
6
|
+
linter. Bash cleanup protection uses its own roster.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
from __future__ import annotations
|
|
@@ -25,7 +26,6 @@ __all__ = [
|
|
|
25
26
|
"ALL_WRITE_AND_EDIT_TOOL_NAMES",
|
|
26
27
|
"ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES",
|
|
27
28
|
"ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES",
|
|
28
|
-
"ALL_IMMEDIATE_HARM_SCRIPT_PATHS",
|
|
29
29
|
"STATE_DESCRIPTION_BLOCKER_MODULE_NAME",
|
|
30
30
|
"SYSTEM_MESSAGE_JOIN_SEPARATOR",
|
|
31
31
|
"HostedHookEntry",
|
|
@@ -55,15 +55,6 @@ ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES: frozenset[str] = frozenset(
|
|
|
55
55
|
ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
|
|
56
56
|
)
|
|
57
57
|
|
|
58
|
-
# apply_patch reaches this narrower roster: the gates whose miss causes immediate
|
|
59
|
-
# harm, plus the TDD gate and the edit tracker. It stays off the full lint surface.
|
|
60
|
-
ALL_IMMEDIATE_HARM_SCRIPT_PATHS: tuple[str, ...] = (
|
|
61
|
-
"blocking/pii_prevention_blocker.py",
|
|
62
|
-
"blocking/sensitive_file_protector.py",
|
|
63
|
-
"blocking/write_existing_file_blocker.py",
|
|
64
|
-
"blocking/code_rules_enforcer.py",
|
|
65
|
-
"blocking/tdd_enforcer.py",
|
|
66
|
-
)
|
|
67
58
|
|
|
68
59
|
|
|
69
60
|
STATE_DESCRIPTION_BLOCKER_MODULE_NAME = "state_description_blocker"
|
|
@@ -71,19 +62,18 @@ STATE_DESCRIPTION_BLOCKER_MODULE_NAME = "state_description_blocker"
|
|
|
71
62
|
|
|
72
63
|
@dataclass(frozen=True)
|
|
73
64
|
class HostedHookEntry:
|
|
74
|
-
"""
|
|
65
|
+
"""One hosted hook, the tools it applies to, and whether a crash blocks.
|
|
75
66
|
|
|
76
67
|
Attributes:
|
|
77
68
|
script_relative_path: Hook path relative to the hooks/ directory.
|
|
78
69
|
applicable_tool_names: Tool names this hook applies to. The dispatcher
|
|
79
70
|
skips the hook when the payload's tool is not in this set.
|
|
80
|
-
is_blocking: True when a crash
|
|
71
|
+
is_blocking: True when a crash is a blocking signal. False when the
|
|
81
72
|
hook is advisory and a crash stays silent.
|
|
82
|
-
native_module_name:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
string or None.
|
|
73
|
+
native_module_name: Importable module whose evaluate function the
|
|
74
|
+
dispatcher calls in-process, or None when the hook runs via runpy
|
|
75
|
+
under __main__. evaluate takes the payload dict and returns a
|
|
76
|
+
deny-reason string or None.
|
|
87
77
|
"""
|
|
88
78
|
|
|
89
79
|
script_relative_path: str
|
|
@@ -93,79 +83,6 @@ class HostedHookEntry:
|
|
|
93
83
|
|
|
94
84
|
|
|
95
85
|
ALL_HOSTED_HOOK_ENTRIES: tuple[HostedHookEntry, ...] = (
|
|
96
|
-
HostedHookEntry(
|
|
97
|
-
script_relative_path="blocking/write_existing_file_blocker.py",
|
|
98
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
99
|
-
),
|
|
100
|
-
HostedHookEntry(
|
|
101
|
-
script_relative_path="blocking/sensitive_file_protector.py",
|
|
102
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
103
|
-
),
|
|
104
|
-
HostedHookEntry(
|
|
105
|
-
script_relative_path="blocking/pii_prevention_blocker.py",
|
|
106
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
107
|
-
),
|
|
108
|
-
HostedHookEntry(
|
|
109
|
-
script_relative_path="validation/hook_format_validator.py",
|
|
110
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
111
|
-
),
|
|
112
|
-
HostedHookEntry(
|
|
113
|
-
script_relative_path="blocking/code_rules_enforcer.py",
|
|
114
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
115
|
-
),
|
|
116
|
-
HostedHookEntry(
|
|
117
|
-
script_relative_path="blocking/tdd_enforcer.py",
|
|
118
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
119
|
-
),
|
|
120
|
-
HostedHookEntry(
|
|
121
|
-
script_relative_path="blocking/windows_rmtree_blocker.py",
|
|
122
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
123
|
-
),
|
|
124
|
-
HostedHookEntry(
|
|
125
|
-
script_relative_path="blocking/duplicate_rmtree_helper_blocker.py",
|
|
126
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
127
|
-
),
|
|
128
|
-
HostedHookEntry(
|
|
129
|
-
script_relative_path="blocking/state_description_blocker.py",
|
|
130
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
131
|
-
native_module_name=STATE_DESCRIPTION_BLOCKER_MODULE_NAME,
|
|
132
|
-
),
|
|
133
|
-
HostedHookEntry(
|
|
134
|
-
script_relative_path="blocking/subprocess_budget_completeness.py",
|
|
135
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
136
|
-
),
|
|
137
|
-
HostedHookEntry(
|
|
138
|
-
script_relative_path="blocking/hook_prose_detector_consistency.py",
|
|
139
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
140
|
-
),
|
|
141
|
-
HostedHookEntry(
|
|
142
|
-
script_relative_path="blocking/workflow_substitution_slot_blocker.py",
|
|
143
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
144
|
-
),
|
|
145
|
-
HostedHookEntry(
|
|
146
|
-
script_relative_path="blocking/claude_md_orphan_file_blocker.py",
|
|
147
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
148
|
-
),
|
|
149
|
-
HostedHookEntry(
|
|
150
|
-
script_relative_path="blocking/package_inventory_stale_blocker.py",
|
|
151
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
152
|
-
),
|
|
153
|
-
HostedHookEntry(
|
|
154
|
-
script_relative_path="blocking/env_var_table_code_drift_blocker.py",
|
|
155
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
156
|
-
),
|
|
157
|
-
HostedHookEntry(
|
|
158
|
-
script_relative_path="blocking/pytest_testpaths_orphan_blocker.py",
|
|
159
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
160
|
-
),
|
|
161
|
-
HostedHookEntry(
|
|
162
|
-
script_relative_path="blocking/open_questions_in_plans_blocker.py",
|
|
163
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
164
|
-
),
|
|
165
|
-
HostedHookEntry(
|
|
166
|
-
script_relative_path="blocking/docstring_rule_gate_count_blocker.py",
|
|
167
|
-
applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
168
|
-
),
|
|
169
86
|
HostedHookEntry(
|
|
170
87
|
script_relative_path="advisory/refactor_guard.py",
|
|
171
88
|
applicable_tool_names=frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME}),
|
|
@@ -17,7 +17,4 @@ BLOCK_DECISION = "block"
|
|
|
17
17
|
DECISION_KEY = "decision"
|
|
18
18
|
REASON_KEY = "reason"
|
|
19
19
|
|
|
20
|
-
ALL_STOP_HOSTED_HOOK_PATHS: tuple[str, ...] = (
|
|
21
|
-
"blocking/question_to_user_enforcer.py",
|
|
22
|
-
"blocking/session_handoff_blocker.py",
|
|
23
|
-
)
|
|
20
|
+
ALL_STOP_HOSTED_HOOK_PATHS: tuple[str, ...] = ()
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
"""Behavioral tests for the Bash PostToolUse dispatcher's hosted-hook roster."""
|
|
2
2
|
|
|
3
|
+
from hooks_constants import bash_post_call_dispatcher_constants as constants
|
|
3
4
|
from hooks_constants.bash_post_call_dispatcher_constants import (
|
|
4
5
|
ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES,
|
|
5
6
|
)
|
|
6
7
|
from hooks_constants.bash_pre_tool_use_dispatcher_constants import BASH_TOOL_NAME
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
def
|
|
10
|
+
def test_roster_runs_the_recorder_then_the_pr_done_reminder() -> None:
|
|
10
11
|
all_script_paths = [
|
|
11
12
|
each_entry.script_relative_path for each_entry in ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES
|
|
12
13
|
]
|
|
13
|
-
assert
|
|
14
|
+
assert all_script_paths == [
|
|
15
|
+
"observability/test_failure_recorder.py",
|
|
16
|
+
"advisory/pr_done_reminder.py",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_pr_done_reminder_also_serves_the_powershell_tool() -> None:
|
|
21
|
+
reminder_entry = ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES[-1]
|
|
22
|
+
assert reminder_entry.script_relative_path == "advisory/pr_done_reminder.py"
|
|
23
|
+
assert "PowerShell" in reminder_entry.applicable_tool_names
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_context_forwarding_keys_match_the_hook_output_contract() -> None:
|
|
27
|
+
assert constants.POST_TOOL_USE_HOOK_EVENT_NAME == "PostToolUse"
|
|
28
|
+
assert constants.HOOK_SPECIFIC_OUTPUT_KEY == "hookSpecificOutput"
|
|
29
|
+
assert constants.ADDITIONAL_CONTEXT_KEY == "additionalContext"
|
|
30
|
+
assert constants.ADDITIONAL_CONTEXT_JOIN_SEPARATOR == "\n\n"
|
|
14
31
|
|
|
15
32
|
|
|
16
33
|
def test_every_roster_entry_applies_to_bash() -> None:
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
"""Tests for the Bash and PowerShell dispatcher hosted-hook roster.
|
|
2
|
-
|
|
3
|
-
The roster order and per-hook applicable-tool sets fix the firing sequence and
|
|
4
|
-
tool coverage the dispatcher must reproduce, so these tests pin both against the
|
|
5
|
-
registration order the standalone chain used.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
1
|
+
"""Tests for the Bash and PowerShell dispatcher hosted-hook roster."""
|
|
9
2
|
|
|
10
3
|
from pathlib import Path
|
|
11
4
|
from runpy import run_path
|
|
@@ -13,64 +6,8 @@ from runpy import run_path
|
|
|
13
6
|
ALL_CONSTANT_BINDINGS = run_path(
|
|
14
7
|
str(Path(__file__).with_name("bash_pre_tool_use_dispatcher_constants.py"))
|
|
15
8
|
)
|
|
16
|
-
ALL_BASH_AND_POWERSHELL_TOOL_NAMES = ALL_CONSTANT_BINDINGS["ALL_BASH_AND_POWERSHELL_TOOL_NAMES"]
|
|
17
9
|
ALL_BASH_HOSTED_HOOK_ENTRIES = ALL_CONSTANT_BINDINGS["ALL_BASH_HOSTED_HOOK_ENTRIES"]
|
|
18
|
-
BASH_TOOL_NAME = ALL_CONSTANT_BINDINGS["BASH_TOOL_NAME"]
|
|
19
|
-
POWERSHELL_TOOL_NAME = ALL_CONSTANT_BINDINGS["POWERSHELL_TOOL_NAME"]
|
|
20
|
-
|
|
21
|
-
_EXPECTED_BASH_ORDER = (
|
|
22
|
-
"blocking/destructive_command_blocker.py",
|
|
23
|
-
"blocking/shell_substitution_blocker.py",
|
|
24
|
-
"blocking/piped_pytest_blocker.py",
|
|
25
|
-
"blocking/cursor_cli_python_misfire_blocker.py",
|
|
26
|
-
"blocking/unscoped_search_blocker.py",
|
|
27
|
-
"blocking/nas_ssh_binary_enforcer.py",
|
|
28
|
-
"blocking/pii_prevention_blocker.py",
|
|
29
|
-
"blocking/block_main_commit.py",
|
|
30
|
-
"blocking/session_edit_stage_gate.py",
|
|
31
|
-
"blocking/windows_rmtree_blocker.py",
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
_POWERSHELL_APPLICABLE = (
|
|
35
|
-
"blocking/cursor_cli_python_misfire_blocker.py",
|
|
36
|
-
"blocking/unscoped_search_blocker.py",
|
|
37
|
-
"blocking/pii_prevention_blocker.py",
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def test_roster_lists_all_bash_hooks_in_registration_order() -> None:
|
|
42
|
-
"""The roster reproduces the standalone Bash chain order exactly."""
|
|
43
|
-
actual_order = tuple(
|
|
44
|
-
each_entry.script_relative_path for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
|
|
45
|
-
)
|
|
46
|
-
assert actual_order == _EXPECTED_BASH_ORDER
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def test_every_hook_applies_to_the_bash_tool() -> None:
|
|
50
|
-
"""Every hosted hook runs on a Bash tool call."""
|
|
51
|
-
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
|
|
52
|
-
assert BASH_TOOL_NAME in each_entry.applicable_tool_names
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_powershell_applicable_hooks_include_the_shared_gates() -> None:
|
|
56
|
-
"""PowerShell runs the shared unscoped-search and PII gates."""
|
|
57
|
-
powershell_hooks = tuple(
|
|
58
|
-
each_entry.script_relative_path
|
|
59
|
-
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
|
|
60
|
-
if POWERSHELL_TOOL_NAME in each_entry.applicable_tool_names
|
|
61
|
-
)
|
|
62
|
-
assert powershell_hooks == _POWERSHELL_APPLICABLE
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def test_powershell_hooks_carry_the_shared_tool_set() -> None:
|
|
66
|
-
"""The PowerShell-applicable hooks name both Bash and PowerShell."""
|
|
67
|
-
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
|
|
68
|
-
if each_entry.script_relative_path in _POWERSHELL_APPLICABLE:
|
|
69
|
-
assert each_entry.applicable_tool_names == ALL_BASH_AND_POWERSHELL_TOOL_NAMES
|
|
70
10
|
|
|
71
11
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
hooks_root = Path(__file__).resolve().parent.parent
|
|
75
|
-
for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
|
|
76
|
-
assert (hooks_root / each_entry.script_relative_path).is_file()
|
|
12
|
+
def test_roster_has_no_blocking_hooks() -> None:
|
|
13
|
+
assert ALL_BASH_HOSTED_HOOK_ENTRIES == ()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Pin the PR done reminder's command shape and checklist wording."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from hooks_constants import pr_done_reminder_constants as constants
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_gh_probe_asks_for_every_field_the_checklist_reads() -> None:
|
|
9
|
+
assert constants.ALL_GH_PR_VIEW_ARGUMENTS[:3] == ("gh", "pr", "view")
|
|
10
|
+
all_requested_fields = constants.ALL_GH_PR_VIEW_ARGUMENTS[-1].split(",")
|
|
11
|
+
for each_field in ("number", "url", "isDraft", "mergeable", "statusCheckRollup", "labels"):
|
|
12
|
+
assert each_field in all_requested_fields
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_git_global_options_that_take_a_value_are_named() -> None:
|
|
16
|
+
assert constants.ALL_GIT_OPTIONS_WITH_VALUE == frozenset({"-C", "-c"})
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_powershell_wrappers_and_their_command_flags_are_named() -> None:
|
|
20
|
+
assert "pwsh" in constants.ALL_POWERSHELL_PROGRAM_NAMES
|
|
21
|
+
assert "powershell" in constants.ALL_POWERSHELL_PROGRAM_NAMES
|
|
22
|
+
assert "-command" in constants.ALL_POWERSHELL_COMMAND_FLAGS
|
|
23
|
+
assert "-c" in constants.ALL_POWERSHELL_COMMAND_FLAGS
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_checklist_lines_join_on_a_single_newline() -> None:
|
|
27
|
+
assert constants.REMINDER_LINE_SEPARATOR == "\n"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_every_mergeable_value_has_a_hint() -> None:
|
|
31
|
+
assert set(constants.ALL_REMINDER_HINTS_BY_MERGEABLE) == {
|
|
32
|
+
constants.MERGEABLE_CLEAN_VALUE,
|
|
33
|
+
constants.MERGEABLE_CONFLICTING_VALUE,
|
|
34
|
+
constants.MERGEABLE_UNKNOWN_VALUE,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_header_says_it_never_blocks() -> None:
|
|
39
|
+
assert "never a block" in constants.REMINDER_HEADER
|
|
40
|
+
assert "never a block" in constants.NO_PULL_REQUEST_REMINDER
|
|
@@ -4,36 +4,24 @@ import importlib
|
|
|
4
4
|
import pathlib
|
|
5
5
|
import sys
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
MULTI_EDIT_TOOL_NAME,
|
|
26
|
-
WRITE_TOOL_NAME,
|
|
27
|
-
)
|
|
28
|
-
from pre_tool_use_dispatcher import (
|
|
29
|
-
HostedHookResult,
|
|
30
|
-
aggregate_hosted_hook_results,
|
|
31
|
-
)
|
|
32
|
-
except ImportError as import_error:
|
|
33
|
-
raise ImportError(
|
|
34
|
-
"test_pre_tool_use_dispatcher_constants: cannot import its sibling modules; "
|
|
35
|
-
"ensure the hooks and blocking directories are importable."
|
|
36
|
-
) from import_error
|
|
7
|
+
_HOOKS_ROOT = pathlib.Path(__file__).resolve().parent.parent
|
|
8
|
+
if str(_HOOKS_ROOT) not in sys.path:
|
|
9
|
+
sys.path.insert(0, str(_HOOKS_ROOT))
|
|
10
|
+
|
|
11
|
+
_BLOCKING_DIR = _HOOKS_ROOT / "blocking"
|
|
12
|
+
if str(_BLOCKING_DIR) not in sys.path:
|
|
13
|
+
sys.path.insert(0, str(_BLOCKING_DIR))
|
|
14
|
+
|
|
15
|
+
from hooks_constants.pre_tool_use_dispatcher_constants import (
|
|
16
|
+
ALL_HOSTED_HOOK_ENTRIES,
|
|
17
|
+
ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
18
|
+
ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
|
|
19
|
+
APPLY_PATCH_TOOL_NAME,
|
|
20
|
+
BLOCKING_CRASH_DENY_REASON,
|
|
21
|
+
EDIT_TOOL_NAME,
|
|
22
|
+
MULTI_EDIT_TOOL_NAME,
|
|
23
|
+
)
|
|
24
|
+
from pre_tool_use_dispatcher import HostedHookResult, aggregate_hosted_hook_results
|
|
37
25
|
|
|
38
26
|
|
|
39
27
|
def _entry_for(script_relative_path: str):
|
|
@@ -45,39 +33,44 @@ def _entry_for(script_relative_path: str):
|
|
|
45
33
|
return matching_entries[0] if matching_entries else None
|
|
46
34
|
|
|
47
35
|
|
|
48
|
-
def
|
|
49
|
-
|
|
36
|
+
def test_roster_keeps_only_nonblocking_edit_advisors() -> None:
|
|
37
|
+
all_script_paths = tuple(
|
|
50
38
|
each_entry.script_relative_path for each_entry in ALL_HOSTED_HOOK_ENTRIES
|
|
51
|
-
]
|
|
52
|
-
assert "blocking/duplicate_rmtree_helper_blocker.py" in all_registered_script_paths, (
|
|
53
|
-
"duplicate_rmtree_helper_blocker must be hosted by the dispatcher so a local "
|
|
54
|
-
"re-definition of the Windows-safe rmtree helper trio is blocked at Write time"
|
|
55
39
|
)
|
|
40
|
+
assert all_script_paths == (
|
|
41
|
+
"advisory/refactor_guard.py",
|
|
42
|
+
"advisory/migration_safety_advisor.py",
|
|
43
|
+
)
|
|
44
|
+
assert all(not each_entry.is_blocking for each_entry in ALL_HOSTED_HOOK_ENTRIES)
|
|
56
45
|
|
|
57
46
|
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
def test_advisors_apply_to_edit_and_multi_edit() -> None:
|
|
48
|
+
for each_script_path in (
|
|
49
|
+
"advisory/refactor_guard.py",
|
|
50
|
+
"advisory/migration_safety_advisor.py",
|
|
51
|
+
):
|
|
52
|
+
entry = _entry_for(each_script_path)
|
|
53
|
+
assert entry is not None
|
|
54
|
+
assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
|
|
63
55
|
|
|
64
56
|
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
def test_every_hosted_script_path_exists_under_the_hooks_root() -> None:
|
|
58
|
+
for each_entry in ALL_HOSTED_HOOK_ENTRIES:
|
|
59
|
+
hosted_script_path = _HOOKS_ROOT / each_entry.script_relative_path
|
|
60
|
+
assert hosted_script_path.is_file()
|
|
69
61
|
|
|
70
62
|
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
assert
|
|
74
|
-
assert
|
|
63
|
+
def test_retired_native_detector_keeps_its_callable_linter_interface() -> None:
|
|
64
|
+
native_module = importlib.import_module("state_description_blocker")
|
|
65
|
+
assert native_module.find_violations("The API uses port 8080.", "guide.md") == []
|
|
66
|
+
assert native_module.find_violations("Previously set via env var.", "guide.md")
|
|
67
|
+
assert all(each_entry.native_module_name is None for each_entry in ALL_HOSTED_HOOK_ENTRIES)
|
|
75
68
|
|
|
76
69
|
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
def test_four_way_set_covers_every_mutation_tool_name() -> None:
|
|
71
|
+
assert ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES == (
|
|
72
|
+
ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
|
|
73
|
+
)
|
|
81
74
|
|
|
82
75
|
|
|
83
76
|
def test_blocking_hook_crash_deny_reason_surfaces_the_constant() -> None:
|
|
@@ -90,151 +83,3 @@ def test_blocking_hook_crash_deny_reason_surfaces_the_constant() -> None:
|
|
|
90
83
|
decision = aggregate_hosted_hook_results([crash_result])
|
|
91
84
|
assert decision.should_deny
|
|
92
85
|
assert BLOCKING_CRASH_DENY_REASON in decision.all_deny_reasons
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def test_refactor_guard_is_hosted_as_an_edit_and_multi_edit_advisory_hook() -> None:
|
|
96
|
-
entry = _entry_for("advisory/refactor_guard.py")
|
|
97
|
-
assert entry is not None, (
|
|
98
|
-
"refactor_guard must be hosted by the dispatcher rather than spawning its own process"
|
|
99
|
-
)
|
|
100
|
-
assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
|
|
101
|
-
assert entry.is_blocking is False
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def test_migration_safety_advisor_is_hosted_as_an_edit_and_multi_edit_advisory_hook() -> None:
|
|
105
|
-
entry = _entry_for("advisory/migration_safety_advisor.py")
|
|
106
|
-
assert entry is not None, (
|
|
107
|
-
"migration_safety_advisor must be hosted by the dispatcher rather than "
|
|
108
|
-
"spawning its own process"
|
|
109
|
-
)
|
|
110
|
-
assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
|
|
111
|
-
assert entry.is_blocking is False
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def test_every_hosted_script_path_exists_under_the_hooks_root() -> None:
|
|
115
|
-
for each_entry in ALL_HOSTED_HOOK_ENTRIES:
|
|
116
|
-
hosted_script_path = _HOOKS_ROOT / each_entry.script_relative_path
|
|
117
|
-
assert hosted_script_path.is_file(), (
|
|
118
|
-
f"{each_entry.script_relative_path} is on the roster but missing from the hooks tree"
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def test_every_native_module_exposes_a_callable_evaluate() -> None:
|
|
123
|
-
nativized_entries = [
|
|
124
|
-
each_entry
|
|
125
|
-
for each_entry in ALL_HOSTED_HOOK_ENTRIES
|
|
126
|
-
if each_entry.native_module_name is not None
|
|
127
|
-
]
|
|
128
|
-
assert nativized_entries, (
|
|
129
|
-
"the roster must carry at least one nativized hook for this test to lock the contract"
|
|
130
|
-
)
|
|
131
|
-
for each_entry in nativized_entries:
|
|
132
|
-
native_module = importlib.import_module(each_entry.native_module_name)
|
|
133
|
-
evaluate_function = getattr(native_module, "evaluate", None)
|
|
134
|
-
assert callable(evaluate_function), (
|
|
135
|
-
f"{each_entry.native_module_name} must expose a callable named evaluate, "
|
|
136
|
-
"matching the native_module_name docstring contract"
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def test_four_way_set_covers_every_mutation_tool_name() -> None:
|
|
141
|
-
assert ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES == (
|
|
142
|
-
ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def test_immediate_harm_hooks_reach_apply_patch() -> None:
|
|
147
|
-
"""PII, sensitive-path, existing-file, CODE_RULES, and TDD gates all see apply_patch."""
|
|
148
|
-
for each_script_path in ALL_IMMEDIATE_HARM_SCRIPT_PATHS:
|
|
149
|
-
entry = _entry_for(each_script_path)
|
|
150
|
-
assert entry is not None, f"{each_script_path} must stay on the hosted roster"
|
|
151
|
-
assert APPLY_PATCH_TOOL_NAME in entry.applicable_tool_names, (
|
|
152
|
-
f"{each_script_path} must reach apply_patch for mutation-tool parity"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
_ALL_DEFERRED_LINT_SCRIPT_PATHS = (
|
|
157
|
-
"blocking/state_description_blocker.py",
|
|
158
|
-
"blocking/workflow_substitution_slot_blocker.py",
|
|
159
|
-
"blocking/claude_md_orphan_file_blocker.py",
|
|
160
|
-
"blocking/package_inventory_stale_blocker.py",
|
|
161
|
-
"blocking/env_var_table_code_drift_blocker.py",
|
|
162
|
-
"blocking/pytest_testpaths_orphan_blocker.py",
|
|
163
|
-
"blocking/open_questions_in_plans_blocker.py",
|
|
164
|
-
"blocking/docstring_rule_gate_count_blocker.py",
|
|
165
|
-
"blocking/duplicate_rmtree_helper_blocker.py",
|
|
166
|
-
"validation/hook_format_validator.py",
|
|
167
|
-
"blocking/hook_prose_detector_consistency.py",
|
|
168
|
-
"blocking/subprocess_budget_completeness.py",
|
|
169
|
-
"blocking/windows_rmtree_blocker.py",
|
|
170
|
-
"advisory/refactor_guard.py",
|
|
171
|
-
"advisory/migration_safety_advisor.py",
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def test_lint_and_advisory_hooks_stay_off_the_apply_patch_roster() -> None:
|
|
176
|
-
"""Every hook reaching MultiEdit but not apply_patch fails the same one rule.
|
|
177
|
-
|
|
178
|
-
apply_patch reaches only a gate whose violation is already real and
|
|
179
|
-
unrecoverable the moment the call returns: a leaked secret, an exposed
|
|
180
|
-
sensitive path, a blind overwrite, or an untested change landing. Every
|
|
181
|
-
hook named here instead judges the quality of the authored content for a
|
|
182
|
-
consequence the write itself does not cause right now: doc-inventory
|
|
183
|
-
drift, prose or naming style, a future-runtime correctness pattern (an
|
|
184
|
-
unsafe rmtree that only misbehaves on Windows, a subprocess-timeout
|
|
185
|
-
budget the harness reads separately), or an advisory suggestion that
|
|
186
|
-
never denies at all. Each is fixable in a later Edit-tool pass, so none
|
|
187
|
-
needs apply_patch's narrower, deny-only roster.
|
|
188
|
-
"""
|
|
189
|
-
for each_script_path in _ALL_DEFERRED_LINT_SCRIPT_PATHS:
|
|
190
|
-
entry = _entry_for(each_script_path)
|
|
191
|
-
assert entry is not None, f"{each_script_path} must stay on the hosted roster"
|
|
192
|
-
assert MULTI_EDIT_TOOL_NAME in entry.applicable_tool_names, (
|
|
193
|
-
f"{each_script_path} must still reach MultiEdit"
|
|
194
|
-
)
|
|
195
|
-
assert APPLY_PATCH_TOOL_NAME not in entry.applicable_tool_names, (
|
|
196
|
-
f"{each_script_path} judges deferred-fixable quality, not immediate harm, "
|
|
197
|
-
"so it must stay off the apply_patch roster"
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def test_edit_and_multi_edit_applicable_sets_are_equal() -> None:
|
|
202
|
-
"""The Edit roster and the MultiEdit roster name the same hooks.
|
|
203
|
-
|
|
204
|
-
Every hook applicable to Edit judges Write's content or an Edit's
|
|
205
|
-
old/new string pair with no dependency on which tool delivered it, so
|
|
206
|
-
the two sets must match exactly. A hook that legitimately stays
|
|
207
|
-
Edit-only is an exception written down here with its reason, not a
|
|
208
|
-
silent gap this test lets back in.
|
|
209
|
-
"""
|
|
210
|
-
all_edit_script_paths = {
|
|
211
|
-
each_entry.script_relative_path
|
|
212
|
-
for each_entry in ALL_HOSTED_HOOK_ENTRIES
|
|
213
|
-
if EDIT_TOOL_NAME in each_entry.applicable_tool_names
|
|
214
|
-
}
|
|
215
|
-
all_multi_edit_script_paths = {
|
|
216
|
-
each_entry.script_relative_path
|
|
217
|
-
for each_entry in ALL_HOSTED_HOOK_ENTRIES
|
|
218
|
-
if MULTI_EDIT_TOOL_NAME in each_entry.applicable_tool_names
|
|
219
|
-
}
|
|
220
|
-
assert all_edit_script_paths == all_multi_edit_script_paths, (
|
|
221
|
-
"Edit-only (not MultiEdit): "
|
|
222
|
-
f"{sorted(all_edit_script_paths - all_multi_edit_script_paths)}; "
|
|
223
|
-
"MultiEdit-only (not Edit): "
|
|
224
|
-
f"{sorted(all_multi_edit_script_paths - all_edit_script_paths)}"
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def test_multi_edit_widened_hooks_reach_multi_edit() -> None:
|
|
229
|
-
all_multi_edit_widened_script_paths = (
|
|
230
|
-
"blocking/write_existing_file_blocker.py",
|
|
231
|
-
"blocking/code_rules_enforcer.py",
|
|
232
|
-
"blocking/tdd_enforcer.py",
|
|
233
|
-
"blocking/state_description_blocker.py",
|
|
234
|
-
)
|
|
235
|
-
for each_script_path in all_multi_edit_widened_script_paths:
|
|
236
|
-
entry = _entry_for(each_script_path)
|
|
237
|
-
assert entry is not None, f"{each_script_path} must stay on the hosted roster"
|
|
238
|
-
assert MULTI_EDIT_TOOL_NAME in entry.applicable_tool_names, (
|
|
239
|
-
f"{each_script_path} must reach MultiEdit for mutation-tool parity"
|
|
240
|
-
)
|
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
"""Tests for the Stop-hook dispatcher hosted-hook roster."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from hooks_constants.stop_dispatcher_constants import ALL_STOP_HOSTED_HOOK_PATHS
|
|
4
4
|
|
|
5
|
-
import sys
|
|
6
|
-
from pathlib import Path
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
sys.path.insert(0, _HOOKS_DIR)
|
|
11
|
-
|
|
12
|
-
from hooks_constants.stop_dispatcher_constants import ALL_STOP_HOSTED_HOOK_PATHS # noqa: E402
|
|
13
|
-
|
|
14
|
-
_EXPECTED_STOP_ORDER = (
|
|
15
|
-
"blocking/question_to_user_enforcer.py",
|
|
16
|
-
"blocking/session_handoff_blocker.py",
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def test_roster_lists_all_stop_hooks_in_registration_order() -> None:
|
|
21
|
-
"""The roster reproduces the standalone Stop chain order exactly."""
|
|
22
|
-
assert ALL_STOP_HOSTED_HOOK_PATHS == _EXPECTED_STOP_ORDER
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def test_every_roster_path_points_at_an_existing_hook() -> None:
|
|
26
|
-
"""Each roster path names a hook script present on disk, catching a typo."""
|
|
27
|
-
hooks_root = Path(__file__).resolve().parent.parent
|
|
28
|
-
for each_relative_path in ALL_STOP_HOSTED_HOOK_PATHS:
|
|
29
|
-
assert (hooks_root / each_relative_path).is_file()
|
|
6
|
+
def test_roster_has_no_blocking_hooks() -> None:
|
|
7
|
+
assert ALL_STOP_HOSTED_HOOK_PATHS == ()
|