claude-dev-env 2.5.0 → 2.7.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.
Files changed (153) hide show
  1. package/CLAUDE.md +20 -57
  2. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -1
  3. package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +12 -2
  4. package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +309 -0
  5. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +540 -0
  6. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +206 -70
  7. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/__init__.py +1 -0
  8. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/_repo_test_helpers.py +76 -0
  9. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_baseline_import_isolation.py +248 -0
  10. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_regression.py +309 -0
  11. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +91 -58
  12. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +202 -0
  13. package/_shared/pr-loop/worker-spawn.md +3 -1
  14. package/agents/CLAUDE.md +1 -1
  15. package/agents/code-verifier.md +36 -7
  16. package/bin/codex-compat.mjs +104 -0
  17. package/bin/codex-compat.test.mjs +51 -0
  18. package/codex-capability-map.json +13 -0
  19. package/docs/CODE_RULES.md +2 -0
  20. package/docs/codex-compatibility.md +25 -0
  21. package/docs/nas-ssh-invocation.md +96 -12
  22. package/docs/references/code-review-enforcement.md +31 -6
  23. package/hooks/blocking/CLAUDE.md +3 -0
  24. package/hooks/blocking/config/code_review_enforcement_constants.py +40 -10
  25. package/hooks/blocking/config/test_code_review_enforcement_constants.py +56 -3
  26. package/hooks/blocking/eli11_reply_enforcer.py +479 -0
  27. package/hooks/blocking/gh_body_arg_blocker.py +1 -1
  28. package/hooks/blocking/nas_ssh_binary_enforcer.py +8 -46
  29. package/hooks/blocking/shell_substitution_blocker.py +129 -0
  30. package/hooks/blocking/state_description_blocker.py +1 -1
  31. package/hooks/blocking/stop_dispatcher.py +1 -1
  32. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +2 -3
  33. package/hooks/blocking/test_eli11_reply_enforcer.py +457 -0
  34. package/hooks/blocking/test_shell_substitution_blocker.py +124 -0
  35. package/hooks/blocking/test_stop_dispatcher.py +23 -0
  36. package/hooks/blocking/test_unscoped_search_blocker.py +102 -0
  37. package/hooks/blocking/test_verdict_directory_write_blocker.py +4 -8
  38. package/hooks/blocking/unscoped_search_blocker.py +391 -0
  39. package/hooks/git-hooks/CLAUDE.md +3 -0
  40. package/hooks/git-hooks/conftest.py +30 -0
  41. package/hooks/git-hooks/gate_utils.py +2 -2
  42. package/hooks/git-hooks/git_hooks_constants/__init__.py +41 -2
  43. package/hooks/git-hooks/pre_push.py +75 -4
  44. package/hooks/git-hooks/pre_push_base_reference.py +166 -0
  45. package/hooks/git-hooks/test_config.py +0 -15
  46. package/hooks/git-hooks/test_gate_utils.py +3 -15
  47. package/hooks/git-hooks/test_pre_commit.py +1 -15
  48. package/hooks/git-hooks/test_pre_push.py +236 -27
  49. package/hooks/git-hooks/test_pre_push_base_reference.py +339 -0
  50. package/hooks/hooks.json +0 -12
  51. package/hooks/hooks_constants/CLAUDE.md +5 -1
  52. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +4 -4
  53. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +101 -0
  54. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +2 -8
  55. package/hooks/hooks_constants/shell_command_segments.py +82 -0
  56. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +67 -0
  57. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -0
  58. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +5 -6
  59. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +1 -0
  60. package/hooks/hooks_constants/unscoped_search_blocker_constants.py +153 -0
  61. package/package.json +4 -2
  62. package/rules/CLAUDE.md +17 -23
  63. package/rules/agent-spawn-protocol.md +6 -6
  64. package/rules/anti-corollary-tests.md +1 -1
  65. package/rules/bdd.md +1 -1
  66. package/rules/cleanup-temp-files.md +10 -4
  67. package/rules/code-standards.md +7 -0
  68. package/rules/conservative-action.md +1 -5
  69. package/rules/context7.md +0 -4
  70. package/rules/destructive-commands.md +47 -0
  71. package/rules/doc-inventory-integrity.md +48 -0
  72. package/rules/doc-prose-cuts.md +58 -0
  73. package/rules/docstring-prose-matches-implementation.md +10 -2
  74. package/rules/durable-post-artifacts.md +0 -4
  75. package/rules/eli11-replies.md +31 -0
  76. package/rules/explore-thoroughly.md +4 -4
  77. package/rules/falsify-before-green.md +68 -0
  78. package/rules/file-global-constants.md +1 -1
  79. package/rules/filesystem-search.md +51 -0
  80. package/rules/gh-cli-conventions.md +27 -0
  81. package/rules/git-workflow.md +26 -0
  82. package/rules/hedging-claims.md +9 -0
  83. package/rules/long-horizon-autonomy.md +0 -4
  84. package/rules/measurement-denominators.md +48 -0
  85. package/rules/nas-ssh-invocation.md +23 -5
  86. package/rules/parallel-tools.md +2 -2
  87. package/rules/plain-illustrative-docstrings.md +3 -7
  88. package/rules/plain-language.md +2 -0
  89. package/rules/proof-of-work-pr-comments.md +0 -4
  90. package/rules/re-stage-before-commit.md +2 -0
  91. package/rules/research-mode.md +10 -0
  92. package/rules/shell-invocation.md +21 -0
  93. package/rules/testing.md +4 -0
  94. package/rules/verified-commit-gate-skip.md +3 -27
  95. package/rules/verify-before-asking.md +5 -0
  96. package/rules/windows-filesystem-safe.md +1 -1
  97. package/rules/workers-done-before-complete.md +4 -0
  98. package/scripts/CLAUDE.md +3 -3
  99. package/scripts/Migrate-ShellPolicy.ps1 +1 -1
  100. package/scripts/codex_capability_bridge.py +171 -0
  101. package/scripts/codex_compat_materializer.py +1087 -0
  102. package/scripts/codex_compat_watcher.py +502 -0
  103. package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
  104. package/scripts/dev_env_scripts_constants/code_review_constants.py +37 -0
  105. package/scripts/dev_env_scripts_constants/grok_worker_constants.py +79 -13
  106. package/scripts/grok_headless_runner.py +213 -16
  107. package/scripts/invoke_code_review.py +11 -4
  108. package/scripts/resolve_worker_spawn.py +56 -10
  109. package/scripts/spawn_grok_batch.py +43 -22
  110. package/scripts/sync_to_cursor/rules.py +0 -10
  111. package/scripts/test_grok_headless_runner.py +592 -10
  112. package/scripts/test_invoke_code_review.py +143 -0
  113. package/scripts/test_invoke_code_review_chain.py +1 -1
  114. package/scripts/test_invoke_code_review_contract.py +1 -1
  115. package/scripts/test_resolve_worker_spawn.py +179 -15
  116. package/scripts/test_spawn_grok_batch.py +225 -22
  117. package/scripts/tests/test_code_review_constants.py +80 -0
  118. package/scripts/tests/test_codex_capability_bridge.py +91 -0
  119. package/scripts/tests/test_codex_compat_materializer.py +632 -0
  120. package/scripts/tests/test_codex_compat_watcher.py +599 -0
  121. package/scripts/tests/test_sync_to_cursor.py +0 -1
  122. package/skills/autoconverge/workflow/converge.contract.test.mjs +28 -6
  123. package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +73 -0
  124. package/skills/autoconverge/workflow/converge.mjs +64 -15
  125. package/skills/bugteam/reference/copilot-gap-analysis.md +1 -1
  126. package/skills/condensing-instructions/SKILL.md +42 -51
  127. package/skills/fresh-branch/CLAUDE.md +1 -1
  128. package/skills/fresh-branch/SKILL.md +5 -6
  129. package/skills/fresh-branch/scripts/create_fresh_branch.py +42 -24
  130. package/skills/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +1 -3
  131. package/skills/fresh-branch/scripts/test_create_fresh_branch.py +30 -126
  132. package/skills/grok-spawn/SKILL.md +5 -3
  133. package/skills/grok-spawn/reference/flag-profiles.md +3 -1
  134. package/skills/orchestrator/SKILL.md +23 -9
  135. package/skills/orchestrator-refresh/SKILL.md +20 -1
  136. package/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
  137. package/skills/session-log/SKILL.md +1 -1
  138. package/rules/claude-md-orphan-file.md +0 -28
  139. package/rules/cleanup-command-forms.md +0 -23
  140. package/rules/code-reviews.md +0 -11
  141. package/rules/env-var-table-code-drift.md +0 -10
  142. package/rules/gh-body-file.md +0 -5
  143. package/rules/gh-paginate.md +0 -3
  144. package/rules/hook-prose-matches-detector.md +0 -15
  145. package/rules/no-historical-clutter.md +0 -26
  146. package/rules/no-inline-destructive-literals.md +0 -9
  147. package/rules/no-justification-noise.md +0 -61
  148. package/rules/package-inventory-stale-entry.md +0 -25
  149. package/rules/right-sized-engineering.md +0 -28
  150. package/rules/self-contained-docs.md +0 -17
  151. package/rules/shell-invocation-policy.md +0 -5
  152. package/rules/state-what-is.md +0 -25
  153. package/rules/tdd.md +0 -7
