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,130 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Stop hook that blocks Claude responses asking the user questions in prose.
|
|
4
|
-
|
|
5
|
-
User-directed questions must route through the AskUserQuestion tool so the user
|
|
6
|
-
sees structured options with labels. When the final paragraph of the response
|
|
7
|
-
ends with a question mark or contains a recognized preamble phrase
|
|
8
|
-
("would you like", "should I", "do you want", "want me to", etc.), Claude is
|
|
9
|
-
forced to re-output the response with the ask moved into an AskUserQuestion
|
|
10
|
-
tool call.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import json
|
|
14
|
-
import re
|
|
15
|
-
import sys
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
_hooks_dir = str(Path(__file__).resolve().parent.parent)
|
|
19
|
-
if _hooks_dir not in sys.path:
|
|
20
|
-
sys.path.insert(0, _hooks_dir)
|
|
21
|
-
|
|
22
|
-
from hooks_constants.hook_block_logger import log_hook_block # noqa: E402
|
|
23
|
-
from hooks_constants.messages import USER_FACING_ASKUSERQUESTION_NOTICE # noqa: E402
|
|
24
|
-
from hooks_constants.text_stripping import strip_code_and_quotes # noqa: E402
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def extract_final_paragraph(text: str) -> str:
|
|
28
|
-
"""Return the last non-empty paragraph of the prose after stripping code and quotes."""
|
|
29
|
-
paragraph_split_pattern = re.compile(r"\n\s*\n")
|
|
30
|
-
prose_text = strip_code_and_quotes(text)
|
|
31
|
-
candidate_paragraphs = [
|
|
32
|
-
each_paragraph.strip()
|
|
33
|
-
for each_paragraph in paragraph_split_pattern.split(prose_text)
|
|
34
|
-
if each_paragraph.strip()
|
|
35
|
-
]
|
|
36
|
-
if not candidate_paragraphs:
|
|
37
|
-
return ""
|
|
38
|
-
return candidate_paragraphs[-1]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def find_user_directed_question_indicators(text: str) -> list[str]:
|
|
42
|
-
"""Return indicator names for every user-directed question signal in the final paragraph."""
|
|
43
|
-
all_preamble_patterns = [
|
|
44
|
-
(re.compile(regex_text, re.IGNORECASE), display_name)
|
|
45
|
-
for regex_text, display_name in [
|
|
46
|
-
(r"\bwould\s+you\s+like\b", "would you like"),
|
|
47
|
-
(r"\bshould\s+i\b", "should i"),
|
|
48
|
-
(r"\bdo\s+you\s+want\b", "do you want"),
|
|
49
|
-
(r"\bwhich\s+would\s+you\s+prefer\b", "which would you prefer"),
|
|
50
|
-
(r"\blet\s+me\s+know\s+if\b", "let me know if"),
|
|
51
|
-
(r"\blet\s+me\s+know\s+which\b", "let me know which"),
|
|
52
|
-
(r"\blet\s+me\s+know\s+whether\b", "let me know whether"),
|
|
53
|
-
(r"\bplease\s+confirm\b", "please confirm"),
|
|
54
|
-
(r"\bplease\s+let\s+me\s+know\b", "please let me know"),
|
|
55
|
-
(r"\bwant\s+me\s+to\b", "want me to"),
|
|
56
|
-
]
|
|
57
|
-
]
|
|
58
|
-
terminal_question_mark_pattern = re.compile(r"\?[\s\"'\)\]\}]*\Z")
|
|
59
|
-
terminal_question_mark_indicator = "terminal question mark in final paragraph"
|
|
60
|
-
|
|
61
|
-
final_paragraph = extract_final_paragraph(text)
|
|
62
|
-
if not final_paragraph:
|
|
63
|
-
return []
|
|
64
|
-
|
|
65
|
-
matched_indicators: list[str] = []
|
|
66
|
-
|
|
67
|
-
if terminal_question_mark_pattern.search(final_paragraph.rstrip()):
|
|
68
|
-
matched_indicators.append(terminal_question_mark_indicator)
|
|
69
|
-
|
|
70
|
-
for each_pattern, each_display_name in all_preamble_patterns:
|
|
71
|
-
if (
|
|
72
|
-
each_pattern.search(final_paragraph)
|
|
73
|
-
and each_display_name not in matched_indicators
|
|
74
|
-
):
|
|
75
|
-
matched_indicators.append(each_display_name)
|
|
76
|
-
|
|
77
|
-
return matched_indicators
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def main() -> None:
|
|
81
|
-
try:
|
|
82
|
-
hook_input = json.load(sys.stdin)
|
|
83
|
-
except json.JSONDecodeError:
|
|
84
|
-
sys.exit(0)
|
|
85
|
-
|
|
86
|
-
if hook_input.get("stop_hook_active", False):
|
|
87
|
-
sys.exit(0)
|
|
88
|
-
|
|
89
|
-
assistant_message = hook_input.get("last_assistant_message", "")
|
|
90
|
-
|
|
91
|
-
if not assistant_message:
|
|
92
|
-
sys.exit(0)
|
|
93
|
-
|
|
94
|
-
matched_indicators = find_user_directed_question_indicators(assistant_message)
|
|
95
|
-
|
|
96
|
-
if not matched_indicators:
|
|
97
|
-
sys.exit(0)
|
|
98
|
-
|
|
99
|
-
formatted_indicator_list = ", ".join(
|
|
100
|
-
f'"{each_indicator}"' for each_indicator in matched_indicators
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
block_reason = (
|
|
104
|
-
f"ASKUSERQUESTION GUARDRAIL: Your response asks the user a question in prose "
|
|
105
|
-
f"(indicators: {formatted_indicator_list}). "
|
|
106
|
-
f"User-directed questions must route through the AskUserQuestion tool so the user "
|
|
107
|
-
f"sees structured options with labels.\n\n"
|
|
108
|
-
f"Re-output your response with the trailing question removed from prose and moved "
|
|
109
|
-
f"into an AskUserQuestion tool call. Rhetorical questions answered in the same "
|
|
110
|
-
f"paragraph are allowed; questions inside code fences, inline code, and blockquotes "
|
|
111
|
-
f"are ignored.\n\n"
|
|
112
|
-
f"You MUST re-output the complete, revised response with the correction applied."
|
|
113
|
-
)
|
|
114
|
-
block_response = {
|
|
115
|
-
"decision": "block",
|
|
116
|
-
"reason": block_reason,
|
|
117
|
-
"systemMessage": USER_FACING_ASKUSERQUESTION_NOTICE,
|
|
118
|
-
"suppressOutput": True,
|
|
119
|
-
}
|
|
120
|
-
log_hook_block(
|
|
121
|
-
calling_hook_name="question_to_user_enforcer.py",
|
|
122
|
-
hook_event="Stop",
|
|
123
|
-
block_reason=block_reason,
|
|
124
|
-
)
|
|
125
|
-
print(json.dumps(block_response))
|
|
126
|
-
sys.exit(0)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if __name__ == "__main__":
|
|
130
|
-
main()
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""PreToolUse hook: block SendUserFile attaches that should open locally.
|
|
3
|
-
|
|
4
|
-
SendUserFile attaches a file to the session. While the user is at the terminal
|
|
5
|
-
(status "normal" or unset) an attach does not let them see the file — it must
|
|
6
|
-
open on screen in its native Windows app. The corrective message names the
|
|
7
|
-
``Invoke-Item -LiteralPath`` form. The one attach allowed through is an
|
|
8
|
-
away-from-desk phone push (status "proactive").
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import json
|
|
12
|
-
import sys
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
|
|
15
|
-
_hooks_dir = str(Path(__file__).resolve().parent.parent)
|
|
16
|
-
if _hooks_dir not in sys.path:
|
|
17
|
-
sys.path.insert(0, _hooks_dir)
|
|
18
|
-
|
|
19
|
-
from hooks_constants.hook_block_logger import log_hook_block # noqa: E402
|
|
20
|
-
from hooks_constants.send_user_file_open_locally_blocker_constants import ( # noqa: E402
|
|
21
|
-
CORRECTIVE_MESSAGE,
|
|
22
|
-
PROACTIVE_STATUS,
|
|
23
|
-
TOOL_NAME,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def _should_block(status: str) -> bool:
|
|
28
|
-
"""Return whether a SendUserFile call with this status should be denied.
|
|
29
|
-
|
|
30
|
-
Args:
|
|
31
|
-
status: The ``status`` field from the SendUserFile input. A proactive
|
|
32
|
-
phone push is allowed; every other value, including an empty one,
|
|
33
|
-
is a desk-side attach the user cannot see and is denied.
|
|
34
|
-
"""
|
|
35
|
-
return status != PROACTIVE_STATUS
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def main() -> None:
|
|
39
|
-
try:
|
|
40
|
-
hook_input = json.load(sys.stdin)
|
|
41
|
-
except json.JSONDecodeError:
|
|
42
|
-
sys.exit(0)
|
|
43
|
-
|
|
44
|
-
if hook_input.get("tool_name", "") != TOOL_NAME:
|
|
45
|
-
sys.exit(0)
|
|
46
|
-
|
|
47
|
-
tool_input = hook_input.get("tool_input") or {}
|
|
48
|
-
status = tool_input.get("status", "")
|
|
49
|
-
if not _should_block(status):
|
|
50
|
-
sys.exit(0)
|
|
51
|
-
|
|
52
|
-
deny_payload = {
|
|
53
|
-
"hookSpecificOutput": {
|
|
54
|
-
"hookEventName": "PreToolUse",
|
|
55
|
-
"permissionDecision": "deny",
|
|
56
|
-
"permissionDecisionReason": CORRECTIVE_MESSAGE,
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
log_hook_block(
|
|
60
|
-
calling_hook_name="send_user_file_open_locally_blocker.py",
|
|
61
|
-
hook_event="PreToolUse",
|
|
62
|
-
block_reason=CORRECTIVE_MESSAGE,
|
|
63
|
-
tool_name=TOOL_NAME,
|
|
64
|
-
)
|
|
65
|
-
print(json.dumps(deny_payload))
|
|
66
|
-
sys.stdout.flush()
|
|
67
|
-
sys.exit(0)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if __name__ == "__main__":
|
|
71
|
-
main()
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Deny a Write, Edit, or MultiEdit whose target filename names a secret or a lock file.
|
|
3
|
-
|
|
4
|
-
::
|
|
5
|
-
|
|
6
|
-
.env flag: a live secrets file
|
|
7
|
-
.env.local flag: a live per-machine secrets file
|
|
8
|
-
credentials.json flag: a live credential file
|
|
9
|
-
id_ed25519 flag: a live private key
|
|
10
|
-
package-lock.json flag: regenerated by its package manager, never hand-edited
|
|
11
|
-
|
|
12
|
-
.env.example ok: a placeholders-only template, committed on purpose
|
|
13
|
-
.env.sample ok: the same shape, .sample spelling
|
|
14
|
-
.env.template ok: the same shape, .template spelling
|
|
15
|
-
main.py ok: ordinary source
|
|
16
|
-
|
|
17
|
-
A basename whose FINAL suffix is ``.example``, ``.sample``, or ``.template``
|
|
18
|
-
names a committed template, so the filename guard steps aside for it. The
|
|
19
|
-
suffix has to come last: ``.env.example.bak`` is a copy of a live secrets
|
|
20
|
-
file, not a template, and stays denied.
|
|
21
|
-
|
|
22
|
-
The guard over a write's contents stays in force: the ``pii_prevention_blocker``
|
|
23
|
-
hook scans what a write carries, so a template holding a real secret or a real
|
|
24
|
-
email address is denied on its contents. The two hooks are layered, and this
|
|
25
|
-
one rules on the filename alone.
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
from __future__ import annotations
|
|
29
|
-
|
|
30
|
-
import fnmatch
|
|
31
|
-
import json
|
|
32
|
-
import os
|
|
33
|
-
import sys
|
|
34
|
-
|
|
35
|
-
import _path_setup # noqa: F401
|
|
36
|
-
|
|
37
|
-
from codex_apply_patch import payload_patch_target_paths
|
|
38
|
-
from hooks_constants.hook_block_logger import log_hook_block
|
|
39
|
-
from hooks_constants.pre_tool_use_dispatcher_constants import (
|
|
40
|
-
ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
|
|
41
|
-
APPLY_PATCH_TOOL_NAME,
|
|
42
|
-
)
|
|
43
|
-
from hooks_constants.sensitive_file_protector_constants import (
|
|
44
|
-
ALL_SENSITIVE_PATTERNS,
|
|
45
|
-
ALL_TEMPLATE_SUFFIXES,
|
|
46
|
-
DENY_DECISION,
|
|
47
|
-
DENY_REASON_TEMPLATE,
|
|
48
|
-
HOOK_EVENT_NAME,
|
|
49
|
-
HOOK_SCRIPT_NAME,
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def is_template_filename(filename: str) -> bool:
|
|
54
|
-
"""Report whether a basename names a placeholders-only committed template.
|
|
55
|
-
|
|
56
|
-
::
|
|
57
|
-
|
|
58
|
-
.env.example -> True
|
|
59
|
-
.ENV.Template -> True
|
|
60
|
-
.env.example.bak -> False
|
|
61
|
-
.env.local -> False
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
filename: The basename of the file a Write, Edit, or MultiEdit targets.
|
|
65
|
-
|
|
66
|
-
Returns:
|
|
67
|
-
True when the basename's final suffix is a template suffix.
|
|
68
|
-
"""
|
|
69
|
-
return filename.lower().endswith(ALL_TEMPLATE_SUFFIXES)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def is_sensitive_file(file_path: str) -> str | None:
|
|
73
|
-
"""Return the sensitive pattern a path's basename matches, or None.
|
|
74
|
-
|
|
75
|
-
Args:
|
|
76
|
-
file_path: The path the Write, Edit, or MultiEdit targets.
|
|
77
|
-
|
|
78
|
-
Returns:
|
|
79
|
-
The matched pattern, or None when the basename names a template or
|
|
80
|
-
matches no pattern.
|
|
81
|
-
"""
|
|
82
|
-
filename = os.path.basename(file_path)
|
|
83
|
-
if is_template_filename(filename):
|
|
84
|
-
return None
|
|
85
|
-
for each_pattern in ALL_SENSITIVE_PATTERNS:
|
|
86
|
-
if fnmatch.fnmatch(filename.lower(), each_pattern.lower()):
|
|
87
|
-
return each_pattern
|
|
88
|
-
return None
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def build_deny_response(deny_reason: str) -> dict[str, dict[str, str]]:
|
|
92
|
-
"""Wrap a deny reason in the PreToolUse decision payload Claude Code reads.
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
deny_reason: The operator-facing sentence explaining the denial.
|
|
96
|
-
|
|
97
|
-
Returns:
|
|
98
|
-
The hook decision dictionary carrying the deny permission decision.
|
|
99
|
-
"""
|
|
100
|
-
return {
|
|
101
|
-
"hookSpecificOutput": {
|
|
102
|
-
"hookEventName": HOOK_EVENT_NAME,
|
|
103
|
-
"permissionDecision": DENY_DECISION,
|
|
104
|
-
"permissionDecisionReason": deny_reason,
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def deny_write(file_path: str, matched_pattern: str) -> None:
|
|
110
|
-
"""Record the block in the hook-blocks log and emit the deny decision.
|
|
111
|
-
|
|
112
|
-
Args:
|
|
113
|
-
file_path: The path the Write, Edit, MultiEdit, or apply_patch targets.
|
|
114
|
-
matched_pattern: The sensitive pattern the basename matched.
|
|
115
|
-
"""
|
|
116
|
-
deny_reason = DENY_REASON_TEMPLATE.format(
|
|
117
|
-
filename=os.path.basename(file_path),
|
|
118
|
-
matched_pattern=matched_pattern,
|
|
119
|
-
)
|
|
120
|
-
log_hook_block(
|
|
121
|
-
calling_hook_name=HOOK_SCRIPT_NAME,
|
|
122
|
-
hook_event=HOOK_EVENT_NAME,
|
|
123
|
-
block_reason=deny_reason,
|
|
124
|
-
offending_input_preview=file_path,
|
|
125
|
-
)
|
|
126
|
-
sys.stdout.write(json.dumps(build_deny_response(deny_reason)))
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def _deny_apply_patch_sensitive_target(hook_input: dict, tool_input: dict) -> None:
|
|
130
|
-
"""Deny the first apply_patch target path whose basename names a sensitive file."""
|
|
131
|
-
for each_target_path in payload_patch_target_paths(hook_input, tool_input):
|
|
132
|
-
matched_pattern = is_sensitive_file(each_target_path)
|
|
133
|
-
if matched_pattern is not None:
|
|
134
|
-
deny_write(each_target_path, matched_pattern)
|
|
135
|
-
return
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def main() -> None:
|
|
139
|
-
"""Deny the write when the stdin payload targets a sensitive filename."""
|
|
140
|
-
try:
|
|
141
|
-
hook_input = json.load(sys.stdin)
|
|
142
|
-
except json.JSONDecodeError:
|
|
143
|
-
sys.exit(0)
|
|
144
|
-
|
|
145
|
-
tool_name = hook_input.get("tool_name", "")
|
|
146
|
-
tool_input = hook_input.get("tool_input", {})
|
|
147
|
-
|
|
148
|
-
if tool_name not in ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES:
|
|
149
|
-
sys.exit(0)
|
|
150
|
-
|
|
151
|
-
if tool_name == APPLY_PATCH_TOOL_NAME:
|
|
152
|
-
_deny_apply_patch_sensitive_target(hook_input, tool_input)
|
|
153
|
-
sys.exit(0)
|
|
154
|
-
|
|
155
|
-
file_path = tool_input.get("file_path", "")
|
|
156
|
-
if not file_path:
|
|
157
|
-
sys.exit(0)
|
|
158
|
-
|
|
159
|
-
matched_pattern = is_sensitive_file(file_path)
|
|
160
|
-
if matched_pattern is not None:
|
|
161
|
-
deny_write(file_path, matched_pattern)
|
|
162
|
-
|
|
163
|
-
sys.exit(0)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if __name__ == "__main__":
|
|
167
|
-
main()
|