claude-dev-env 1.59.0 → 1.60.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/audit-rubrics/category_rubrics/category-b-selector-engine-compat.md +1 -1
- package/audit-rubrics/category_rubrics/category-e-dead-code.md +1 -0
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
- package/audit-rubrics/prompts/category-b-selector-engine-compat.md +2 -2
- package/hooks/blocking/code_rules_dead_module_constant.py +321 -0
- package/hooks/blocking/code_rules_duplicate_body.py +152 -0
- package/hooks/blocking/code_rules_enforcer.py +30 -15
- package/hooks/blocking/code_rules_typeddict_stub.py +172 -0
- package/hooks/blocking/config/__init__.py +5 -0
- package/hooks/blocking/config/verified_commit_constants.py +106 -0
- package/hooks/blocking/test_code_rules_enforcer_cross_skill_duplicate.py +146 -0
- package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +188 -0
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias.py +415 -0
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +156 -0
- package/hooks/blocking/test_verdict_directory_write_blocker.py +720 -0
- package/hooks/blocking/test_verification_verdict_store.py +278 -0
- package/hooks/blocking/test_verified_commit_gate.py +368 -0
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -0
- package/hooks/blocking/test_verifier_verdict_minter.py +214 -0
- package/hooks/blocking/verdict_directory_write_blocker.py +667 -0
- package/hooks/blocking/verification_verdict_store.py +446 -0
- package/hooks/blocking/verified_commit_gate.py +523 -0
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +152 -0
- package/hooks/blocking/verifier_verdict_minter.py +299 -0
- package/hooks/diagnostic/test_hook_log_extractor.py +3 -3
- package/hooks/hooks.json +43 -1
- package/hooks/hooks_constants/blocking_check_limits.py +1 -0
- package/hooks/hooks_constants/dead_module_constant_constants.py +20 -0
- package/hooks/hooks_constants/duplicate_function_body_constants.py +22 -5
- package/hooks/hooks_constants/precommit_code_rules_gate_constants.py +1 -1
- package/package.json +1 -1
- package/rules/file-global-constants.md +7 -1
- package/rules/no-cross-skill-duplicate-helpers.md +29 -0
- package/skills/_shared/pr-loop/scripts/preflight_worktree.py +392 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +70 -0
- package/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +263 -0
- package/skills/autoconverge/SKILL.md +54 -17
- package/skills/autoconverge/reference/closing-report.md +59 -17
- package/skills/autoconverge/workflow/aggregate_runs.py +371 -0
- package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +193 -76
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +76 -0
- package/skills/autoconverge/workflow/converge.contract.test.mjs +206 -206
- package/skills/autoconverge/workflow/converge.mjs +128 -6
- package/skills/autoconverge/workflow/convergence_summary.py +110 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +2 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +7 -0
- package/skills/autoconverge/workflow/render_report.py +488 -397
- package/skills/autoconverge/workflow/test_aggregate_runs.py +134 -0
- package/skills/autoconverge/workflow/test_convergence_summary.py +132 -0
- package/skills/autoconverge/workflow/test_render_report.py +488 -259
- package/skills/pr-converge/reference/per-tick.md +28 -8
- package/skills/rebase/SKILL.md +2 -4
- package/system-prompts/software-engineer.xml +2 -6
- package/hooks/blocking/content_search_to_zoekt_redirector.py +0 -59
- package/hooks/blocking/content_search_zoekt_bash_block_reason.py +0 -25
- package/hooks/blocking/content_search_zoekt_block_payload.py +0 -21
- package/hooks/blocking/content_search_zoekt_indexed_paths.py +0 -24
- package/hooks/blocking/content_search_zoekt_indexed_roots_config.py +0 -131
- package/hooks/blocking/content_search_zoekt_redirect_guidance.py +0 -52
- package/hooks/blocking/test_content_search_to_zoekt_redirector_integration.py +0 -61
- package/hooks/blocking/test_content_search_to_zoekt_redirector_unit.py +0 -92
- package/hooks/blocking/test_content_search_zoekt_indexed_roots_config.py +0 -102
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Entry-point tests proving the zero-payload-alias check guards hook-infrastructure files.
|
|
2
|
+
|
|
3
|
+
A pass-through alias inside a hook module is the motivating case for the
|
|
4
|
+
zero-payload-alias check, so the deny must fire on the same PreToolUse path a
|
|
5
|
+
live Write into ``packages/claude-dev-env/hooks/blocking`` would take — not only
|
|
6
|
+
through ``validate_content``, which hook files never reach at PreToolUse. These
|
|
7
|
+
tests drive the real ``main()`` stdin entry point and the pre-check CLI with a
|
|
8
|
+
hook-infrastructure target.
|
|
9
|
+
|
|
10
|
+
Each test builds a temporary tree whose tail mirrors a production hook directory
|
|
11
|
+
(``packages/claude-dev-env/hooks/blocking``) so ``is_hook_infrastructure`` matches
|
|
12
|
+
the target path the same way it would for the real directory.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import contextlib
|
|
18
|
+
import io
|
|
19
|
+
import json
|
|
20
|
+
import pathlib
|
|
21
|
+
import shutil
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
import tempfile
|
|
25
|
+
from collections.abc import Iterator
|
|
26
|
+
from types import SimpleNamespace
|
|
27
|
+
|
|
28
|
+
import pytest
|
|
29
|
+
|
|
30
|
+
_HOOK_DIRECTORY = pathlib.Path(__file__).resolve().parent
|
|
31
|
+
_HOOKS_PARENT = _HOOK_DIRECTORY.parent
|
|
32
|
+
if str(_HOOK_DIRECTORY) not in sys.path:
|
|
33
|
+
sys.path.insert(0, str(_HOOK_DIRECTORY))
|
|
34
|
+
if str(_HOOKS_PARENT) not in sys.path:
|
|
35
|
+
sys.path.insert(0, str(_HOOKS_PARENT))
|
|
36
|
+
|
|
37
|
+
from code_rules_enforcer import main # noqa: E402
|
|
38
|
+
|
|
39
|
+
code_rules_enforcer = SimpleNamespace(main=main, sys=sys)
|
|
40
|
+
|
|
41
|
+
_ENFORCER_SCRIPT_PATH = _HOOK_DIRECTORY / "code_rules_enforcer.py"
|
|
42
|
+
|
|
43
|
+
PASS_THROUGH_ALIAS_SOURCE = (
|
|
44
|
+
"def find_bare_path_segments(content: str) -> set[str]:\n"
|
|
45
|
+
" return {part for part in content.split() if part}\n"
|
|
46
|
+
"\n"
|
|
47
|
+
"def find_bare_index_segments(content: str) -> set[str]:\n"
|
|
48
|
+
" return find_bare_path_segments(content)\n"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
_HOOK_INFRASTRUCTURE_TAIL = pathlib.Path("packages") / "claude-dev-env" / "hooks" / "blocking"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.fixture
|
|
55
|
+
def hook_blocking_dir() -> Iterator[pathlib.Path]:
|
|
56
|
+
base_directory = pathlib.Path(tempfile.mkdtemp())
|
|
57
|
+
blocking_directory = base_directory / _HOOK_INFRASTRUCTURE_TAIL
|
|
58
|
+
blocking_directory.mkdir(parents=True)
|
|
59
|
+
try:
|
|
60
|
+
yield blocking_directory
|
|
61
|
+
finally:
|
|
62
|
+
shutil.rmtree(base_directory, ignore_errors=False)
|
|
63
|
+
|
|
64
|
+
|
|
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
|
+
def test_write_of_pass_through_alias_into_hook_directory_denies(
|
|
95
|
+
hook_blocking_dir: pathlib.Path,
|
|
96
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
97
|
+
capsys: pytest.CaptureFixture[str],
|
|
98
|
+
) -> None:
|
|
99
|
+
"""A Write that introduces a pass-through alias into a hook file is denied.
|
|
100
|
+
|
|
101
|
+
The target lives under a hook-infrastructure path the full code-rules suite
|
|
102
|
+
exempts, so this proves the zero-payload-alias check still fires on the exact
|
|
103
|
+
directory its docstring names as the motivating case — at the PreToolUse Write
|
|
104
|
+
point, not only through ``validate_content``."""
|
|
105
|
+
new_file = hook_blocking_dir / "new_blocker.py"
|
|
106
|
+
stdout = _run_main_with_write_payload(
|
|
107
|
+
str(new_file), PASS_THROUGH_ALIAS_SOURCE, monkeypatch, capsys
|
|
108
|
+
)
|
|
109
|
+
assert stdout != "", (
|
|
110
|
+
"A pass-through alias written into a hook-infrastructure file must produce "
|
|
111
|
+
"a deny payload, got empty stdout"
|
|
112
|
+
)
|
|
113
|
+
deny_payload = json.loads(stdout)
|
|
114
|
+
decision = deny_payload["hookSpecificOutput"]["permissionDecision"]
|
|
115
|
+
reason = deny_payload["hookSpecificOutput"]["permissionDecisionReason"]
|
|
116
|
+
assert decision == "deny", f"expected deny, got: {decision!r}"
|
|
117
|
+
assert "find_bare_index_segments" in reason, (
|
|
118
|
+
f"the deny reason must name the pass-through alias, got: {reason!r}"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_precheck_of_pass_through_alias_at_hook_target_exits_nonzero(
|
|
123
|
+
hook_blocking_dir: pathlib.Path,
|
|
124
|
+
tmp_path_factory: pytest.TempPathFactory,
|
|
125
|
+
) -> None:
|
|
126
|
+
"""The pre-check CLI flags a pass-through alias judged at a hook-infrastructure target.
|
|
127
|
+
|
|
128
|
+
Driving the real ``--check`` argv path proves the gate's pre-check mode also
|
|
129
|
+
routes a hook ``.py`` target through the zero-payload-alias check rather than
|
|
130
|
+
exiting clean on the blanket hook-infrastructure exemption."""
|
|
131
|
+
staging_directory = tmp_path_factory.mktemp("staging")
|
|
132
|
+
candidate_file = staging_directory / "candidate.py"
|
|
133
|
+
candidate_file.write_text(PASS_THROUGH_ALIAS_SOURCE, encoding="utf-8")
|
|
134
|
+
target_path = str(hook_blocking_dir / "new_blocker.py")
|
|
135
|
+
completed = subprocess.run(
|
|
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
|
+
)
|
|
149
|
+
assert completed.returncode == 1, (
|
|
150
|
+
"a pass-through alias at a hook target must exit nonzero, got: "
|
|
151
|
+
f"{completed.returncode}, stdout: {completed.stdout!r}, "
|
|
152
|
+
f"stderr: {completed.stderr!r}"
|
|
153
|
+
)
|
|
154
|
+
assert "find_bare_index_segments" in completed.stdout, (
|
|
155
|
+
f"the pre-check must name the pass-through alias, got: {completed.stdout!r}"
|
|
156
|
+
)
|