claude-dev-env 2.29.0 → 2.30.1
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 +21 -6
- package/.agents/agents/reference/README.md +6 -0
- package/.agents/agents/reference/pr-description-illustrative-voice.md +45 -0
- package/.agents/agents/reference/pr-description-verification.md +19 -0
- package/.agents/agents/test_pr_description_writer_style.py +47 -0
- package/.agents/skills/e-simplify/SKILL.md +20 -8
- package/_shared/pr-loop/code-rules-gate.md +1 -1
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -2
- package/_shared/pr-loop/scripts/code_rules_gate_parts/enforcer_loading.py +8 -8
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_enforcer_loading.py +2 -2
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +1 -1
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +15 -15
- package/docs/CODE_RULES.md +10 -0
- package/hooks/blocking/code_rules_enforcer.py +435 -318
- package/hooks/blocking/shell_substitution_blocker.py +106 -30
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +14 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_noun_word.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_class_docstring_methods.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dispatch_wiring.py +117 -22
- package/hooks/blocking/test_code_rules_enforcer_docstring_args_signature.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_docstring_unreferenced_param.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_fstring_scan.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_ignored_must_check_return.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_join_separator_magic.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_js_returns_object.py +3 -3
- package/hooks/blocking/test_code_rules_enforcer_module_docstring_roster.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_naming_pattern.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +117 -38
- package/hooks/blocking/test_code_rules_enforcer_output_snapshot.py +121 -0
- package/hooks/blocking/test_code_rules_enforcer_precheck_forecast.py +17 -15
- package/hooks/blocking/test_code_rules_enforcer_split_entry_1.py +4 -2
- package/hooks/blocking/test_code_rules_enforcer_split_entry_2.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_stage.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_string_magic.py +4 -4
- package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +2 -2
- package/hooks/blocking/test_code_rules_validation_phase.py +332 -0
- package/hooks/blocking/test_fable_spawn_gate.py +1 -1
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +26 -11
- package/hooks/blocking/test_shell_substitution_blocker.py +69 -0
- package/hooks/hooks.json +1 -1
- package/hooks/hooks_constants/code_rules_enforcer_constants.py +7 -0
- package/hooks/hooks_constants/shell_substitution_blocker_constants.py +4 -1
- package/hooks/hooks_constants/task_tool_prompt_constants.py +13 -0
- package/hooks/hooks_constants/test_code_rules_enforcer_constants.py +12 -0
- package/hooks/hooks_constants/validation_phase_constants.py +34 -0
- package/hooks/session/task_tool_prompt.py +37 -0
- package/hooks/session/test_task_tool_prompt.py +65 -0
- package/hooks/validators/README.md +1 -1
- package/hooks/validators/config/hook_timing_harness_constants.py +16 -0
- package/hooks/validators/hook_timing_harness.py +287 -0
- package/hooks/validators/test_hook_timing_harness.py +251 -0
- package/package.json +1 -1
- package/hooks/hooks_constants/task_list_loop_starter_constants.py +0 -19
- package/hooks/session/task_list_loop_starter.py +0 -45
- package/hooks/session/test_task_list_loop_starter.py +0 -63
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""SessionStart hook — start a task-list maintenance loop for the session.
|
|
3
|
-
|
|
4
|
-
At session start this hook emits an ``additionalContext`` directive asking Claude
|
|
5
|
-
to keep the session's task list current on a 10-minute cadence. Claude reuses the
|
|
6
|
-
active ``/loop`` skill when available and starts the skill for the session's first
|
|
7
|
-
task-list maintenance loop.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import json
|
|
13
|
-
import sys
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
|
|
16
|
-
_hooks_dir = str(Path(__file__).resolve().parent.parent)
|
|
17
|
-
if _hooks_dir not in sys.path:
|
|
18
|
-
sys.path.insert(0, _hooks_dir)
|
|
19
|
-
|
|
20
|
-
from hooks_constants.task_list_loop_starter_constants import ( # noqa: E402
|
|
21
|
-
TASK_LIST_LOOP_DIRECTIVE,
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def build_session_directive() -> str:
|
|
26
|
-
"""Return the task-list loop directive emitted at session start."""
|
|
27
|
-
return TASK_LIST_LOOP_DIRECTIVE
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def main() -> None:
|
|
31
|
-
"""Emit the task-list loop directive as SessionStart additionalContext."""
|
|
32
|
-
print(
|
|
33
|
-
json.dumps(
|
|
34
|
-
{
|
|
35
|
-
"hookSpecificOutput": {
|
|
36
|
-
"hookEventName": "SessionStart",
|
|
37
|
-
"additionalContext": build_session_directive(),
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if __name__ == "__main__":
|
|
45
|
-
main()
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"""Tests for task_list_loop_starter — SessionStart hook that starts a task-list loop."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
import sys
|
|
5
|
-
from io import StringIO
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from unittest.mock import patch
|
|
8
|
-
|
|
9
|
-
_SESSION_DIR = Path(__file__).resolve().parent
|
|
10
|
-
_HOOKS_ROOT = _SESSION_DIR.parent
|
|
11
|
-
for each_sys_path_entry in (str(_SESSION_DIR), str(_HOOKS_ROOT)):
|
|
12
|
-
if each_sys_path_entry not in sys.path:
|
|
13
|
-
sys.path.insert(0, each_sys_path_entry)
|
|
14
|
-
|
|
15
|
-
import task_list_loop_starter as starter
|
|
16
|
-
|
|
17
|
-
from hooks_constants.task_list_loop_starter_constants import (
|
|
18
|
-
TASK_LIST_LOOP_DIRECTIVE,
|
|
19
|
-
TASK_LIST_MAINTENANCE_INSTRUCTION,
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _run_main() -> str:
|
|
24
|
-
"""Return stdout produced by running the hook's main()."""
|
|
25
|
-
captured_stdout = StringIO()
|
|
26
|
-
with patch("sys.stdout", captured_stdout):
|
|
27
|
-
starter.main()
|
|
28
|
-
return captured_stdout.getvalue()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class TestSessionDirective:
|
|
32
|
-
def test_main_emits_additional_context(self) -> None:
|
|
33
|
-
emitted = json.loads(_run_main())
|
|
34
|
-
hook_output = emitted["hookSpecificOutput"]
|
|
35
|
-
assert hook_output["hookEventName"] == "SessionStart"
|
|
36
|
-
assert "additionalContext" in hook_output
|
|
37
|
-
|
|
38
|
-
def test_directive_carries_the_one_line_instruction(self) -> None:
|
|
39
|
-
emitted = json.loads(_run_main())
|
|
40
|
-
assert TASK_LIST_MAINTENANCE_INSTRUCTION in emitted["hookSpecificOutput"]["additionalContext"]
|
|
41
|
-
|
|
42
|
-
def test_directive_names_the_ten_minute_cadence(self) -> None:
|
|
43
|
-
emitted = json.loads(_run_main())
|
|
44
|
-
assert "10-minute" in emitted["hookSpecificOutput"]["additionalContext"]
|
|
45
|
-
|
|
46
|
-
def test_directive_names_the_loop_command(self) -> None:
|
|
47
|
-
emitted = json.loads(_run_main())
|
|
48
|
-
assert "/loop 10m" in emitted["hookSpecificOutput"]["additionalContext"]
|
|
49
|
-
|
|
50
|
-
def test_directive_runs_the_instruction_immediately(self) -> None:
|
|
51
|
-
emitted = json.loads(_run_main())
|
|
52
|
-
assert "Run that instruction once immediately when starting the loop, then" in emitted[
|
|
53
|
-
"hookSpecificOutput"
|
|
54
|
-
]["additionalContext"]
|
|
55
|
-
|
|
56
|
-
def test_directive_reuses_an_existing_loop(self) -> None:
|
|
57
|
-
emitted = json.loads(_run_main())
|
|
58
|
-
assert "Reuse the active task-list maintenance loop when available." in emitted[
|
|
59
|
-
"hookSpecificOutput"
|
|
60
|
-
]["additionalContext"]
|
|
61
|
-
|
|
62
|
-
def test_build_session_directive_returns_the_shared_constant(self) -> None:
|
|
63
|
-
assert starter.build_session_directive() == TASK_LIST_LOOP_DIRECTIVE
|