claude-dev-env 2.4.0 → 2.7.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/CLAUDE.md +26 -59
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +84 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +6 -3
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +12 -2
- package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +309 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +540 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +206 -70
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/__init__.py +1 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/_repo_test_helpers.py +76 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_baseline_import_isolation.py +248 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_regression.py +309 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +91 -58
- package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +306 -306
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +44 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +202 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -24
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py +107 -107
- package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +290 -48
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +42 -2
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +36 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +100 -1
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -497
- package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +311 -2
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep.py +301 -301
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep_constants.py +85 -85
- package/_shared/pr-loop/worker-spawn.md +1 -1
- package/agents/CLAUDE.md +3 -2
- package/agents/caveman.md +0 -1
- package/agents/clasp-deployment-orchestrator.md +0 -1
- package/agents/clean-coder.md +0 -1
- package/agents/code-advisor.md +0 -1
- package/agents/code-quality-agent.md +1 -2
- package/agents/code-verifier.md +36 -8
- package/agents/deep-research.md +0 -1
- package/agents/docs-agent.md +0 -1
- package/agents/git-commit-crafter.md +0 -1
- package/agents/issue-tracker.md +42 -0
- package/agents/plan-packet-validator.md +0 -1
- package/agents/pr-description-writer.md +0 -1
- package/agents/test_agent_frontmatter.py +67 -18
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +143 -141
- package/bin/CLAUDE.md +68 -5
- package/bin/codex-compat.mjs +104 -0
- package/bin/codex-compat.test.mjs +51 -0
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +88 -0
- package/bin/install.mjs +1138 -114
- package/bin/install.prune.test.mjs +869 -19
- package/bin/install.test.mjs +906 -2
- package/codex-capability-map.json +13 -0
- package/commands/implement.md +1 -1
- package/commands/right-size.md +1 -1
- package/docs/CLAUDE.md +1 -0
- package/docs/CODE_RULES.md +2 -0
- package/docs/codex-compatibility.md +25 -0
- package/docs/host-pool-health-monitor.md +102 -0
- package/docs/nas-ssh-invocation.md +96 -12
- package/docs/references/CLAUDE.md +4 -2
- package/docs/references/advisor-tool.md +13 -0
- package/docs/references/code-review-enforcement.md +35 -0
- package/docs/references/team-advisor-skill.md +14 -0
- package/hooks/blocking/CLAUDE.md +4 -0
- package/hooks/blocking/code_review_pr_create_gate.py +7 -3
- package/hooks/blocking/code_review_push_gate.py +9 -4
- package/hooks/blocking/code_review_stamp_directory_write_blocker.py +8 -0
- package/hooks/blocking/config/__init__.py +5 -5
- package/hooks/blocking/config/code_review_enforcement_constants.py +40 -7
- package/hooks/blocking/config/test_code_review_enforcement_constants.py +58 -0
- package/hooks/blocking/config/verified_commit_constants.py +160 -159
- package/hooks/blocking/eli11_reply_enforcer.py +479 -0
- package/hooks/blocking/gh_body_arg_blocker.py +1 -1
- package/hooks/blocking/nas_ssh_binary_enforcer.py +8 -46
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +256 -0
- package/hooks/blocking/pre_tool_use_dispatcher.py +24 -24
- package/hooks/blocking/shell_substitution_blocker.py +129 -0
- package/hooks/blocking/state_description_blocker.py +1 -1
- package/hooks/blocking/stop_dispatcher.py +1 -1
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +2 -3
- package/hooks/blocking/test_code_review_pr_create_gate.py +14 -0
- package/hooks/blocking/test_code_review_push_gate.py +16 -0
- package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +19 -0
- package/hooks/blocking/test_eli11_reply_enforcer.py +457 -0
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +231 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +10 -1
- package/hooks/blocking/test_shell_substitution_blocker.py +124 -0
- package/hooks/blocking/test_stop_dispatcher.py +23 -0
- package/hooks/blocking/test_unscoped_search_blocker.py +102 -0
- package/hooks/blocking/test_verdict_directory_write_blocker.py +804 -808
- package/hooks/blocking/test_verification_verdict_store.py +54 -0
- package/hooks/blocking/test_verified_commit_gate.py +581 -581
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -131
- package/hooks/blocking/unscoped_search_blocker.py +391 -0
- package/hooks/blocking/verdict_directory_write_blocker.py +687 -687
- package/hooks/blocking/verification_verdict_store.py +1039 -1036
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +167 -167
- package/hooks/blocking/verifier_verdict_minter.py +280 -280
- package/hooks/git-hooks/CLAUDE.md +3 -0
- package/hooks/git-hooks/conftest.py +30 -0
- package/hooks/git-hooks/gate_utils.py +2 -2
- package/hooks/git-hooks/git_hooks_constants/__init__.py +41 -2
- package/hooks/git-hooks/pre_push.py +75 -4
- package/hooks/git-hooks/pre_push_base_reference.py +166 -0
- package/hooks/git-hooks/test_config.py +0 -15
- package/hooks/git-hooks/test_gate_utils.py +3 -15
- package/hooks/git-hooks/test_pre_commit.py +1 -15
- package/hooks/git-hooks/test_pre_push.py +257 -23
- package/hooks/git-hooks/test_pre_push_base_reference.py +339 -0
- package/hooks/hooks.json +10 -12
- package/hooks/hooks_constants/CLAUDE.md +7 -2
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +4 -4
- package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +101 -0
- package/hooks/hooks_constants/enter_worktree_prefetch_constants.py +18 -18
- package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +2 -8
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +48 -0
- package/hooks/hooks_constants/ruff_integration_constants.py +16 -0
- package/hooks/hooks_constants/shell_command_segments.py +82 -0
- package/hooks/hooks_constants/shell_substitution_blocker_constants.py +67 -0
- package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -0
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +5 -6
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +1 -0
- package/hooks/hooks_constants/unscoped_search_blocker_constants.py +153 -0
- package/hooks/lifecycle/enter_worktree_origin_prefetch.py +163 -146
- package/hooks/lifecycle/test_enter_worktree_origin_prefetch.py +185 -178
- package/hooks/pyproject.toml +1 -0
- package/hooks/validators/CLAUDE.md +1 -0
- package/hooks/validators/config/__init__.py +0 -0
- package/hooks/validators/config/directory_exemption_constants.py +183 -0
- package/hooks/validators/config/test_directory_exemption_constants.py +21 -0
- package/hooks/validators/conftest.py +4 -0
- package/hooks/validators/ruff_integration.py +49 -5
- package/hooks/validators/run_all_validators.py +206 -9
- package/hooks/validators/test_directory_exemption_constants.py +185 -0
- package/hooks/validators/test_python_antipattern_checks.py +110 -5
- package/hooks/validators/test_ruff_integration.py +92 -1
- package/hooks/validators/test_run_all_validators.py +115 -68
- package/hooks/validators/test_run_all_validators_pretooluse.py +159 -1
- package/package.json +13 -3
- package/rules/CLAUDE.md +17 -22
- package/rules/agent-spawn-protocol.md +6 -6
- package/rules/anti-corollary-tests.md +1 -1
- package/rules/bdd.md +1 -1
- package/rules/cleanup-temp-files.md +10 -4
- package/rules/code-standards.md +7 -0
- package/rules/conservative-action.md +1 -5
- package/rules/context7.md +0 -4
- package/rules/destructive-commands.md +47 -0
- package/rules/doc-inventory-integrity.md +48 -0
- package/rules/doc-prose-cuts.md +58 -0
- package/rules/docstring-prose-matches-implementation.md +53 -44
- package/rules/durable-post-artifacts.md +0 -4
- package/rules/eli11-replies.md +31 -0
- package/rules/explore-thoroughly.md +4 -4
- package/rules/falsify-before-green.md +68 -0
- package/rules/file-global-constants.md +1 -1
- package/rules/filesystem-search.md +51 -0
- package/rules/gh-cli-conventions.md +27 -0
- package/rules/git-workflow.md +26 -0
- package/rules/hedging-claims.md +9 -0
- package/rules/long-horizon-autonomy.md +0 -4
- package/rules/measurement-denominators.md +48 -0
- package/rules/nas-ssh-invocation.md +23 -5
- package/rules/parallel-tools.md +2 -2
- package/rules/plain-illustrative-docstrings.md +3 -7
- package/rules/plain-language.md +2 -0
- package/rules/proof-of-work-pr-comments.md +0 -4
- package/rules/re-stage-before-commit.md +2 -0
- package/rules/research-mode.md +10 -0
- package/rules/shell-invocation.md +21 -0
- package/rules/testing.md +4 -0
- package/rules/verified-commit-gate-skip.md +3 -27
- package/rules/verify-before-asking.md +5 -0
- package/rules/windows-filesystem-safe.md +1 -1
- package/rules/workers-done-before-complete.md +4 -0
- package/scripts/CLAUDE.md +1 -0
- package/scripts/Capture-PoolHealth.ps1 +410 -0
- package/scripts/Migrate-ShellPolicy.ps1 +1 -1
- package/scripts/_code_review_test_support.py +404 -0
- package/scripts/claude_chain_runner.py +141 -1
- package/scripts/codex_capability_bridge.py +171 -0
- package/scripts/codex_compat_materializer.py +1087 -0
- package/scripts/codex_compat_watcher.py +502 -0
- package/scripts/conftest.py +16 -1
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
- package/scripts/dev_env_scripts_constants/claude_chain_constants.py +9 -0
- package/scripts/dev_env_scripts_constants/code_review_constants.py +37 -0
- package/scripts/invoke_code_review.py +11 -4
- package/scripts/resolve_worker_spawn.py +626 -626
- package/scripts/spawn_grok_batch.py +672 -672
- package/scripts/sync_to_cursor/rules.py +0 -10
- package/scripts/test_claude_chain_runner.py +131 -0
- package/scripts/test_invoke_code_review.py +85 -908
- package/scripts/test_invoke_code_review_chain.py +70 -0
- package/scripts/test_invoke_code_review_cli.py +192 -0
- package/scripts/test_invoke_code_review_contract.py +256 -0
- package/scripts/test_invoke_code_review_git.py +123 -0
- package/scripts/test_invoke_code_review_mode.py +99 -0
- package/scripts/test_resolve_worker_spawn.py +1014 -1014
- package/scripts/tests/test_code_review_constants.py +80 -0
- package/scripts/tests/test_codex_capability_bridge.py +91 -0
- package/scripts/tests/test_codex_compat_materializer.py +632 -0
- package/scripts/tests/test_codex_compat_watcher.py +599 -0
- package/scripts/tests/test_sync_to_cursor.py +0 -1
- package/skills/CLAUDE.md +2 -0
- package/skills/auditing-claude-config/SKILL.md +114 -114
- package/skills/autoconverge/SKILL.md +427 -427
- package/skills/autoconverge/reference/convergence.md +24 -3
- package/skills/autoconverge/workflow/CLAUDE.md +1 -0
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +3 -3
- package/skills/autoconverge/workflow/converge.contract.test.mjs +1263 -1263
- package/skills/autoconverge/workflow/converge.mjs +168 -1
- package/skills/autoconverge/workflow/converge.p2-advance.test.mjs +202 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +265 -265
- package/skills/bugteam/reference/copilot-gap-analysis.md +1 -1
- package/skills/closeout/SKILL.md +33 -50
- package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +8 -0
- package/skills/codex-review/scripts/run_codex_review.py +233 -1
- package/skills/codex-review/scripts/test_run_codex_review.py +189 -0
- package/skills/condensing-instructions/SKILL.md +72 -0
- package/skills/copilot-review/SKILL.md +119 -119
- package/skills/e-code-review/SKILL.md +52 -0
- package/skills/e-code-review/reference/fix.md +54 -0
- package/skills/e-code-review/reference/loop.md +43 -0
- package/skills/e-code-review/reference/low.md +57 -0
- package/skills/e-code-review/reference/medium.md +153 -0
- package/skills/e-code-review/reference/xhigh.md +182 -0
- package/skills/e-simplify/SKILL.md +97 -0
- package/skills/fresh-branch/CLAUDE.md +1 -1
- package/skills/fresh-branch/SKILL.md +5 -6
- package/skills/fresh-branch/scripts/create_fresh_branch.py +42 -24
- package/skills/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +1 -3
- package/skills/fresh-branch/scripts/test_create_fresh_branch.py +30 -126
- package/skills/issue-tracker/SKILL.md +92 -0
- package/skills/issue-tracker/reference/epic-and-sub-issue-model.md +55 -0
- package/skills/issue-tracker/reference/handoff-schema.md +64 -0
- package/skills/issue-tracker/reference/operation-matrix.md +41 -0
- package/skills/orchestrator/SKILL.md +177 -22
- package/skills/orchestrator/scripts/status_gate.py +625 -0
- package/skills/orchestrator/scripts/status_gate_constants/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/constants.py +47 -0
- package/skills/orchestrator/scripts/test_status_gate.py +439 -0
- package/skills/orchestrator-refresh/SKILL.md +129 -35
- package/skills/plan-to-pr/SKILL.md +155 -0
- package/skills/plan-to-pr/reference/final-validation-tasks.md +15 -0
- package/skills/plan-to-pr/reference/model-routing.md +36 -0
- package/skills/plan-to-pr/reference/packet-contract.md +43 -0
- package/skills/plan-to-pr/reference/packet-schema.json +57 -0
- package/skills/plan-to-pr/reference/process-inventory.md +22 -0
- package/skills/plan-to-pr/reference/review-loop.md +33 -0
- package/skills/plan-to-pr/reference/run-record.schema.json +27 -0
- package/skills/plan-to-pr/reference/self-audit-tasks.md +15 -0
- package/skills/plan-to-pr/reference/task-seeds.md +14 -0
- package/skills/plan-to-pr/reference/task-ticket.md +38 -0
- package/skills/plan-to-pr/scripts/config/__init__.py +1 -0
- package/skills/plan-to-pr/scripts/config/constants.py +193 -0
- package/skills/plan-to-pr/scripts/create_packet.py +173 -0
- package/skills/plan-to-pr/scripts/test_create_packet.py +102 -0
- package/skills/plan-to-pr/scripts/test_validate_packet.py +256 -0
- package/skills/plan-to-pr/scripts/test_validate_protocol.py +135 -0
- package/skills/plan-to-pr/scripts/test_validate_run.py +158 -0
- package/skills/plan-to-pr/scripts/validate_packet.py +655 -0
- package/skills/plan-to-pr/scripts/validate_protocol.py +622 -0
- package/skills/plan-to-pr/scripts/validate_run.py +173 -0
- package/skills/plan-to-pr/test_skill_contract.py +207 -0
- package/skills/plan-to-pr/test_task_ticket_contract.py +151 -0
- package/skills/pr-converge/SKILL.md +472 -469
- package/skills/pr-converge/reference/examples.md +3 -3
- package/skills/pr-converge/reference/fix-protocol.md +1 -1
- package/skills/pr-converge/reference/ground-rules.md +7 -4
- package/skills/pr-converge/reference/multi-pr-orchestration.md +4 -1
- package/skills/pr-converge/reference/per-tick.md +5 -5
- package/skills/pr-converge/reference/progress-checklist.md +1 -1
- package/skills/pr-converge/scripts/check_convergence_gates.py +279 -279
- package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -507
- package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -84
- package/skills/pr-converge/test_step5_host_branch.py +1 -1
- package/skills/pr-fix-protocol/SKILL.md +1 -1
- package/skills/privacy-hygiene/SKILL.md +68 -68
- package/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
- package/skills/prototype/workflows/promotion.md +1 -1
- package/skills/release-notes-html/SKILL.md +164 -0
- package/skills/session-log/SKILL.md +1 -1
- package/skills/task-build/CLAUDE.md +8 -7
- package/skills/task-build/SKILL.md +16 -8
- package/skills/task-build/reference/tool-routing.md +19 -0
- package/rules/claude-md-orphan-file.md +0 -28
- package/rules/cleanup-command-forms.md +0 -23
- package/rules/code-reviews.md +0 -11
- package/rules/env-var-table-code-drift.md +0 -10
- package/rules/gh-body-file.md +0 -5
- package/rules/gh-paginate.md +0 -3
- package/rules/hook-prose-matches-detector.md +0 -15
- package/rules/no-historical-clutter.md +0 -26
- package/rules/no-inline-destructive-literals.md +0 -9
- package/rules/no-justification-noise.md +0 -61
- package/rules/package-inventory-stale-entry.md +0 -25
- package/rules/right-sized-engineering.md +0 -28
- package/rules/self-contained-docs.md +0 -17
- package/rules/shell-invocation-policy.md +0 -5
- package/rules/tdd.md +0 -7
- package/skills/closeout/reference/issue-body-templates.md +0 -108
|
@@ -9,6 +9,8 @@ import importlib.util
|
|
|
9
9
|
import pathlib
|
|
10
10
|
import re
|
|
11
11
|
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
12
14
|
_CONFIG_DIR = pathlib.Path(__file__).parent
|
|
13
15
|
|
|
14
16
|
SAMPLE_ROOT_KEY_HEX_LENGTH = 16
|
|
@@ -23,6 +25,10 @@ _constants_module = importlib.util.module_from_spec(_constants_spec)
|
|
|
23
25
|
_constants_spec.loader.exec_module(_constants_module)
|
|
24
26
|
|
|
25
27
|
effort_meets_threshold = _constants_module.effort_meets_threshold
|
|
28
|
+
CODE_REVIEW_ENFORCEMENT_ENV_VAR = _constants_module.CODE_REVIEW_ENFORCEMENT_ENV_VAR
|
|
29
|
+
code_review_enforcement_enabled_in_environment = (
|
|
30
|
+
_constants_module.code_review_enforcement_enabled_in_environment
|
|
31
|
+
)
|
|
26
32
|
PUSH_REQUIRED_EFFORT = _constants_module.PUSH_REQUIRED_EFFORT
|
|
27
33
|
PR_CREATE_REQUIRED_EFFORT = _constants_module.PR_CREATE_REQUIRED_EFFORT
|
|
28
34
|
GATED_PUSH_SUBCOMMANDS = _constants_module.GATED_PUSH_SUBCOMMANDS
|
|
@@ -106,3 +112,55 @@ def test_push_gate_message_names_the_push_action_and_low_effort() -> None:
|
|
|
106
112
|
|
|
107
113
|
def test_guard_message_directs_users_to_the_sanctioned_minter_flag() -> None:
|
|
108
114
|
assert SANCTIONED_STAMP_MINTER_FLAG in STAMP_DIRECTORY_GUARD_MESSAGE
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_enforcement_defaults_to_off(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
118
|
+
monkeypatch.delenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, raising=False)
|
|
119
|
+
assert code_review_enforcement_enabled_in_environment() is False
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@pytest.mark.parametrize("enabling_value", ["1", "true", "TRUE", " yes ", "on"])
|
|
123
|
+
def test_enforcement_turns_on_for_each_enabling_environment_value(
|
|
124
|
+
monkeypatch: pytest.MonkeyPatch, enabling_value: str
|
|
125
|
+
) -> None:
|
|
126
|
+
monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, enabling_value)
|
|
127
|
+
assert code_review_enforcement_enabled_in_environment() is True
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@pytest.mark.parametrize("non_enabling_value", ["0", "false", "off", "", "maybe"])
|
|
131
|
+
def test_enforcement_stays_off_for_a_non_enabling_environment_value(
|
|
132
|
+
monkeypatch: pytest.MonkeyPatch, non_enabling_value: str
|
|
133
|
+
) -> None:
|
|
134
|
+
monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, non_enabling_value)
|
|
135
|
+
assert code_review_enforcement_enabled_in_environment() is False
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _module_flag_after_a_fresh_import(
|
|
139
|
+
monkeypatch: pytest.MonkeyPatch, environment_value: str | None
|
|
140
|
+
) -> bool:
|
|
141
|
+
if environment_value is None:
|
|
142
|
+
monkeypatch.delenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, raising=False)
|
|
143
|
+
else:
|
|
144
|
+
monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, environment_value)
|
|
145
|
+
fresh_spec = importlib.util.spec_from_file_location(
|
|
146
|
+
"code_review_enforcement_constants_fresh_import",
|
|
147
|
+
_CONFIG_DIR / "code_review_enforcement_constants.py",
|
|
148
|
+
)
|
|
149
|
+
assert fresh_spec is not None
|
|
150
|
+
assert fresh_spec.loader is not None
|
|
151
|
+
fresh_module = importlib.util.module_from_spec(fresh_spec)
|
|
152
|
+
fresh_spec.loader.exec_module(fresh_module)
|
|
153
|
+
flag_value: bool = fresh_module.CODE_REVIEW_ENFORCEMENT_ENABLED
|
|
154
|
+
return flag_value
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_module_flag_turns_on_when_the_environment_asks_for_enforcement(
|
|
158
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
159
|
+
) -> None:
|
|
160
|
+
assert _module_flag_after_a_fresh_import(monkeypatch, "true") is True
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def test_module_flag_stays_off_when_the_environment_is_unset(
|
|
164
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
165
|
+
) -> None:
|
|
166
|
+
assert _module_flag_after_a_fresh_import(monkeypatch, None) is False
|
|
@@ -1,159 +1,160 @@
|
|
|
1
|
-
"""Constants for the verified-commit gate hook family.
|
|
2
|
-
|
|
3
|
-
Shared by ``verification_verdict_store.py``, ``verified_commit_gate.py``,
|
|
4
|
-
and ``verifier_verdict_minter.py`` so every tunable lives in one place.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
GIT_TIMEOUT_SECONDS = 30
|
|
10
|
-
ROOT_KEY_HEX_LENGTH = 16
|
|
11
|
-
VERDICT_JSON_INDENT = 2
|
|
12
|
-
CLAUDE_HOME_DIRECTORY_NAME = ".claude"
|
|
13
|
-
VERDICT_DIRECTORY_NAME = "verification"
|
|
14
|
-
VERDICT_DIRECTORY_NAME_SEPARATOR_PATTERN = r"['\"\\/,\s]+"
|
|
15
|
-
VERDICT_DIRECTORY_PATH_BOUNDARY_PATTERN = r"(?=['\"]*[\\/,])"
|
|
16
|
-
RELATIVE_VERDICT_DIRECTORY_PATTERN = r"(?:^|(?<=[\s;&|(='\"]))verification[\\/]"
|
|
17
|
-
VERDICT_PATH_GLUE_PATTERN = r"['\"+\\/\s]*[\\/]['\"+\\/\s]*"
|
|
18
|
-
VERDICT_DIRECTORY_CHANGE_TARGET_PATTERN = r"[ \t]+['\"]?verification[\\/]?['\"]?(?=[\s;&|]|$)"
|
|
19
|
-
VERDICT_PATH_JOINED_VARIABLE_PATTERN = r"\$\{?(\w+)\}?[\\/]|[\\/]\$\{?(\w+)\}?"
|
|
20
|
-
VERDICT_PATH_VARIABLE_ASSIGNMENT_PATTERN = r"(?:^|(?<=[\s;&|(]))%s=(\S+)"
|
|
21
|
-
VERDICT_FILE_RELATIVE_REFERENCE_PATTERN = (
|
|
22
|
-
rf"(?:^|(?<=[\s;&|(='\"\\/]))verification[\\/][0-9a-f]{{{ROOT_KEY_HEX_LENGTH}}}\.json"
|
|
23
|
-
)
|
|
24
|
-
PATH_OBFUSCATION_PRIMITIVE_PATTERN = (
|
|
25
|
-
r"chr\s*\(|bytes\.fromhex\s*\(|b64decode\s*\(|codecs\.decode\s*\("
|
|
26
|
-
r"|(?:bytes|bytearray)\s*\(\s*\[|\[char\[?\]?\]"
|
|
27
|
-
)
|
|
28
|
-
ALL_VERDICT_PATH_SEGMENT_NAMES = (".claude", "verification")
|
|
29
|
-
ALL_VERDICT_PATH_SEGMENT_BODIES = ("claude", "verification")
|
|
30
|
-
HEX_TOKEN_PATTERN = r"(?<![0-9a-fx])([0-9a-f]{6,})(?![0-9a-f])"
|
|
31
|
-
BASE64_TOKEN_PATTERN = r"[A-Za-z0-9+/]{8,}={0,2}"
|
|
32
|
-
CHARACTER_CODE_SEQUENCE_PATTERN = r"\d{1,3}(?:\s*,\s*\d{1,3})+"
|
|
33
|
-
CHR_CALL_CHAIN_PATTERN = r"chr\(\s*\d{1,3}\s*\)(?:\s*\+\s*chr\(\s*\d{1,3}\s*\))+"
|
|
34
|
-
CHR_CALL_CODE_PATTERN = r"chr\(\s*(\d{1,3})\s*\)"
|
|
35
|
-
HEX_DIGITS_PER_BYTE = 2
|
|
36
|
-
FILE_WRITE_PRIMITIVE_PATTERN = (
|
|
37
|
-
r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
38
|
-
r"|Out-File|Set-Content|Add-Content|\btee\b|>"
|
|
39
|
-
)
|
|
40
|
-
NON_REDIRECT_FILE_WRITE_PRIMITIVE_PATTERN = (
|
|
41
|
-
r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
42
|
-
r"|Out-File|Set-Content|Add-Content|\btee\b"
|
|
43
|
-
)
|
|
44
|
-
WRITE_CALL_REGION_PATTERN = (
|
|
45
|
-
r"(?:\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
46
|
-
r"|Out-File|Set-Content|Add-Content|\btee\b)[^;&|\n]*"
|
|
47
|
-
)
|
|
48
|
-
VERDICT_KEY_ALL_PASS = "all_pass"
|
|
49
|
-
VERDICT_KEY_MANIFEST_SHA256 = "manifest_sha256"
|
|
50
|
-
VERDICT_KEY_FINDINGS = "findings"
|
|
51
|
-
VERDICT_FINDING_CHECK_KEY = "check"
|
|
52
|
-
LOGS_DIRECTORY_NAME = "logs"
|
|
53
|
-
VERIFIER_VERDICTS_JSONL_FILENAME = "verifier-verdicts.jsonl"
|
|
54
|
-
LEDGER_KEY_TIMESTAMP = "timestamp"
|
|
55
|
-
LEDGER_KEY_REPO_ROOT = "repo_root"
|
|
56
|
-
LEDGER_KEY_BRANCH = "branch"
|
|
57
|
-
LEDGER_KEY_MANIFEST_HASH = "manifest_hash"
|
|
58
|
-
LEDGER_KEY_ALL_PASS = "all_pass"
|
|
59
|
-
LEDGER_KEY_FINDING_COUNT = "finding_count"
|
|
60
|
-
LEDGER_KEY_FINDING_CHECK_NAMES = "finding_check_names"
|
|
61
|
-
LEDGER_KEY_MINTED_FROM_AGENT_ID = "minted_from_agent_id"
|
|
62
|
-
VERDICT_FILE_GLOB = "*.json"
|
|
63
|
-
SUBAGENTS_DIRECTORY_NAME = "subagents"
|
|
64
|
-
AGENT_TRANSCRIPT_GLOB = "agent-*.jsonl"
|
|
65
|
-
AGENT_META_SIDECAR_SUFFIX = ".meta.json"
|
|
66
|
-
AGENT_META_TYPE_KEY = "agentType"
|
|
67
|
-
TRANSCRIPT_ENTRY_TYPE_KEY = "type"
|
|
68
|
-
TRANSCRIPT_ASSISTANT_ENTRY_TYPE = "assistant"
|
|
69
|
-
TRANSCRIPT_MESSAGE_KEY = "message"
|
|
70
|
-
TRANSCRIPT_CONTENT_KEY = "content"
|
|
71
|
-
TRANSCRIPT_CONTENT_TYPE_KEY = "type"
|
|
72
|
-
TRANSCRIPT_TEXT_CONTENT_TYPE = "text"
|
|
73
|
-
TRANSCRIPT_TEXT_KEY = "text"
|
|
74
|
-
VERDICT_FENCE_PATTERN = r"```verdict\s*\n(.*?)```"
|
|
75
|
-
MANIFEST_HASH_CLI_FLAG = "--manifest-hash"
|
|
76
|
-
MANIFEST_HASH_FOR_BRANCH_CLI_FLAG = "--manifest-hash-for-branch"
|
|
77
|
-
WORKTREE_LIST_PATH_PREFIX = "worktree "
|
|
78
|
-
WORKTREE_LIST_BRANCH_PREFIX = "branch "
|
|
79
|
-
BRANCH_REFERENCE_PREFIX = "refs/heads/"
|
|
80
|
-
EMPTY_SURFACE_GUARD_MESSAGE = (
|
|
81
|
-
"ERROR: The work tree at {repo_root} has no changed or untracked files "
|
|
82
|
-
"versus origin/main (empty change surface). This work tree holds nothing "
|
|
83
|
-
"to verify — you are pointed at the wrong work tree. Run `git worktree list` "
|
|
84
|
-
"to see all checked-out work trees and target the one on the branch under review."
|
|
85
|
-
)
|
|
86
|
-
BRANCH_WORKTREE_ABSENT_MESSAGE = (
|
|
87
|
-
"ERROR: No work tree has branch '{branch}' checked out. "
|
|
88
|
-
"Check it out in a work tree first: "
|
|
89
|
-
"`git worktree add <path> <branch>` or `git checkout <branch>`."
|
|
90
|
-
)
|
|
91
|
-
DOCS_ONLY_EXTENSIONS = frozenset(
|
|
92
|
-
{".md", ".txt", ".rst", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".ico"}
|
|
93
|
-
)
|
|
94
|
-
PYTHON_EXTENSION = ".py"
|
|
95
|
-
TEST_FILE_PREFIX = "test_"
|
|
96
|
-
TEST_FILE_SUFFIX = "_test.py"
|
|
97
|
-
CONFTEST_FILE_NAME = "conftest.py"
|
|
98
|
-
MINIMUM_STATUS_FIELD_COUNT = 2
|
|
99
|
-
ALL_FALLBACK_BASE_REFERENCES = ("origin/main", "origin/master")
|
|
100
|
-
DETACHED_HEAD_LABEL = "HEAD"
|
|
101
|
-
BRANCH_REMOTE_CONFIG_KEY_TEMPLATE = "branch.{branch_name}.remote"
|
|
102
|
-
ALL_TOOLING_STATE_PREFIXES = (
|
|
103
|
-
".claude/verification/",
|
|
104
|
-
".claude/worktrees/",
|
|
105
|
-
".claude/daemon/",
|
|
106
|
-
".claude/teams/",
|
|
107
|
-
".claude/sessions/",
|
|
108
|
-
".cursor/worktrees/",
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
)
|
|
1
|
+
"""Constants for the verified-commit gate hook family.
|
|
2
|
+
|
|
3
|
+
Shared by ``verification_verdict_store.py``, ``verified_commit_gate.py``,
|
|
4
|
+
and ``verifier_verdict_minter.py`` so every tunable lives in one place.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
GIT_TIMEOUT_SECONDS = 30
|
|
10
|
+
ROOT_KEY_HEX_LENGTH = 16
|
|
11
|
+
VERDICT_JSON_INDENT = 2
|
|
12
|
+
CLAUDE_HOME_DIRECTORY_NAME = ".claude"
|
|
13
|
+
VERDICT_DIRECTORY_NAME = "verification"
|
|
14
|
+
VERDICT_DIRECTORY_NAME_SEPARATOR_PATTERN = r"['\"\\/,\s]+"
|
|
15
|
+
VERDICT_DIRECTORY_PATH_BOUNDARY_PATTERN = r"(?=['\"]*[\\/,])"
|
|
16
|
+
RELATIVE_VERDICT_DIRECTORY_PATTERN = r"(?:^|(?<=[\s;&|(='\"]))verification[\\/]"
|
|
17
|
+
VERDICT_PATH_GLUE_PATTERN = r"['\"+\\/\s]*[\\/]['\"+\\/\s]*"
|
|
18
|
+
VERDICT_DIRECTORY_CHANGE_TARGET_PATTERN = r"[ \t]+['\"]?verification[\\/]?['\"]?(?=[\s;&|]|$)"
|
|
19
|
+
VERDICT_PATH_JOINED_VARIABLE_PATTERN = r"\$\{?(\w+)\}?[\\/]|[\\/]\$\{?(\w+)\}?"
|
|
20
|
+
VERDICT_PATH_VARIABLE_ASSIGNMENT_PATTERN = r"(?:^|(?<=[\s;&|(]))%s=(\S+)"
|
|
21
|
+
VERDICT_FILE_RELATIVE_REFERENCE_PATTERN = (
|
|
22
|
+
rf"(?:^|(?<=[\s;&|(='\"\\/]))verification[\\/][0-9a-f]{{{ROOT_KEY_HEX_LENGTH}}}\.json"
|
|
23
|
+
)
|
|
24
|
+
PATH_OBFUSCATION_PRIMITIVE_PATTERN = (
|
|
25
|
+
r"chr\s*\(|bytes\.fromhex\s*\(|b64decode\s*\(|codecs\.decode\s*\("
|
|
26
|
+
r"|(?:bytes|bytearray)\s*\(\s*\[|\[char\[?\]?\]"
|
|
27
|
+
)
|
|
28
|
+
ALL_VERDICT_PATH_SEGMENT_NAMES = (".claude", "verification")
|
|
29
|
+
ALL_VERDICT_PATH_SEGMENT_BODIES = ("claude", "verification")
|
|
30
|
+
HEX_TOKEN_PATTERN = r"(?<![0-9a-fx])([0-9a-f]{6,})(?![0-9a-f])"
|
|
31
|
+
BASE64_TOKEN_PATTERN = r"[A-Za-z0-9+/]{8,}={0,2}"
|
|
32
|
+
CHARACTER_CODE_SEQUENCE_PATTERN = r"\d{1,3}(?:\s*,\s*\d{1,3})+"
|
|
33
|
+
CHR_CALL_CHAIN_PATTERN = r"chr\(\s*\d{1,3}\s*\)(?:\s*\+\s*chr\(\s*\d{1,3}\s*\))+"
|
|
34
|
+
CHR_CALL_CODE_PATTERN = r"chr\(\s*(\d{1,3})\s*\)"
|
|
35
|
+
HEX_DIGITS_PER_BYTE = 2
|
|
36
|
+
FILE_WRITE_PRIMITIVE_PATTERN = (
|
|
37
|
+
r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
38
|
+
r"|Out-File|Set-Content|Add-Content|\btee\b|>"
|
|
39
|
+
)
|
|
40
|
+
NON_REDIRECT_FILE_WRITE_PRIMITIVE_PATTERN = (
|
|
41
|
+
r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
42
|
+
r"|Out-File|Set-Content|Add-Content|\btee\b"
|
|
43
|
+
)
|
|
44
|
+
WRITE_CALL_REGION_PATTERN = (
|
|
45
|
+
r"(?:\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
|
|
46
|
+
r"|Out-File|Set-Content|Add-Content|\btee\b)[^;&|\n]*"
|
|
47
|
+
)
|
|
48
|
+
VERDICT_KEY_ALL_PASS = "all_pass"
|
|
49
|
+
VERDICT_KEY_MANIFEST_SHA256 = "manifest_sha256"
|
|
50
|
+
VERDICT_KEY_FINDINGS = "findings"
|
|
51
|
+
VERDICT_FINDING_CHECK_KEY = "check"
|
|
52
|
+
LOGS_DIRECTORY_NAME = "logs"
|
|
53
|
+
VERIFIER_VERDICTS_JSONL_FILENAME = "verifier-verdicts.jsonl"
|
|
54
|
+
LEDGER_KEY_TIMESTAMP = "timestamp"
|
|
55
|
+
LEDGER_KEY_REPO_ROOT = "repo_root"
|
|
56
|
+
LEDGER_KEY_BRANCH = "branch"
|
|
57
|
+
LEDGER_KEY_MANIFEST_HASH = "manifest_hash"
|
|
58
|
+
LEDGER_KEY_ALL_PASS = "all_pass"
|
|
59
|
+
LEDGER_KEY_FINDING_COUNT = "finding_count"
|
|
60
|
+
LEDGER_KEY_FINDING_CHECK_NAMES = "finding_check_names"
|
|
61
|
+
LEDGER_KEY_MINTED_FROM_AGENT_ID = "minted_from_agent_id"
|
|
62
|
+
VERDICT_FILE_GLOB = "*.json"
|
|
63
|
+
SUBAGENTS_DIRECTORY_NAME = "subagents"
|
|
64
|
+
AGENT_TRANSCRIPT_GLOB = "agent-*.jsonl"
|
|
65
|
+
AGENT_META_SIDECAR_SUFFIX = ".meta.json"
|
|
66
|
+
AGENT_META_TYPE_KEY = "agentType"
|
|
67
|
+
TRANSCRIPT_ENTRY_TYPE_KEY = "type"
|
|
68
|
+
TRANSCRIPT_ASSISTANT_ENTRY_TYPE = "assistant"
|
|
69
|
+
TRANSCRIPT_MESSAGE_KEY = "message"
|
|
70
|
+
TRANSCRIPT_CONTENT_KEY = "content"
|
|
71
|
+
TRANSCRIPT_CONTENT_TYPE_KEY = "type"
|
|
72
|
+
TRANSCRIPT_TEXT_CONTENT_TYPE = "text"
|
|
73
|
+
TRANSCRIPT_TEXT_KEY = "text"
|
|
74
|
+
VERDICT_FENCE_PATTERN = r"```verdict\s*\n(.*?)```"
|
|
75
|
+
MANIFEST_HASH_CLI_FLAG = "--manifest-hash"
|
|
76
|
+
MANIFEST_HASH_FOR_BRANCH_CLI_FLAG = "--manifest-hash-for-branch"
|
|
77
|
+
WORKTREE_LIST_PATH_PREFIX = "worktree "
|
|
78
|
+
WORKTREE_LIST_BRANCH_PREFIX = "branch "
|
|
79
|
+
BRANCH_REFERENCE_PREFIX = "refs/heads/"
|
|
80
|
+
EMPTY_SURFACE_GUARD_MESSAGE = (
|
|
81
|
+
"ERROR: The work tree at {repo_root} has no changed or untracked files "
|
|
82
|
+
"versus origin/main (empty change surface). This work tree holds nothing "
|
|
83
|
+
"to verify — you are pointed at the wrong work tree. Run `git worktree list` "
|
|
84
|
+
"to see all checked-out work trees and target the one on the branch under review."
|
|
85
|
+
)
|
|
86
|
+
BRANCH_WORKTREE_ABSENT_MESSAGE = (
|
|
87
|
+
"ERROR: No work tree has branch '{branch}' checked out. "
|
|
88
|
+
"Check it out in a work tree first: "
|
|
89
|
+
"`git worktree add <path> <branch>` or `git checkout <branch>`."
|
|
90
|
+
)
|
|
91
|
+
DOCS_ONLY_EXTENSIONS = frozenset(
|
|
92
|
+
{".md", ".txt", ".rst", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".ico"}
|
|
93
|
+
)
|
|
94
|
+
PYTHON_EXTENSION = ".py"
|
|
95
|
+
TEST_FILE_PREFIX = "test_"
|
|
96
|
+
TEST_FILE_SUFFIX = "_test.py"
|
|
97
|
+
CONFTEST_FILE_NAME = "conftest.py"
|
|
98
|
+
MINIMUM_STATUS_FIELD_COUNT = 2
|
|
99
|
+
ALL_FALLBACK_BASE_REFERENCES = ("origin/main", "origin/master")
|
|
100
|
+
DETACHED_HEAD_LABEL = "HEAD"
|
|
101
|
+
BRANCH_REMOTE_CONFIG_KEY_TEMPLATE = "branch.{branch_name}.remote"
|
|
102
|
+
ALL_TOOLING_STATE_PREFIXES = (
|
|
103
|
+
".claude/verification/",
|
|
104
|
+
".claude/worktrees/",
|
|
105
|
+
".claude/daemon/",
|
|
106
|
+
".claude/teams/",
|
|
107
|
+
".claude/sessions/",
|
|
108
|
+
".cursor/worktrees/",
|
|
109
|
+
".claude-plugin-data/",
|
|
110
|
+
)
|
|
111
|
+
GATED_GIT_SUBCOMMANDS = frozenset({"commit", "push"})
|
|
112
|
+
ALL_GIT_BINARY_NAMES = frozenset({"git", "git.exe"})
|
|
113
|
+
VALUE_TAKING_GIT_OPTIONS = frozenset({"-C", "-c", "--git-dir", "--work-tree", "--namespace"})
|
|
114
|
+
REPO_DIRECTORY_OPTION = "-C"
|
|
115
|
+
WORK_TREE_OPTION = "--work-tree"
|
|
116
|
+
DIRECTORY_CHANGE_VERBS = frozenset({"cd", "pushd", "set-location", "sl"})
|
|
117
|
+
DIRECTORY_CHANGE_PATH_OPTIONS = frozenset({"-path", "-literalpath"})
|
|
118
|
+
DIRECTORY_CHANGE_OPTION_TERMINATOR = "--"
|
|
119
|
+
DIRECTORY_CHANGE_PATTERN_PREFIX = r"(?:^|(?<=[\s;&|(]))(?:"
|
|
120
|
+
DIRECTORY_CHANGE_PATTERN_SUFFIX = r")(?=\s|$)"
|
|
121
|
+
DIRECTORY_CHANGE_OPTION_PREFIX_PATTERN = r"(?:[ \t]+(?:%s)(?=\s|$))*"
|
|
122
|
+
DIRECTORY_CHANGE_TARGET_PATTERN = r"[ \t]+['\"]?\S*"
|
|
123
|
+
CLAUDE_HOME_TARGET_BOUNDARY_PATTERN = r"[\\/]?['\"]?(?=[\s;&|]|$)"
|
|
124
|
+
VERDICT_DIRECTORY_TARGET_BOUNDARY_PATTERN = r"[\\/]?['\"]?(?=[\s;&|]|$)"
|
|
125
|
+
COMMAND_AFTER_DIRECTORY_CHANGE_PATTERN = r"[;&|\n][\s]*\S"
|
|
126
|
+
OPTION_WITH_VALUE_STEP = 2
|
|
127
|
+
ALL_GATED_TOOL_NAMES = ("Bash", "PowerShell")
|
|
128
|
+
HASH_PREVIEW_LENGTH = 16
|
|
129
|
+
VERIFICATION_BYPASS_MARKER = "# verify-skip"
|
|
130
|
+
MINTING_AGENT_TYPE = "code-verifier"
|
|
131
|
+
VERDICT_DIRECTORY_GUARD_MESSAGE = (
|
|
132
|
+
"BLOCKED: [VERDICT_DIRECTORY_GUARD] Shell access to the verification "
|
|
133
|
+
"verdict directory (~/.claude/verification/) is denied. Only the "
|
|
134
|
+
"verifier_verdict_minter.py SubagentStop hook writes verdict files; a "
|
|
135
|
+
"shell write here would forge a passing verdict and defeat the "
|
|
136
|
+
"verified-commit gate. Spawn the code-verifier agent to earn a verdict "
|
|
137
|
+
"instead of writing one."
|
|
138
|
+
)
|
|
139
|
+
CORRECTIVE_MESSAGE = (
|
|
140
|
+
"BLOCKED: [VERIFIED_COMMIT_GATE] This branch surface has no passing "
|
|
141
|
+
"verification verdict. Clear commit-committability gates first "
|
|
142
|
+
"(CODE_RULES on changed lines and merge conflicts vs base — the "
|
|
143
|
+
"code_verifier_spawn_preflight_gate enforces these on the spawn). If a "
|
|
144
|
+
"prior commit failed on CODE_RULES or staging, fix those before "
|
|
145
|
+
"re-verifying. Then spawn the code-verifier agent (Agent or Task tool, "
|
|
146
|
+
"subagent_type 'code-verifier') with the task texts, the diff scope, "
|
|
147
|
+
"and recorded baselines; when it finishes with a clean verdict the "
|
|
148
|
+
"SubagentStop hook mints the verdict and this command will pass. Any "
|
|
149
|
+
"file change after verification invalidates the verdict, so verify "
|
|
150
|
+
"last only after commit gates are green. The verdict binds to the exact "
|
|
151
|
+
"surface content (every changed and untracked file's bytes), not to a "
|
|
152
|
+
"work-tree path, so a commit from a different work tree passes only "
|
|
153
|
+
"when its surface is byte-identical; a work tree carrying any extra or "
|
|
154
|
+
"later edit has a surface no verdict covers. To land this change, run "
|
|
155
|
+
"this command from the work tree that holds the verified surface, or "
|
|
156
|
+
"verify this surface here. Exempt automatically: docs/image files, "
|
|
157
|
+
"pytest test files, and "
|
|
158
|
+
"Python files whose docstring- and comment-stripped AST is unchanged "
|
|
159
|
+
"(comment-only edits in non-Python files are not exempt)."
|
|
160
|
+
)
|