claude-dev-env 2.18.0 → 2.20.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/skills/AGENTS.md +4 -4
- package/.agents/skills/_shared/AGENTS.md +1 -0
- package/.agents/skills/_shared/pr-loop/AGENTS.md +1 -0
- package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +119 -0
- package/.agents/skills/_shared/pr-loop/preflight-proposal.md +5 -0
- package/.agents/skills/e-code-review/SKILL.md +12 -1
- package/.agents/skills/e-code-review/reference/fix.md +5 -1
- package/.agents/skills/e-code-review/reference/loop.md +4 -0
- package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +66 -0
- package/.agents/skills/e-code-review/reference/preflight-proposal.md +40 -0
- package/.agents/skills/e-code-review/reference/runner-selection.md +1 -0
- package/.agents/skills/pr-cleanup/SKILL.md +105 -75
- package/.agents/skills/pr-cleanup/reference/process-inventory.md +15 -0
- package/.agents/skills/pr-cleanup/reference/task-seeds.md +20 -0
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/SKILL.md +18 -12
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/offense-examples.md +1 -1
- package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/task-seeds.md +3 -2
- package/.agents/skills/pr-refinement/SKILL.md +31 -0
- package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/SKILL.md +24 -7
- package/.agents/skills/{small-cl → pr-small-cl}/SKILL.md +1 -1
- package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +33 -5
- package/.agents/skills/skill-builder/SKILL.md +1 -0
- package/.agents/skills-archived/bugteam/SKILL.md +1 -1
- package/.agents/skills-archived/bugteam/test_skill_additions.py +1 -1
- package/.agents/skills-archived/comments/SKILL.md +1 -1
- package/.agents/skills-archived/descriptions/SKILL.md +1 -1
- package/.agents/skills-archived/reviews/SKILL.md +1 -1
- package/AGENTS.md +1 -1
- package/_shared/pr-loop/AGENTS.md +2 -1
- package/_shared/pr-loop/preflight-proposal.md +56 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +29 -6
- package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_arguments.py +15 -3
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +47 -4
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +4 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +47 -0
- package/bin/ever-shipped-skills.mjs +14 -0
- package/bin/install-constants.mjs +5 -0
- package/bin/install.agents-home.test.mjs +23 -0
- package/bin/install.codex-rules.test.mjs +61 -6
- package/bin/install.mjs +57 -9
- package/bin/install.prune.test.mjs +65 -3
- package/bin/install.test.mjs +202 -2
- package/docs/CODE_RULES.md +6 -0
- package/hooks/advisory/conftest.py +10 -0
- package/hooks/advisory/migration_safety_advisor.py +14 -14
- package/hooks/advisory/refactor_guard.py +250 -144
- package/hooks/advisory/refactor_guard_test_support.py +46 -0
- package/hooks/advisory/test_migration_safety_advisor.py +120 -0
- package/hooks/advisory/test_refactor_guard_advisory.py +171 -0
- package/hooks/advisory/test_refactor_guard_eligibility.py +166 -0
- package/hooks/atomic_file_writer.py +81 -0
- package/hooks/blocking/AGENTS.md +2 -1
- package/hooks/blocking/block_main_commit.py +66 -33
- package/hooks/blocking/code_rules_banned_identifiers.py +55 -4
- package/hooks/blocking/code_rules_blast_radius.py +194 -0
- package/hooks/blocking/code_rules_enforcer.py +12 -0
- package/hooks/blocking/code_rules_enforcer_test_support.py +92 -0
- package/hooks/blocking/destructive_command_blocker.py +8 -7
- package/hooks/blocking/pre_tool_use_dispatcher.py +11 -7
- package/hooks/blocking/precommit_code_rules_gate.py +14 -139
- package/hooks/blocking/sensitive_file_protector.py +8 -6
- package/hooks/blocking/session_edit_stage_gate.py +31 -1
- package/hooks/blocking/test_block_main_commit.py +145 -0
- package/hooks/blocking/test_claude_md_orphan_file_blocker.py +171 -1
- package/hooks/blocking/test_code_rules_blast_radius.py +161 -0
- package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +37 -12
- package/hooks/blocking/test_code_rules_enforcer_banned_noun_word.py +54 -0
- package/hooks/blocking/test_code_rules_enforcer_duplicate_body_hook_routing.py +15 -53
- package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +13 -62
- package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +309 -0
- package/hooks/blocking/test_code_rules_enforcer_precheck_forecast.py +14 -71
- package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +14 -16
- package/hooks/blocking/test_code_rules_enforcer_split_entry_2.py +31 -46
- package/hooks/blocking/test_code_rules_enforcer_stage.py +192 -0
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +13 -59
- package/hooks/blocking/test_destructive_command_blocker.py +154 -138
- package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +85 -25
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +58 -38
- package/hooks/blocking/test_destructive_command_blocker_patterns.py +133 -0
- package/hooks/blocking/test_docstring_rule_gate_count_blocker.py +113 -1
- package/hooks/blocking/test_env_var_table_code_drift_blocker.py +70 -3
- package/hooks/blocking/test_hook_subprocess_support.py +296 -0
- package/hooks/blocking/test_package_inventory_stale_blocker.py +1 -1
- package/hooks/blocking/test_pii_scanner.py +81 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +32 -3
- package/hooks/blocking/test_precommit_code_rules_gate.py +11 -16
- package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +234 -0
- package/hooks/blocking/test_pytest_testpaths_orphan_blocker.py +25 -18
- package/hooks/blocking/test_sensitive_file_protector.py +145 -5
- package/hooks/blocking/test_session_edit_stage_gate_staging.py +64 -0
- package/hooks/blocking/test_session_edit_stage_gate_support.py +204 -0
- package/hooks/blocking/test_session_edit_stage_gate_tracker.py +116 -0
- package/hooks/blocking/test_shared_stdin_adoption.py +31 -20
- package/hooks/blocking/test_test_preflight_check.py +80 -0
- package/hooks/git-hooks/AGENTS.md +1 -1
- package/hooks/git-hooks/git_hooks_constants/__init__.py +1 -0
- package/hooks/git-hooks/post_commit.py +160 -51
- package/hooks/git-hooks/pre_commit.py +9 -5
- package/hooks/git-hooks/test_post_commit.py +203 -0
- package/hooks/git-hooks/test_pre_commit.py +2 -2
- package/hooks/git-hooks/test_pre_push.py +57 -0
- package/hooks/hooks_constants/AGENTS.md +3 -1
- package/hooks/hooks_constants/atomic_file_writer_constants.py +4 -0
- package/hooks/hooks_constants/banned_identifiers_constants.py +1 -0
- package/hooks/hooks_constants/blast_radius_constants.py +14 -0
- package/hooks/hooks_constants/destructive_command_environment_constants.py +18 -0
- package/hooks/hooks_constants/destructive_command_segment_constants.py +1 -11
- package/hooks/hooks_constants/hardcoded_user_path_constants.py +9 -3
- package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +1 -1
- package/hooks/hooks_constants/refactor_guard_constants.py +75 -0
- package/hooks/hooks_constants/sensitive_file_protector_constants.py +2 -4
- package/hooks/hooks_constants/test_refactor_guard_constants.py +21 -0
- package/hooks/json_file_reader.py +22 -0
- package/hooks/observability/test_instructions_loaded_logger.py +54 -0
- package/hooks/pending_sidecars.py +33 -0
- package/hooks/session/test_plugin_data_dir_cleanup.py +70 -0
- package/hooks/session/test_session_edit_tracker_cleanup.py +16 -3
- package/hooks/test_atomic_file_writer.py +73 -0
- package/hooks/test_json_file_reader.py +24 -0
- package/hooks/test_pending_sidecars.py +25 -0
- package/hooks/validation/mypy_validator.py +213 -80
- package/hooks/validation/test_mypy_validator.py +288 -13
- package/hooks/workflow/auto_formatter.py +225 -93
- package/hooks/workflow/investigation_tracker_reset.py +2 -0
- package/hooks/workflow/test_auto_formatter.py +261 -12
- package/hooks/workflow/test_investigation_tracker_reset.py +90 -0
- package/package.json +1 -1
- package/rules/failure-blast-radius.md +126 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/fetch-commands.md +0 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/report-template.md +0 -0
- /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/rule-checklist.md +0 -0
- /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/examples.md +0 -0
- /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/offense-taxonomy.md +0 -0
|
@@ -14,16 +14,12 @@ the target path the same way it would for the real directory.
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
import contextlib
|
|
18
|
-
import io
|
|
19
17
|
import json
|
|
20
18
|
import pathlib
|
|
21
19
|
import shutil
|
|
22
|
-
import subprocess
|
|
23
20
|
import sys
|
|
24
21
|
import tempfile
|
|
25
22
|
from collections.abc import Iterator
|
|
26
|
-
from types import SimpleNamespace
|
|
27
23
|
|
|
28
24
|
import pytest
|
|
29
25
|
|
|
@@ -35,10 +31,10 @@ if str(_HOOKS_PARENT) not in sys.path:
|
|
|
35
31
|
sys.path.insert(0, str(_HOOKS_PARENT))
|
|
36
32
|
|
|
37
33
|
from code_rules_enforcer import main # noqa: E402
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
from code_rules_enforcer_test_support import ( # noqa: E402
|
|
35
|
+
run_precheck,
|
|
36
|
+
run_write_entrypoint,
|
|
37
|
+
)
|
|
42
38
|
|
|
43
39
|
PASS_THROUGH_ALIAS_SOURCE = (
|
|
44
40
|
"def find_bare_path_segments(content: str) -> set[str]:\n"
|
|
@@ -62,39 +58,8 @@ def hook_blocking_dir() -> Iterator[pathlib.Path]:
|
|
|
62
58
|
shutil.rmtree(base_directory, ignore_errors=False)
|
|
63
59
|
|
|
64
60
|
|
|
65
|
-
def _run_main_with_write_payload(
|
|
66
|
-
file_path: str,
|
|
67
|
-
content: str,
|
|
68
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
69
|
-
capsys: pytest.CaptureFixture[str],
|
|
70
|
-
) -> str:
|
|
71
|
-
"""Drive ``main()`` through its stdin entry point for a Write and return stdout.
|
|
72
|
-
|
|
73
|
-
Args:
|
|
74
|
-
file_path: The on-disk path the Write targets.
|
|
75
|
-
content: The whole-file body the Write would create.
|
|
76
|
-
monkeypatch: The fixture used to redirect ``sys.stdin``.
|
|
77
|
-
capsys: The fixture used to capture the deny payload on stdout.
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
The captured stdout, which holds the deny payload when violations fire.
|
|
81
|
-
"""
|
|
82
|
-
write_payload = json.dumps(
|
|
83
|
-
{
|
|
84
|
-
"tool_name": "Write",
|
|
85
|
-
"tool_input": {"file_path": file_path, "content": content},
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
monkeypatch.setattr(code_rules_enforcer.sys, "stdin", io.StringIO(write_payload))
|
|
89
|
-
with contextlib.suppress(SystemExit):
|
|
90
|
-
code_rules_enforcer.main([])
|
|
91
|
-
return capsys.readouterr().out
|
|
92
|
-
|
|
93
|
-
|
|
94
61
|
def test_write_of_pass_through_alias_into_hook_directory_denies(
|
|
95
62
|
hook_blocking_dir: pathlib.Path,
|
|
96
|
-
monkeypatch: pytest.MonkeyPatch,
|
|
97
|
-
capsys: pytest.CaptureFixture[str],
|
|
98
63
|
) -> None:
|
|
99
64
|
"""A Write that introduces a pass-through alias into a hook file is denied.
|
|
100
65
|
|
|
@@ -103,14 +68,16 @@ def test_write_of_pass_through_alias_into_hook_directory_denies(
|
|
|
103
68
|
directory its docstring names as the motivating case — at the PreToolUse Write
|
|
104
69
|
point, not only through ``validate_content``."""
|
|
105
70
|
new_file = hook_blocking_dir / "new_blocker.py"
|
|
106
|
-
|
|
107
|
-
|
|
71
|
+
captured_stdout, _exit_code = run_write_entrypoint(
|
|
72
|
+
main,
|
|
73
|
+
str(new_file),
|
|
74
|
+
PASS_THROUGH_ALIAS_SOURCE,
|
|
108
75
|
)
|
|
109
|
-
assert
|
|
76
|
+
assert captured_stdout != "", (
|
|
110
77
|
"A pass-through alias written into a hook-infrastructure file must produce "
|
|
111
78
|
"a deny payload, got empty stdout"
|
|
112
79
|
)
|
|
113
|
-
deny_payload = json.loads(
|
|
80
|
+
deny_payload = json.loads(captured_stdout)
|
|
114
81
|
decision = deny_payload["hookSpecificOutput"]["permissionDecision"]
|
|
115
82
|
reason = deny_payload["hookSpecificOutput"]["permissionDecisionReason"]
|
|
116
83
|
assert decision == "deny", f"expected deny, got: {decision!r}"
|
|
@@ -121,31 +88,18 @@ def test_write_of_pass_through_alias_into_hook_directory_denies(
|
|
|
121
88
|
|
|
122
89
|
def test_precheck_of_pass_through_alias_at_hook_target_exits_nonzero(
|
|
123
90
|
hook_blocking_dir: pathlib.Path,
|
|
124
|
-
|
|
91
|
+
tmp_path: pathlib.Path,
|
|
125
92
|
) -> None:
|
|
126
93
|
"""The pre-check CLI flags a pass-through alias judged at a hook-infrastructure target.
|
|
127
94
|
|
|
128
95
|
Driving the real ``--check`` argv path proves the gate's pre-check mode also
|
|
129
96
|
routes a hook ``.py`` target through the zero-payload-alias check rather than
|
|
130
97
|
exiting clean on the blanket hook-infrastructure exemption."""
|
|
131
|
-
staging_directory =
|
|
98
|
+
staging_directory = tmp_path
|
|
132
99
|
candidate_file = staging_directory / "candidate.py"
|
|
133
100
|
candidate_file.write_text(PASS_THROUGH_ALIAS_SOURCE, encoding="utf-8")
|
|
134
101
|
target_path = str(hook_blocking_dir / "new_blocker.py")
|
|
135
|
-
completed =
|
|
136
|
-
[
|
|
137
|
-
sys.executable,
|
|
138
|
-
str(_ENFORCER_SCRIPT_PATH),
|
|
139
|
-
"--check",
|
|
140
|
-
str(candidate_file),
|
|
141
|
-
"--as",
|
|
142
|
-
target_path,
|
|
143
|
-
],
|
|
144
|
-
input="",
|
|
145
|
-
capture_output=True,
|
|
146
|
-
text=True,
|
|
147
|
-
check=False,
|
|
148
|
-
)
|
|
102
|
+
completed = run_precheck(candidate_file, target_path, None)
|
|
149
103
|
assert completed.returncode == 1, (
|
|
150
104
|
"a pass-through alias at a hook target must exit nonzero, got: "
|
|
151
105
|
f"{completed.returncode}, stdout: {completed.stdout!r}, "
|