claude-dev-env 1.38.1 → 1.40.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/CLAUDE.md +10 -36
- package/_shared/pr-loop/audit-reply-template.md +147 -0
- package/_shared/pr-loop/fix-protocol.md +25 -4
- package/_shared/pr-loop/gh-payloads.md +37 -50
- package/_shared/pr-loop/scripts/code_rules_gate.py +0 -60
- package/_shared/pr-loop/scripts/config/post_audit_thread_constants.py +199 -0
- package/_shared/pr-loop/scripts/config/reviews_disabled_constants.py +8 -0
- package/_shared/pr-loop/scripts/post_audit_thread.py +1242 -0
- package/_shared/pr-loop/scripts/preflight.py +129 -2
- package/_shared/pr-loop/scripts/reviews_disabled.py +59 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -19
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1116 -0
- package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +127 -0
- package/_shared/pr-loop/scripts/tests/test_preflight.py +41 -0
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +36 -0
- package/_shared/pr-loop/state-schema.md +1 -1
- package/agents/clean-coder.md +2 -2
- package/agents/pr-description-writer.md +150 -52
- package/bin/install.mjs +6 -7
- package/bin/install.test.mjs +8 -0
- package/commands/doc-gist.md +16 -0
- package/commands/plan.md +0 -2
- package/commands/review-plan.md +1 -1
- package/docs/CODE_RULES.md +122 -2
- package/docs/PR_DESCRIPTION_GUIDE.md +127 -64
- package/hooks/blocking/bot_mention_comment_blocker.py +75 -0
- package/hooks/blocking/code_rules_enforcer.py +1143 -129
- package/hooks/blocking/convergence_gate_blocker.py +130 -0
- package/hooks/blocking/destructive_command_blocker.py +74 -0
- package/hooks/blocking/gh_body_arg_blocker.py +30 -0
- package/hooks/blocking/md_to_html_blocker.py +119 -0
- package/hooks/blocking/pr_description_enforcer.py +57 -22
- package/hooks/blocking/test_bot_mention_comment_blocker.py +131 -0
- package/hooks/blocking/test_code_rules_enforcer.py +21 -0
- package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +70 -0
- package/hooks/blocking/test_code_rules_enforcer_any_imports_and_cast.py +92 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +143 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +152 -0
- package/hooks/blocking/test_code_rules_enforcer_bare_except.py +120 -0
- package/hooks/blocking/test_code_rules_enforcer_boundary_types.py +175 -0
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
- package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +50 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_format.py +255 -0
- package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +130 -0
- package/hooks/blocking/test_code_rules_enforcer_stub_implementations.py +141 -0
- package/hooks/blocking/test_code_rules_enforcer_test_branching.py +143 -0
- package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +169 -0
- package/hooks/blocking/test_code_rules_enforcer_todo_markers.py +99 -0
- package/hooks/blocking/test_code_rules_enforcer_typed_dict_pairs.py +141 -0
- package/hooks/blocking/test_convergence_gate_blocker.py +63 -0
- package/hooks/blocking/test_destructive_command_blocker.py +146 -0
- package/hooks/blocking/test_destructive_command_blocker_no_verify.py +102 -0
- package/hooks/blocking/test_gh_body_arg_blocker.py +45 -0
- package/hooks/blocking/test_md_to_html_blocker.py +317 -0
- package/hooks/blocking/test_pr_description_enforcer.py +69 -8
- package/hooks/config/any_type_config.py +7 -0
- package/hooks/config/banned_identifiers_constants.py +11 -0
- package/hooks/config/blocking_check_limits.py +38 -0
- package/hooks/config/bot_mention_comment_blocker_constants.py +20 -0
- package/hooks/config/code_rules_enforcer_constants.py +53 -0
- package/hooks/config/convergence_branch_constants.py +9 -0
- package/hooks/config/doc_gist_auto_publish_constants.py +18 -0
- package/hooks/config/html_companion_constants.py +20 -0
- package/hooks/config/inline_tuple_string_magic_constants.py +22 -0
- package/hooks/config/pr_description_enforcer_constants.py +14 -0
- package/hooks/config/test_banned_identifiers_constants.py +17 -0
- package/hooks/hooks.json +28 -20
- package/hooks/pyproject.toml +69 -0
- package/hooks/validators/mypy_integration.py +47 -1
- package/hooks/validators/run_all_validators.py +3 -3
- package/hooks/validators/test_mypy_integration.py +50 -1
- package/hooks/workflow/doc_gist_auto_publish.py +144 -0
- package/hooks/workflow/md_to_html_companion.py +365 -0
- package/hooks/workflow/test_doc_gist_auto_publish.py +117 -0
- package/hooks/workflow/test_md_to_html_companion.py +452 -0
- package/package.json +1 -1
- package/rules/gh-body-file.md +2 -0
- package/scripts/Install-SweepEmptyDirs.ps1 +111 -0
- package/scripts/check.ps1 +106 -0
- package/scripts/config/timing.py +11 -0
- package/scripts/sweep_empty_dirs.py +138 -0
- package/scripts/sync_to_cursor/rules.py +1 -1
- package/scripts/test_sweep_empty_dirs.py +183 -0
- package/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +323 -0
- package/skills/_shared/pr-loop/scripts/_cli_utils.py +22 -0
- package/skills/_shared/pr-loop/scripts/_path_resolver.py +165 -0
- package/skills/_shared/pr-loop/scripts/_xml_utils.py +20 -0
- package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +182 -0
- package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +185 -0
- package/skills/_shared/pr-loop/scripts/config/__init__.py +0 -0
- package/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py +78 -0
- package/skills/_shared/pr-loop/scripts/init_loop_state.py +135 -0
- package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +175 -0
- package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +182 -0
- package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +206 -0
- package/skills/bugteam/CONSTRAINTS.md +21 -22
- package/skills/bugteam/EXAMPLES.md +3 -3
- package/skills/bugteam/PROMPTS.md +227 -67
- package/skills/bugteam/SKILL.md +132 -455
- package/skills/bugteam/reference/README.md +1 -1
- package/skills/bugteam/reference/audit-and-teammates.md +112 -39
- package/skills/bugteam/reference/audit-contract.md +4 -22
- package/skills/bugteam/reference/copilot-gap-analysis.md +8 -5
- package/skills/bugteam/reference/design-rationale.md +2 -2
- package/skills/bugteam/reference/github-pr-reviews.md +50 -57
- package/skills/bugteam/reference/obstacles/audit-assign-ids.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-capture-excerpts.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-walk-categories.md +13 -0
- package/skills/bugteam/reference/obstacles/audit-write-xml.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-append-summary.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-apply-fixes.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-git-add-commit.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-git-push.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-post-reply.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-publish-summary.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-py-compile.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-read-files.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-resolve-thread.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-test-suite.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-violation-count.md +13 -0
- package/skills/bugteam/reference/obstacles/fix-write-xml.md +13 -0
- package/skills/bugteam/reference/team-setup.md +111 -9
- package/skills/bugteam/reference/teardown-publish-permissions.md +39 -8
- package/skills/bugteam/scripts/README.md +60 -0
- package/skills/bugteam/scripts/_claude_permissions_common.py +358 -0
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +976 -0
- package/skills/bugteam/scripts/bugteam_fix_hookspath.py +375 -0
- package/skills/bugteam/scripts/bugteam_preflight.py +328 -0
- package/skills/bugteam/scripts/config/bugteam_code_rules_gate_constants.py +25 -0
- package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +26 -0
- package/skills/bugteam/scripts/config/bugteam_preflight_constants.py +35 -0
- package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +20 -0
- package/skills/bugteam/scripts/config/probe_code_rules_enforcer_check_constants.py +12 -0
- package/skills/bugteam/scripts/config/windows_safe_rmtree_constants.py +7 -0
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +175 -0
- package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +107 -0
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +220 -0
- package/skills/bugteam/scripts/test__claude_permissions_common.py +112 -0
- package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +400 -0
- package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +384 -0
- package/skills/bugteam/scripts/test_bugteam_preflight.py +309 -0
- package/skills/bugteam/scripts/test_claude_permissions_common.py +195 -0
- package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +55 -0
- package/skills/bugteam/scripts/test_probe_code_rules_enforcer_check.py +76 -0
- package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +55 -0
- package/skills/bugteam/scripts/test_windows_safe_rmtree.py +108 -0
- package/skills/bugteam/scripts/windows_safe_rmtree.py +100 -0
- package/skills/bugteam/test_skill_additions.py +1 -11
- package/skills/code/SKILL.md +176 -0
- package/skills/copilot-review/SKILL.md +16 -0
- package/skills/doc-gist/SKILL.md +99 -0
- package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +453 -0
- package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +515 -0
- package/skills/doc-gist/references/examples/03-code-review-pr.html +638 -0
- package/skills/doc-gist/references/examples/04-code-understanding.html +491 -0
- package/skills/doc-gist/references/examples/05-design-system.html +629 -0
- package/skills/doc-gist/references/examples/06-component-variants.html +605 -0
- package/skills/doc-gist/references/examples/07-prototype-animation.html +455 -0
- package/skills/doc-gist/references/examples/08-prototype-interaction.html +396 -0
- package/skills/doc-gist/references/examples/09-slide-deck.html +592 -0
- package/skills/doc-gist/references/examples/10-svg-illustrations.html +492 -0
- package/skills/doc-gist/references/examples/11-status-report.html +528 -0
- package/skills/doc-gist/references/examples/12-incident-report.html +596 -0
- package/skills/doc-gist/references/examples/13-flowchart-diagram.html +395 -0
- package/skills/doc-gist/references/examples/14-research-feature-explainer.html +381 -0
- package/skills/doc-gist/references/examples/15-research-concept-explainer.html +368 -0
- package/skills/doc-gist/references/examples/16-implementation-plan.html +702 -0
- package/skills/doc-gist/references/examples/17-pr-writeup.html +595 -0
- package/skills/doc-gist/references/examples/18-editor-triage-board.html +573 -0
- package/skills/doc-gist/references/examples/19-editor-feature-flags.html +663 -0
- package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +722 -0
- package/skills/doc-gist/references/examples/README.md +5 -0
- package/skills/doc-gist/scripts/config/__init__.py +0 -0
- package/skills/doc-gist/scripts/config/gist_upload_constants.py +16 -0
- package/skills/doc-gist/scripts/gist_upload.py +177 -0
- package/skills/doc-gist/scripts/test_gist_upload.py +51 -0
- package/skills/findbugs/SKILL.md +96 -2
- package/skills/monitor-open-prs/SKILL.md +14 -32
- package/skills/monitor-open-prs/test_skill_contract.py +0 -11
- package/skills/pr-consistency-audit/SKILL.md +112 -0
- package/skills/pr-consistency-audit/reference/detection-rules.md +96 -0
- package/skills/pr-consistency-audit/reference/illustrations.md +78 -0
- package/skills/pr-converge/SKILL.md +229 -23
- package/skills/pr-converge/config/__init__.py +0 -0
- package/skills/pr-converge/config/constants.py +63 -0
- package/skills/pr-converge/reference/convergence-gates.md +138 -44
- package/skills/pr-converge/reference/examples.md +43 -11
- package/skills/pr-converge/reference/fix-protocol.md +6 -5
- package/skills/pr-converge/reference/ground-rules.md +5 -3
- package/skills/pr-converge/reference/multi-pr-orchestration.md +44 -19
- package/skills/pr-converge/reference/obstacles/fix-post-replies.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-push.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-read-filelines.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-reset-state.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-resolve-threads.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-stage-commit.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-trigger-bugbot.md +13 -0
- package/skills/pr-converge/reference/obstacles/fix-write-test.md +13 -0
- package/skills/pr-converge/reference/per-tick.md +107 -31
- package/skills/pr-converge/reference/state-schema.md +22 -1
- package/skills/pr-converge/reference/stop-conditions.md +9 -7
- package/skills/pr-converge/scripts/README.md +34 -46
- package/skills/pr-converge/scripts/check_bugbot_ci.py +279 -0
- package/skills/pr-converge/scripts/check_convergence.py +497 -0
- package/skills/pr-converge/scripts/check_pending_reviews.py +154 -0
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +118 -0
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +134 -0
- package/skills/pr-converge/scripts/post_fix_reply.py +168 -0
- package/skills/pr-converge/scripts/test_check_bugbot_ci.py +312 -0
- package/skills/pr-converge/workflows/schedule-wakeup-loop.md +5 -12
- package/skills/qbug/SKILL.md +157 -27
- package/skills/session-log/SKILL.md +216 -114
- package/skills/session-tidy/SKILL.md +1 -1
- package/skills/skill-builder/SKILL.md +138 -56
- package/skills/skill-builder/references/delegation-map.md +72 -113
- package/skills/skill-builder/references/progressive-disclosure.md +122 -0
- package/skills/skill-builder/references/self-audit-checklist.md +92 -0
- package/skills/skill-builder/references/skill-types.md +228 -0
- package/skills/skill-builder/references/thariq-x-post-skills.json +33 -0
- package/skills/skill-builder/templates/gap-analysis.md +15 -8
- package/skills/skill-builder/workflows/improve-skill.md +86 -57
- package/skills/skill-builder/workflows/new-skill.md +80 -168
- package/skills/skill-builder/workflows/polish-skill.md +78 -54
- package/skills/structure-prompt/SKILL.md +50 -0
- package/skills/structure-prompt/reference/adversarial-tuning.md +62 -0
- package/skills/structure-prompt/reference/block-classification.md +27 -0
- package/skills/structure-prompt/reference/canonical-case.md +48 -0
- package/skills/structure-prompt/reference/citation-depth.md +70 -0
- package/skills/structure-prompt/reference/cleanup.md +33 -0
- package/skills/structure-prompt/reference/constraints.md +33 -0
- package/skills/structure-prompt/reference/directives.md +37 -0
- package/skills/structure-prompt/reference/examples.md +72 -0
- package/skills/structure-prompt/reference/instantiation.md +51 -0
- package/skills/structure-prompt/reference/output-contract.md +72 -0
- package/skills/structure-prompt/reference/per-category.md +23 -0
- package/skills/structure-prompt/reference/persona.md +38 -0
- package/skills/structure-prompt/reference/research.md +33 -0
- package/skills/structure-prompt/reference/structure.md +28 -0
- package/agents/code-standards-agent.md +0 -93
- package/agents/groq-coder.md +0 -113
- package/agents/plan-executor.md +0 -226
- package/agents/project-docs-analyzer.md +0 -53
- package/agents/project-structure-organizer-agent.md +0 -72
- package/agents/skill-to-agent-converter.md +0 -370
- package/agents/skill-writer-agent.md +0 -470
- package/agents/user-docs-writer.md +0 -67
- package/agents/workflow-visual-documenter.md +0 -82
- package/commands/readability-review.md +0 -20
- package/hooks/mypy.ini +0 -2
- package/hooks/notification/attention_needed_notify.py +0 -71
- package/hooks/notification/claude_notification_handler.py +0 -67
- package/hooks/notification/notification_utils.py +0 -267
- package/hooks/notification/subagent_complete_notify.py +0 -381
- package/hooks/notification/test_attention_needed_notify.py +0 -47
- package/hooks/notification/test_claude_notification_handler.py +0 -54
- package/hooks/notification/test_notification_utils.py +0 -91
- package/hooks/notification/test_subagent_complete_notify.py +0 -79
- package/scripts/config/groq_bugteam_config.py +0 -230
- package/scripts/config/test_groq_bugteam_config.py +0 -83
- package/scripts/config/test_spec_implementer_prompt.py +0 -32
- package/scripts/groq_bugteam.README.md +0 -131
- package/scripts/groq_bugteam.py +0 -647
- package/scripts/groq_bugteam_dotenv.py +0 -40
- package/scripts/groq_bugteam_spec.py +0 -226
- package/scripts/test_groq_bugteam.py +0 -529
- package/scripts/test_groq_bugteam_apply_fix_from_spec.py +0 -426
- package/scripts/test_groq_bugteam_dotenv.py +0 -66
- package/scripts/test_groq_bugteam_spec.py +0 -338
- package/skills/bugteam/SKILL_EVALS.md +0 -309
- package/skills/dream/SKILL.md +0 -118
- package/skills/ingest/SKILL.md +0 -40
- package/skills/npm-creator/SKILL.md +0 -187
- package/skills/readability-review/SKILL.md +0 -127
- package/skills/resume-review/SKILL.md +0 -261
- package/skills/rule-audit/SKILL.md +0 -307
- package/skills/rule-creator/SKILL.md +0 -150
- package/skills/searching-obsidian-vault/SKILL.md +0 -131
- package/skills/skill-writer/REFERENCE.md +0 -284
- package/skills/skill-writer/SKILL.md +0 -222
- package/skills/tdd-team/SKILL.md +0 -128
|
@@ -57,6 +57,12 @@ from config.preflight_constants import (
|
|
|
57
57
|
PYTHON_FILE_SUFFIX,
|
|
58
58
|
TESTS_DIRECTORY_NAME,
|
|
59
59
|
)
|
|
60
|
+
from reviews_disabled import (
|
|
61
|
+
CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN,
|
|
62
|
+
CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME,
|
|
63
|
+
EXIT_CODE_BUGTEAM_DISABLED_VIA_ENV,
|
|
64
|
+
is_bugteam_disabled_via_env,
|
|
65
|
+
)
|
|
60
66
|
|
|
61
67
|
|
|
62
68
|
def verify_git_hooks_path(repository_root: Path | None = None) -> int:
|
|
@@ -67,8 +73,13 @@ def verify_git_hooks_path(repository_root: Path | None = None) -> int:
|
|
|
67
73
|
overrides such as Husky or lefthook. Falls back to the current working
|
|
68
74
|
directory's effective config when *repository_root* is None.
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
Args:
|
|
77
|
+
repository_root: Optional repository root to check. When None, uses
|
|
78
|
+
the current working directory's effective config.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Zero when the configured path ends with the expected hooks suffix.
|
|
82
|
+
Non-zero and prints a correction message when unset or pointing elsewhere.
|
|
72
83
|
"""
|
|
73
84
|
expected_hooks_path_suffix = HOOKS_PATH_VERIFICATION_SUFFIX
|
|
74
85
|
enforcement_absent_message = (
|
|
@@ -123,6 +134,18 @@ def verify_git_hooks_path(repository_root: Path | None = None) -> int:
|
|
|
123
134
|
|
|
124
135
|
|
|
125
136
|
def find_repository_root(start: Path) -> Path:
|
|
137
|
+
"""Find the repository root by walking up from the starting directory.
|
|
138
|
+
|
|
139
|
+
Searches for a ``.git`` directory or file in parent directories. Falls
|
|
140
|
+
back to the nearest ancestor containing ``pytest.ini`` when no git
|
|
141
|
+
repository is found.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
start: The directory to start searching from.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
The repository root path, or *start* when no repository is found.
|
|
148
|
+
"""
|
|
126
149
|
resolved = start.resolve()
|
|
127
150
|
all_candidates = [resolved, *resolved.parents]
|
|
128
151
|
for each_candidate in all_candidates:
|
|
@@ -136,6 +159,17 @@ def find_repository_root(start: Path) -> Path:
|
|
|
136
159
|
|
|
137
160
|
|
|
138
161
|
def has_pytest_configuration(root: Path) -> bool:
|
|
162
|
+
"""Check whether a directory has pytest configuration available.
|
|
163
|
+
|
|
164
|
+
Checks for ``pytest.ini`` directly, then falls back to searching for
|
|
165
|
+
``[tool.pytest]`` in ``pyproject.toml``.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
root: The directory to check for pytest configuration.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
True when pytest configuration is found in either location.
|
|
172
|
+
"""
|
|
139
173
|
if (root / PYTEST_INI_FILENAME).is_file():
|
|
140
174
|
return True
|
|
141
175
|
pyproject = root / PYPROJECT_TOML_FILENAME
|
|
@@ -146,6 +180,20 @@ def has_pytest_configuration(root: Path) -> bool:
|
|
|
146
180
|
|
|
147
181
|
|
|
148
182
|
def has_discoverable_tests(root: Path) -> bool | None:
|
|
183
|
+
"""Check whether the repository contains discoverable test files via git ls-files.
|
|
184
|
+
|
|
185
|
+
When the root has no ``.git`` marker, returns True without invoking git.
|
|
186
|
+
Otherwise asks git for tracked plus untracked test files matching the
|
|
187
|
+
discovery patterns, respecting ``.gitignore``.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
root: The directory tree root to search.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
True when at least one matching test file is found. False when git
|
|
194
|
+
succeeds and returns an empty list. None when git is unavailable or
|
|
195
|
+
the ls-files invocation fails.
|
|
196
|
+
"""
|
|
149
197
|
git_marker = root / GIT_DIRECTORY_NAME
|
|
150
198
|
if not (git_marker.is_dir() or git_marker.is_file()):
|
|
151
199
|
return True
|
|
@@ -192,6 +240,21 @@ def run_pytest(
|
|
|
192
240
|
verbose: bool,
|
|
193
241
|
all_test_paths: list[Path] | None = None,
|
|
194
242
|
) -> int:
|
|
243
|
+
"""Run pytest in the repository root and return the exit code.
|
|
244
|
+
|
|
245
|
+
Passes ``--ff`` (failed-first) and ``-q`` unless *verbose* is True. When
|
|
246
|
+
*all_test_paths* is provided, restricts the run to those paths via the
|
|
247
|
+
``--`` positional separator so pytest does not misinterpret leading
|
|
248
|
+
hyphens as options. Treats the "no tests collected" exit code as a pass.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
repository_root: The repository root for running pytest.
|
|
252
|
+
verbose: When True, omit ``-q`` so individual test names show.
|
|
253
|
+
all_test_paths: Optional list of test paths to restrict the run.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
The pytest exit code, or 0 when no tests were collected.
|
|
257
|
+
"""
|
|
195
258
|
command = [sys.executable, "-m", "pytest", PYTEST_FAILED_FIRST_FLAG]
|
|
196
259
|
if not verbose:
|
|
197
260
|
command.append("-q")
|
|
@@ -209,6 +272,20 @@ def run_pytest(
|
|
|
209
272
|
|
|
210
273
|
|
|
211
274
|
def get_changed_files(repository_root: Path, base_ref: str) -> list[Path] | None:
|
|
275
|
+
"""Return the list of files changed between *base_ref* and HEAD.
|
|
276
|
+
|
|
277
|
+
Refuses base refs beginning with ``-`` to prevent option injection into
|
|
278
|
+
git diff. Logs a warning and returns None on every failure path so the
|
|
279
|
+
caller can fall back to running the full suite.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
repository_root: The repository root for running git diff.
|
|
283
|
+
base_ref: The git base ref to diff against (e.g., ``origin/main``).
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
A list of relative file paths changed vs *base_ref*. None when
|
|
287
|
+
*base_ref* is invalid or git diff fails.
|
|
288
|
+
"""
|
|
212
289
|
if base_ref.startswith("-"):
|
|
213
290
|
print(
|
|
214
291
|
f"bugteam_preflight: invalid base_ref '{base_ref}' starts "
|
|
@@ -295,6 +372,18 @@ def _find_related_test_files(changed_path: Path, repository_root: Path) -> list[
|
|
|
295
372
|
def discover_related_tests(
|
|
296
373
|
all_changed_files: list[Path], repository_root: Path
|
|
297
374
|
) -> list[Path]:
|
|
375
|
+
"""Discover all test files related to the given changed files.
|
|
376
|
+
|
|
377
|
+
Walks every changed path through :func:`_find_related_test_files` and
|
|
378
|
+
returns the sorted, de-duplicated union.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
all_changed_files: The list of changed source files to map to tests.
|
|
382
|
+
repository_root: The repository root for resolving relative paths.
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
Sorted list of unique related test file paths.
|
|
386
|
+
"""
|
|
298
387
|
related: set[Path] = set()
|
|
299
388
|
for each_file in all_changed_files:
|
|
300
389
|
related.update(_find_related_test_files(each_file, repository_root))
|
|
@@ -302,6 +391,14 @@ def discover_related_tests(
|
|
|
302
391
|
|
|
303
392
|
|
|
304
393
|
def run_pre_commit(repository_root: Path) -> int:
|
|
394
|
+
"""Run pre-commit on all files and return its exit code.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
repository_root: The repository root for running pre-commit.
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
The pre-commit exit code (0 on success, non-zero on failure).
|
|
401
|
+
"""
|
|
305
402
|
completed = subprocess.run(
|
|
306
403
|
list(ALL_PRE_COMMIT_RUN_ALL_FILES_COMMAND),
|
|
307
404
|
cwd=str(repository_root),
|
|
@@ -311,6 +408,15 @@ def run_pre_commit(repository_root: Path) -> int:
|
|
|
311
408
|
|
|
312
409
|
|
|
313
410
|
def parse_arguments(all_arguments: list[str]) -> argparse.Namespace:
|
|
411
|
+
"""Parse command-line arguments for the preflight script.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
all_arguments: Command-line argument list.
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
Parsed namespace with repo_root, no_pytest, pre_commit, verbose,
|
|
418
|
+
base_ref, and scope attributes.
|
|
419
|
+
"""
|
|
314
420
|
parser = argparse.ArgumentParser(
|
|
315
421
|
description="Run local checks before /bugteam (pytest, optional pre-commit).",
|
|
316
422
|
)
|
|
@@ -360,6 +466,16 @@ def parse_arguments(all_arguments: list[str]) -> argparse.Namespace:
|
|
|
360
466
|
|
|
361
467
|
|
|
362
468
|
def main(all_arguments: list[str]) -> int:
|
|
469
|
+
"""Run the preflight checks (git-hooks path, pytest, optional pre-commit).
|
|
470
|
+
|
|
471
|
+
Args:
|
|
472
|
+
all_arguments: Command-line argument list to forward to argparse.
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
Zero on success. Non-zero exit code on the first failing check.
|
|
476
|
+
Returns :data:`EXIT_CODE_BUGTEAM_DISABLED_VIA_ENV` when
|
|
477
|
+
``CLAUDE_REVIEWS_DISABLED`` lists the ``bugteam`` token.
|
|
478
|
+
"""
|
|
363
479
|
arguments = parse_arguments(all_arguments)
|
|
364
480
|
skip_env_var_name = BUGTEAM_PREFLIGHT_SKIP_ENV_VAR_NAME
|
|
365
481
|
skip_enabled_value = BUGTEAM_PREFLIGHT_SKIP_ENABLED_VALUE
|
|
@@ -369,6 +485,17 @@ def main(all_arguments: list[str]) -> int:
|
|
|
369
485
|
file=sys.stderr,
|
|
370
486
|
)
|
|
371
487
|
return 0
|
|
488
|
+
reviews_disabled_env_var_name = CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME
|
|
489
|
+
reviews_disabled_bugteam_token = CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN
|
|
490
|
+
disabled_via_env_exit_code = EXIT_CODE_BUGTEAM_DISABLED_VIA_ENV
|
|
491
|
+
if is_bugteam_disabled_via_env():
|
|
492
|
+
print(
|
|
493
|
+
f"bugteam_preflight: halted "
|
|
494
|
+
f"({reviews_disabled_env_var_name} contains "
|
|
495
|
+
f"'{reviews_disabled_bugteam_token}').",
|
|
496
|
+
file=sys.stderr,
|
|
497
|
+
)
|
|
498
|
+
return disabled_via_env_exit_code
|
|
372
499
|
start = Path.cwd()
|
|
373
500
|
repository_root = (
|
|
374
501
|
arguments.repo_root.resolve()
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Shared helper for the CLAUDE_REVIEWS_DISABLED opt-out gate.
|
|
2
|
+
|
|
3
|
+
Both ``skills/bugteam/scripts/bugteam_preflight.py`` and
|
|
4
|
+
``_shared/pr-loop/scripts/preflight.py`` consume this helper so the parsing
|
|
5
|
+
rules and disabled-token taxonomy live in exactly one place.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
for each_cached_module_name in [
|
|
15
|
+
each_module_key
|
|
16
|
+
for each_module_key in list(sys.modules)
|
|
17
|
+
if each_module_key == "config" or each_module_key.startswith("config.")
|
|
18
|
+
]:
|
|
19
|
+
sys.modules.pop(each_cached_module_name, None)
|
|
20
|
+
_shared_pr_loop_scripts_directory = str(Path(__file__).absolute().parent)
|
|
21
|
+
while _shared_pr_loop_scripts_directory in sys.path:
|
|
22
|
+
sys.path.remove(_shared_pr_loop_scripts_directory)
|
|
23
|
+
if _shared_pr_loop_scripts_directory not in sys.path:
|
|
24
|
+
sys.path.insert(0, _shared_pr_loop_scripts_directory)
|
|
25
|
+
|
|
26
|
+
from config.reviews_disabled_constants import (
|
|
27
|
+
CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN,
|
|
28
|
+
CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME,
|
|
29
|
+
CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR,
|
|
30
|
+
EXIT_CODE_BUGTEAM_DISABLED_VIA_ENV,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN",
|
|
36
|
+
"CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME",
|
|
37
|
+
"CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR",
|
|
38
|
+
"EXIT_CODE_BUGTEAM_DISABLED_VIA_ENV",
|
|
39
|
+
"is_bugteam_disabled_via_env",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def is_bugteam_disabled_via_env() -> bool:
|
|
44
|
+
"""Check whether CLAUDE_REVIEWS_DISABLED opts the bug-audit family out of running.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
True when the env var contains the literal ``bugteam`` token
|
|
48
|
+
(comma-separated, case-insensitive, whitespace-tolerant).
|
|
49
|
+
"""
|
|
50
|
+
reviews_disabled_env_var_name = CLAUDE_REVIEWS_DISABLED_ENV_VAR_NAME
|
|
51
|
+
reviews_disabled_token_separator = CLAUDE_REVIEWS_DISABLED_TOKEN_SEPARATOR
|
|
52
|
+
reviews_disabled_bugteam_token = CLAUDE_REVIEWS_DISABLED_BUGTEAM_TOKEN
|
|
53
|
+
raw_value = os.environ.get(reviews_disabled_env_var_name, "")
|
|
54
|
+
all_disabled_tokens = frozenset(
|
|
55
|
+
each_raw_token.strip().lower()
|
|
56
|
+
for each_raw_token in raw_value.split(reviews_disabled_token_separator)
|
|
57
|
+
if each_raw_token.strip()
|
|
58
|
+
)
|
|
59
|
+
return reviews_disabled_bugteam_token in all_disabled_tokens
|
|
@@ -552,25 +552,6 @@ def test_check_wrapper_plumb_through_accepts_positional_or_keyword_forwarder() -
|
|
|
552
552
|
assert issues == []
|
|
553
553
|
|
|
554
554
|
|
|
555
|
-
def test_check_database_column_string_magic_dedupes_nested_function_tuples() -> None:
|
|
556
|
-
"""Regression: tuples inside nested FunctionDefs must produce one finding, not many.
|
|
557
|
-
|
|
558
|
-
The outer ast.walk previously enumerated every FunctionDef including nested
|
|
559
|
-
ones, then the inner ast.walk(each_node) walked the full subtree, so a tuple
|
|
560
|
-
inside a nested function was visited via every enclosing function. This must
|
|
561
|
-
surface exactly one finding per tuple site.
|
|
562
|
-
"""
|
|
563
|
-
source = (
|
|
564
|
-
"def outer():\n"
|
|
565
|
-
" def inner():\n"
|
|
566
|
-
' x = ("some_column_name", 42)\n'
|
|
567
|
-
" return x\n"
|
|
568
|
-
" return inner\n"
|
|
569
|
-
)
|
|
570
|
-
issues = gate_module.check_database_column_string_magic(source, "module.py")
|
|
571
|
-
assert len(issues) == 1, f"expected 1 finding, got {len(issues)}: {issues!r}"
|
|
572
|
-
|
|
573
|
-
|
|
574
555
|
def test_check_wrapper_plumb_through_skips_uppercase_js_extension() -> None:
|
|
575
556
|
"""Regression: case-insensitive filesystem (Windows, macOS) can yield
|
|
576
557
|
file paths like 'Foo.JS'. The skip predicate must normalize case so
|