@@ -38,14 +38,15 @@ from dev_env_scripts_constants.grok_worker_constants import (
38
38
  DEBUG_FILENAME_PREFIX,
39
39
  DEBUG_FILENAME_SUFFIX,
40
40
  DEFAULT_ROLE,
41
- DEFAULT_WORKER_MAX_TURNS,
42
41
  DEFAULT_WORKER_TIMEOUT_SECONDS,
43
42
  DISABLE_WEB_SEARCH_FLAG,
44
43
  DISALLOWED_TOOLS_FLAG,
45
44
  LEADER_SOCKET_FILENAME_PREFIX,
46
45
  LEADER_SOCKET_FILENAME_SUFFIX,
47
- MIN_WORKER_MAX_TURNS,
46
+ MAXIMUM_WORKER_TIMEOUT_ERROR_TEMPLATE,
47
+ MAXIMUM_WORKER_TIMEOUT_SECONDS,
48
48
  MIN_WORKER_TIMEOUT_SECONDS,
49
+ MINIMUM_WORKER_TIMEOUT_ERROR_TEMPLATE,
49
50
  OUTPUT_FILENAME_PREFIX,
50
51
  OUTPUT_FILENAME_SUFFIX,
51
52
  PROMPT_FILENAME_PREFIX,
@@ -74,7 +75,6 @@ from dev_env_scripts_constants.grok_worker_constants import (
74
75
  WORKER_SPEC_AGENT_NAME_KEY,
75
76
  WORKER_SPEC_CWD_KEY,
76
77
  WORKER_SPEC_IS_REPO_ONLY_KEY,
77
- WORKER_SPEC_MAX_TURNS_KEY,
78
78
  WORKER_SPEC_PROMPT_PARTS_KEY,
79
79
  WORKER_SPEC_ROLE_NAME_KEY,
80
80
  WORKER_SPEC_TIMEOUT_KEY,
@@ -99,7 +99,6 @@ class WorkerSpec:
99
99
  tool_profile: str
100
100
  timeout_seconds: int
101
101
  is_repo_only: bool = False
102
- max_turns: int = DEFAULT_WORKER_MAX_TURNS
103
102
  agent_name: str | None = None
104
103
 
105
104
 
@@ -248,15 +247,46 @@ def _require_worker_field(
248
247
  return all_worker_fields[field_name]
249
248
 
250
249
 
251
- def _require_int_at_least(
252
- raw_field: object, field_name: str, minimum_accepted: int
253
- ) -> int:
254
- parsed_integer = _require_int(raw_field, field_name)
255
- if parsed_integer < minimum_accepted:
250
+ def _require_timeout_within_bounds(raw_field: object) -> int:
251
+ """Accept a worker timeout inside the bounds; refuse anything outside them.
252
+
253
+ ::
254
+
255
+ 0 flag: ValueError naming MIN_WORKER_TIMEOUT_SECONDS
256
+ 5401 flag: ValueError naming MAXIMUM_WORKER_TIMEOUT_SECONDS
257
+ 5400 ok: returned untouched
258
+ 30 ok: returned untouched
259
+
260
+ Rejecting here rather than clamping keeps the fault where the operator
261
+ wrote it. The runner repeats the check for callers that skip the parse.
262
+
263
+ Args:
264
+ raw_field: The parsed ``timeout_seconds`` value from the specification.
265
+
266
+ Returns:
267
+ The accepted timeout in seconds, unchanged.
268
+
269
+ Raises:
270
+ ValueError: When the value is not an int, or falls outside the bounds.
271
+ """
272
+ timeout_seconds = _require_int(raw_field, WORKER_SPEC_TIMEOUT_KEY)
273
+ if timeout_seconds < MIN_WORKER_TIMEOUT_SECONDS:
256
274
  raise ValueError(
257
- f"worker {field_name} must be >= {minimum_accepted}"
275
+ MINIMUM_WORKER_TIMEOUT_ERROR_TEMPLATE.format(
276
+ field_name=WORKER_SPEC_TIMEOUT_KEY,
277
+ requested_seconds=timeout_seconds,
278
+ minimum_seconds=MIN_WORKER_TIMEOUT_SECONDS,
279
+ )
258
280
  )
259
- return parsed_integer
281
+ if timeout_seconds > MAXIMUM_WORKER_TIMEOUT_SECONDS:
282
+ raise ValueError(
283
+ MAXIMUM_WORKER_TIMEOUT_ERROR_TEMPLATE.format(
284
+ field_name=WORKER_SPEC_TIMEOUT_KEY,
285
+ requested_seconds=timeout_seconds,
286
+ maximum_seconds=MAXIMUM_WORKER_TIMEOUT_SECONDS,
287
+ )
288
+ )
289
+ return timeout_seconds
260
290
 
261
291
 
262
292
  def _parse_worker_entry(all_worker_fields: dict[str, object]) -> WorkerSpec:
@@ -275,22 +305,15 @@ def _parse_worker_entry(all_worker_fields: dict[str, object]) -> WorkerSpec:
275
305
  _require_worker_field(all_worker_fields, WORKER_SPEC_TOOL_PROFILE_KEY),
276
306
  WORKER_SPEC_TOOL_PROFILE_KEY,
277
307
  )
278
- timeout_seconds = _require_int_at_least(
308
+ timeout_seconds = _require_timeout_within_bounds(
279
309
  all_worker_fields.get(
280
310
  WORKER_SPEC_TIMEOUT_KEY, DEFAULT_WORKER_TIMEOUT_SECONDS
281
- ),
282
- WORKER_SPEC_TIMEOUT_KEY,
283
- MIN_WORKER_TIMEOUT_SECONDS,
311
+ )
284
312
  )
285
313
  is_repo_only = _require_bool(
286
314
  all_worker_fields.get(WORKER_SPEC_IS_REPO_ONLY_KEY, False),
287
315
  WORKER_SPEC_IS_REPO_ONLY_KEY,
288
316
  )
289
- max_turns = _require_int_at_least(
290
- all_worker_fields.get(WORKER_SPEC_MAX_TURNS_KEY, DEFAULT_WORKER_MAX_TURNS),
291
- WORKER_SPEC_MAX_TURNS_KEY,
292
- MIN_WORKER_MAX_TURNS,
293
- )
294
317
  agent_name = all_worker_fields.get(WORKER_SPEC_AGENT_NAME_KEY)
295
318
  if not isinstance(all_prompt_parts, list) or not all_prompt_parts:
296
319
  raise ValueError("worker prompt_parts must be a non-empty list")
@@ -311,7 +334,6 @@ def _parse_worker_entry(all_worker_fields: dict[str, object]) -> WorkerSpec:
311
334
  tool_profile=tool_profile,
312
335
  timeout_seconds=timeout_seconds,
313
336
  is_repo_only=is_repo_only,
314
- max_turns=max_turns,
315
337
  agent_name=agent_name,
316
338
  )
317
339
 
@@ -423,7 +445,6 @@ def _invoke_worker(
423
445
  prompt_file=scratch_paths.prompt_path,
424
446
  working_directory=worker_spec.working_directory,
425
447
  run_state_directory=run_state_directory,
426
- max_turns=worker_spec.max_turns,
427
448
  timeout_seconds=worker_spec.timeout_seconds,
428
449
  agent_name=worker_spec.agent_name,
429
450
  leader_socket_path=scratch_paths.leader_socket_path,
@@ -59,7 +59,6 @@ def _strip_code_standards_blockquote(markdown: str) -> str:
59
59
  _merged_mapping_key_order = (
60
60
  "code-standards",
61
61
  "tasklings-preferences",
62
- "right-sized-engineering",
63
62
  "bdd",
64
63
  "test-quality",
65
64
  "research-mode",
@@ -350,15 +349,6 @@ def _always_apply_mappings(rules_directory: Path, docs_directory: Path) -> tuple
350
349
  "Core code standards: naming, types, config, hook-enforced rules",
351
350
  "merge_code_standards",
352
351
  ),
353
- RuleMapping(
354
- "right-sized-engineering",
355
- (rules_directory / "right-sized-engineering.md",),
356
- "right-sized-engineering.mdc",
357
- True,
358
- None,
359
- "Right-sized engineering and complexity budget",
360
- "verbatim",
361
- ),
362
352
  RuleMapping(
363
353
  "bdd",
364
354
  (rules_directory / "bdd.md",),