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.
Files changed (133) hide show
  1. package/.agents/skills/AGENTS.md +4 -4
  2. package/.agents/skills/_shared/AGENTS.md +1 -0
  3. package/.agents/skills/_shared/pr-loop/AGENTS.md +1 -0
  4. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +119 -0
  5. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +5 -0
  6. package/.agents/skills/e-code-review/SKILL.md +12 -1
  7. package/.agents/skills/e-code-review/reference/fix.md +5 -1
  8. package/.agents/skills/e-code-review/reference/loop.md +4 -0
  9. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +66 -0
  10. package/.agents/skills/e-code-review/reference/preflight-proposal.md +40 -0
  11. package/.agents/skills/e-code-review/reference/runner-selection.md +1 -0
  12. package/.agents/skills/pr-cleanup/SKILL.md +105 -75
  13. package/.agents/skills/pr-cleanup/reference/process-inventory.md +15 -0
  14. package/.agents/skills/pr-cleanup/reference/task-seeds.md +20 -0
  15. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/SKILL.md +18 -12
  16. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/offense-examples.md +1 -1
  17. package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/task-seeds.md +3 -2
  18. package/.agents/skills/pr-refinement/SKILL.md +31 -0
  19. package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/SKILL.md +24 -7
  20. package/.agents/skills/{small-cl → pr-small-cl}/SKILL.md +1 -1
  21. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +33 -5
  22. package/.agents/skills/skill-builder/SKILL.md +1 -0
  23. package/.agents/skills-archived/bugteam/SKILL.md +1 -1
  24. package/.agents/skills-archived/bugteam/test_skill_additions.py +1 -1
  25. package/.agents/skills-archived/comments/SKILL.md +1 -1
  26. package/.agents/skills-archived/descriptions/SKILL.md +1 -1
  27. package/.agents/skills-archived/reviews/SKILL.md +1 -1
  28. package/AGENTS.md +1 -1
  29. package/_shared/pr-loop/AGENTS.md +2 -1
  30. package/_shared/pr-loop/preflight-proposal.md +56 -0
  31. package/_shared/pr-loop/scripts/code_rules_gate.py +29 -6
  32. package/_shared/pr-loop/scripts/code_rules_gate_parts/gate_arguments.py +15 -3
  33. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_gate_running.py +47 -4
  34. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +4 -0
  35. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +47 -0
  36. package/bin/ever-shipped-skills.mjs +14 -0
  37. package/bin/install-constants.mjs +5 -0
  38. package/bin/install.agents-home.test.mjs +23 -0
  39. package/bin/install.codex-rules.test.mjs +61 -6
  40. package/bin/install.mjs +57 -9
  41. package/bin/install.prune.test.mjs +65 -3
  42. package/bin/install.test.mjs +202 -2
  43. package/docs/CODE_RULES.md +6 -0
  44. package/hooks/advisory/conftest.py +10 -0
  45. package/hooks/advisory/migration_safety_advisor.py +14 -14
  46. package/hooks/advisory/refactor_guard.py +250 -144
  47. package/hooks/advisory/refactor_guard_test_support.py +46 -0
  48. package/hooks/advisory/test_migration_safety_advisor.py +120 -0
  49. package/hooks/advisory/test_refactor_guard_advisory.py +171 -0
  50. package/hooks/advisory/test_refactor_guard_eligibility.py +166 -0
  51. package/hooks/atomic_file_writer.py +81 -0
  52. package/hooks/blocking/AGENTS.md +2 -1
  53. package/hooks/blocking/block_main_commit.py +66 -33
  54. package/hooks/blocking/code_rules_banned_identifiers.py +55 -4
  55. package/hooks/blocking/code_rules_blast_radius.py +194 -0
  56. package/hooks/blocking/code_rules_enforcer.py +12 -0
  57. package/hooks/blocking/code_rules_enforcer_test_support.py +92 -0
  58. package/hooks/blocking/destructive_command_blocker.py +8 -7
  59. package/hooks/blocking/pre_tool_use_dispatcher.py +11 -7
  60. package/hooks/blocking/precommit_code_rules_gate.py +14 -139
  61. package/hooks/blocking/sensitive_file_protector.py +8 -6
  62. package/hooks/blocking/session_edit_stage_gate.py +31 -1
  63. package/hooks/blocking/test_block_main_commit.py +145 -0
  64. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +171 -1
  65. package/hooks/blocking/test_code_rules_blast_radius.py +161 -0
  66. package/hooks/blocking/test_code_rules_enforcer_agent_home_tooling.py +37 -12
  67. package/hooks/blocking/test_code_rules_enforcer_banned_noun_word.py +54 -0
  68. package/hooks/blocking/test_code_rules_enforcer_duplicate_body_hook_routing.py +15 -53
  69. package/hooks/blocking/test_code_rules_enforcer_ephemeral.py +13 -62
  70. package/hooks/blocking/test_code_rules_enforcer_narrow_edit.py +309 -0
  71. package/hooks/blocking/test_code_rules_enforcer_precheck_forecast.py +14 -71
  72. package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +14 -16
  73. package/hooks/blocking/test_code_rules_enforcer_split_entry_2.py +31 -46
  74. package/hooks/blocking/test_code_rules_enforcer_stage.py +192 -0
  75. package/hooks/blocking/test_code_rules_enforcer_zero_payload_alias_hook_routing.py +13 -59
  76. package/hooks/blocking/test_destructive_command_blocker.py +154 -138
  77. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +85 -25
  78. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +58 -38
  79. package/hooks/blocking/test_destructive_command_blocker_patterns.py +133 -0
  80. package/hooks/blocking/test_docstring_rule_gate_count_blocker.py +113 -1
  81. package/hooks/blocking/test_env_var_table_code_drift_blocker.py +70 -3
  82. package/hooks/blocking/test_hook_subprocess_support.py +296 -0
  83. package/hooks/blocking/test_package_inventory_stale_blocker.py +1 -1
  84. package/hooks/blocking/test_pii_scanner.py +81 -0
  85. package/hooks/blocking/test_pre_tool_use_dispatcher.py +32 -3
  86. package/hooks/blocking/test_precommit_code_rules_gate.py +11 -16
  87. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +234 -0
  88. package/hooks/blocking/test_pytest_testpaths_orphan_blocker.py +25 -18
  89. package/hooks/blocking/test_sensitive_file_protector.py +145 -5
  90. package/hooks/blocking/test_session_edit_stage_gate_staging.py +64 -0
  91. package/hooks/blocking/test_session_edit_stage_gate_support.py +204 -0
  92. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +116 -0
  93. package/hooks/blocking/test_shared_stdin_adoption.py +31 -20
  94. package/hooks/blocking/test_test_preflight_check.py +80 -0
  95. package/hooks/git-hooks/AGENTS.md +1 -1
  96. package/hooks/git-hooks/git_hooks_constants/__init__.py +1 -0
  97. package/hooks/git-hooks/post_commit.py +160 -51
  98. package/hooks/git-hooks/pre_commit.py +9 -5
  99. package/hooks/git-hooks/test_post_commit.py +203 -0
  100. package/hooks/git-hooks/test_pre_commit.py +2 -2
  101. package/hooks/git-hooks/test_pre_push.py +57 -0
  102. package/hooks/hooks_constants/AGENTS.md +3 -1
  103. package/hooks/hooks_constants/atomic_file_writer_constants.py +4 -0
  104. package/hooks/hooks_constants/banned_identifiers_constants.py +1 -0
  105. package/hooks/hooks_constants/blast_radius_constants.py +14 -0
  106. package/hooks/hooks_constants/destructive_command_environment_constants.py +18 -0
  107. package/hooks/hooks_constants/destructive_command_segment_constants.py +1 -11
  108. package/hooks/hooks_constants/hardcoded_user_path_constants.py +9 -3
  109. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +1 -1
  110. package/hooks/hooks_constants/refactor_guard_constants.py +75 -0
  111. package/hooks/hooks_constants/sensitive_file_protector_constants.py +2 -4
  112. package/hooks/hooks_constants/test_refactor_guard_constants.py +21 -0
  113. package/hooks/json_file_reader.py +22 -0
  114. package/hooks/observability/test_instructions_loaded_logger.py +54 -0
  115. package/hooks/pending_sidecars.py +33 -0
  116. package/hooks/session/test_plugin_data_dir_cleanup.py +70 -0
  117. package/hooks/session/test_session_edit_tracker_cleanup.py +16 -3
  118. package/hooks/test_atomic_file_writer.py +73 -0
  119. package/hooks/test_json_file_reader.py +24 -0
  120. package/hooks/test_pending_sidecars.py +25 -0
  121. package/hooks/validation/mypy_validator.py +213 -80
  122. package/hooks/validation/test_mypy_validator.py +288 -13
  123. package/hooks/workflow/auto_formatter.py +225 -93
  124. package/hooks/workflow/investigation_tracker_reset.py +2 -0
  125. package/hooks/workflow/test_auto_formatter.py +261 -12
  126. package/hooks/workflow/test_investigation_tracker_reset.py +90 -0
  127. package/package.json +1 -1
  128. package/rules/failure-blast-radius.md +126 -0
  129. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/fetch-commands.md +0 -0
  130. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/report-template.md +0 -0
  131. /package/.agents/skills/{name-by-capability-audit → pr-name-by-capability}/reference/rule-checklist.md +0 -0
  132. /package/.agents/skills/{shared-extraction-audit → pr-shared-extraction}/reference/examples.md +0 -0
  133. /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
- code_rules_enforcer = SimpleNamespace(main=main, sys=sys)
40
-
41
- _ENFORCER_SCRIPT_PATH = _HOOK_DIRECTORY / "code_rules_enforcer.py"
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
- stdout = _run_main_with_write_payload(
107
- str(new_file), PASS_THROUGH_ALIAS_SOURCE, monkeypatch, capsys
71
+ captured_stdout, _exit_code = run_write_entrypoint(
72
+ main,
73
+ str(new_file),
74
+ PASS_THROUGH_ALIAS_SOURCE,
108
75
  )
109
- assert stdout != "", (
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(stdout)
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
- tmp_path_factory: pytest.TempPathFactory,
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 = tmp_path_factory.mktemp("staging")
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 = 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
- )
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}, "