claude-dev-env 1.93.1 → 1.94.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/_shared/pr-loop/CLAUDE.md +1 -0
- package/_shared/pr-loop/audit-contract.md +1 -1
- package/_shared/pr-loop/gh-payloads.md +3 -3
- package/_shared/pr-loop/post-audit-thread-contract.md +51 -0
- package/_shared/pr-loop/scripts/README.md +2 -2
- package/_shared/pr-loop/scripts/fix_hookspath.py +47 -12
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -69
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -374
- package/_shared/pr-loop/state-schema.md +3 -22
- package/bin/CLAUDE.md +1 -1
- package/bin/install.mjs +2 -7
- package/bin/install.test.mjs +10 -4
- package/hooks/blocking/CLAUDE.md +2 -0
- package/hooks/blocking/pii_commit_command.py +398 -0
- package/hooks/blocking/pii_payload_scan.py +133 -0
- package/hooks/blocking/pii_prevention_blocker.py +151 -449
- package/hooks/blocking/test_pii_prevention_blocker.py +299 -0
- package/hooks/blocking/test_verdict_directory_write_blocker.py +42 -7
- package/hooks/hooks_constants/CLAUDE.md +2 -2
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -2
- package/hooks/hooks_constants/local_identity.py +65 -15
- package/hooks/hooks_constants/pii_prevention_constants.py +16 -0
- package/hooks/hooks_constants/pr_description_enforcer_constants.py +1 -1
- package/hooks/hooks_constants/test_local_identity.py +68 -0
- package/package.json +1 -1
- package/scripts/CLAUDE.md +10 -1
- package/scripts/Get-SessionAccount.ps1 +210 -0
- package/scripts/tests/CLAUDE.md +15 -1
- package/scripts/tests/Get-SessionAccount.Tests.ps1 +350 -0
- package/skills/CLAUDE.md +3 -25
- package/skills/anthropic-plan/SKILL.md +1 -13
- package/skills/autoconverge/CLAUDE.md +5 -2
- package/skills/autoconverge/SKILL.md +112 -387
- package/skills/autoconverge/reference/CLAUDE.md +4 -1
- package/skills/autoconverge/reference/closing-report.md +9 -2
- package/skills/autoconverge/reference/convergence.md +26 -22
- package/skills/autoconverge/reference/headless-safety.md +44 -0
- package/skills/autoconverge/reference/multi-pr.md +88 -0
- package/skills/autoconverge/reference/self-closing-loop.md +84 -0
- package/skills/autoconverge/reference/stop-conditions.md +21 -13
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +87 -27
- package/skills/autoconverge/workflow/converge.contract.test.mjs +40 -10
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +179 -47
- package/skills/autoconverge/workflow/converge.fix-progress.test.mjs +1 -1
- package/skills/autoconverge/workflow/converge.mjs +284 -94
- package/skills/bugteam/CLAUDE.md +1 -1
- package/skills/bugteam/CONSTRAINTS.md +3 -3
- package/skills/bugteam/PROMPTS.md +8 -19
- package/skills/bugteam/SKILL.md +13 -14
- package/skills/bugteam/reference/CLAUDE.md +1 -1
- package/skills/bugteam/reference/audit-and-teammates.md +2 -2
- package/skills/bugteam/reference/copilot-gap-analysis.md +2 -0
- package/skills/bugteam/reference/github-pr-reviews.md +56 -38
- package/skills/bugteam/reference/team-setup.md +11 -11
- package/skills/bugteam/scripts/CLAUDE.md +6 -6
- package/skills/bugteam/scripts/README.md +20 -8
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +13 -1463
- package/skills/bugteam/scripts/bugteam_fix_hookspath.py +23 -358
- package/skills/bugteam/scripts/bugteam_preflight.py +13 -315
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +2 -3
- package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +34 -1053
- package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +30 -347
- package/skills/bugteam/scripts/test_bugteam_preflight.py +30 -305
- package/skills/copilot-finding-triage/SKILL.md +80 -28
- package/skills/copilot-finding-triage/reference/tier-rubric.md +70 -11
- package/skills/copilot-finding-triage/templates/notification.md +8 -3
- package/skills/everything-search/SKILL.md +1 -2
- package/skills/grokify/SKILL.md +58 -0
- package/skills/grokify/templates/handoff-template.md +92 -0
- package/skills/orchestrator/SKILL.md +12 -8
- package/skills/orchestrator-refresh/SKILL.md +3 -3
- package/skills/pr-converge/SKILL.md +132 -233
- package/skills/pr-converge/reference/convergence-gates.md +102 -66
- package/skills/pr-converge/reference/examples.md +37 -25
- package/skills/pr-converge/reference/fix-protocol.md +7 -7
- package/skills/pr-converge/reference/multi-pr-orchestration.md +10 -4
- package/skills/pr-converge/reference/per-tick.md +64 -41
- package/skills/pr-converge/reference/state-schema.md +27 -2
- package/skills/pr-converge/scripts/CLAUDE.md +8 -0
- package/skills/pr-converge/scripts/README.md +4 -3
- package/skills/pr-converge/scripts/_pr_converge_path_setup.py +23 -0
- package/skills/pr-converge/scripts/check_convergence.py +189 -645
- package/skills/pr-converge/scripts/check_convergence_gates.py +235 -0
- package/skills/pr-converge/scripts/check_convergence_thread_gates.py +219 -0
- package/skills/pr-converge/scripts/conftest.py +8 -0
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -0
- package/skills/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +36 -0
- package/skills/pr-converge/scripts/test__pr_converge_path_setup.py +26 -0
- package/skills/pr-converge/scripts/test_check_convergence.py +73 -228
- package/skills/pr-converge/scripts/test_check_convergence_contract.py +321 -0
- package/skills/pr-converge/scripts/test_check_convergence_gates.py +68 -0
- package/skills/pr-converge/scripts/test_check_convergence_thread_gates.py +75 -0
- package/skills/privacy-hygiene/SKILL.md +4 -3
- package/skills/reviewer-gates/SKILL.md +26 -8
- package/skills/session-log/SKILL.md +11 -12
- package/skills/session-tidy/SKILL.md +40 -30
- package/skills/skill-builder/CLAUDE.md +13 -10
- package/skills/skill-builder/SKILL.md +31 -31
- package/skills/skill-builder/references/CLAUDE.md +10 -6
- package/skills/skill-builder/references/delegation-map.md +13 -4
- package/skills/skill-builder/references/description-field.md +113 -0
- package/skills/skill-builder/references/self-audit-checklist.md +21 -4
- package/skills/skill-builder/references/skill-modularity.md +113 -0
- package/skills/skill-builder/references/skill-types.md +4 -0
- package/skills/skill-builder/templates/CLAUDE.md +4 -4
- package/skills/skill-builder/templates/gap-analysis.md +25 -1
- package/skills/skill-builder/workflows/CLAUDE.md +6 -4
- package/skills/skill-builder/workflows/improve-skill.md +17 -16
- package/skills/skill-builder/workflows/new-skill.md +34 -10
- package/skills/skill-builder/workflows/polish-skill.md +59 -43
- package/skills/usage-pause/SKILL.md +10 -14
- package/skills/bdd-protocol/CLAUDE.md +0 -26
- package/skills/bdd-protocol/SKILL.md +0 -30
- package/skills/bdd-protocol/references/CLAUDE.md +0 -10
- package/skills/bdd-protocol/references/anti-patterns.md +0 -26
- package/skills/bdd-protocol/references/example-mapping.md +0 -23
- package/skills/bg-agent/CLAUDE.md +0 -17
- package/skills/bg-agent/SKILL.md +0 -69
- package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_code_rules_gate_constants.py +0 -55
- package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_fix_hookspath_constants.py +0 -26
- package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_preflight_constants.py +0 -35
- package/skills/caveman/CLAUDE.md +0 -15
- package/skills/caveman/SKILL.md +0 -38
- package/skills/code/CLAUDE.md +0 -17
- package/skills/code/SKILL.md +0 -178
- package/skills/deep-research/CLAUDE.md +0 -17
- package/skills/deep-research/SKILL.md +0 -80
- package/skills/findbugs/CLAUDE.md +0 -20
- package/skills/findbugs/SKILL.md +0 -241
- package/skills/fixbugs/CLAUDE.md +0 -19
- package/skills/fixbugs/SKILL.md +0 -142
- package/skills/gh-paginate/CLAUDE.md +0 -18
- package/skills/gh-paginate/SKILL.md +0 -84
- package/skills/gotcha/CLAUDE.md +0 -33
- package/skills/gotcha/SKILL.md +0 -73
- package/skills/implement/CLAUDE.md +0 -27
- package/skills/implement/SKILL.md +0 -66
- package/skills/implement/scripts/CLAUDE.md +0 -22
- package/skills/implement/scripts/append_note.py +0 -133
- package/skills/implement/scripts/implement_scripts_constants/CLAUDE.md +0 -22
- package/skills/implement/scripts/implement_scripts_constants/__init__.py +0 -0
- package/skills/implement/scripts/implement_scripts_constants/notes_constants.py +0 -12
- package/skills/implement/scripts/test_append_note.py +0 -191
- package/skills/log-audit/CLAUDE.md +0 -20
- package/skills/log-audit/SKILL.md +0 -66
- package/skills/log-audit/reference/CLAUDE.md +0 -9
- package/skills/log-audit/reference/charter.md +0 -52
- package/skills/log-audit/scripts/CLAUDE.md +0 -27
- package/skills/log-audit/scripts/cluster_recurrences.py +0 -261
- package/skills/log-audit/scripts/collect_log_window.py +0 -199
- package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +0 -12
- package/skills/log-audit/scripts/log_audit_constants/__init__.py +0 -0
- package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +0 -23
- package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +0 -24
- package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +0 -49
- package/skills/log-audit/scripts/mine_copilot_findings.py +0 -302
- package/skills/log-audit/scripts/test_cluster_recurrences.py +0 -160
- package/skills/log-audit/scripts/test_collect_log_window.py +0 -111
- package/skills/log-audit/scripts/test_mine_copilot_findings.py +0 -126
- package/skills/logifix/CLAUDE.md +0 -36
- package/skills/logifix/SKILL.md +0 -69
- package/skills/logifix/scripts/CLAUDE.md +0 -16
- package/skills/logifix/scripts/logifix.ps1 +0 -205
- package/skills/monitor-open-prs/CLAUDE.md +0 -34
- package/skills/monitor-open-prs/SKILL.md +0 -88
- package/skills/monitor-open-prs/scripts/CLAUDE.md +0 -17
- package/skills/monitor-open-prs/scripts/discover_open_prs.py +0 -69
- package/skills/monitor-open-prs/scripts/test_discover_open_prs.py +0 -149
- package/skills/monitor-open-prs/test_skill_contract.py +0 -27
- package/skills/post-audit-findings/SKILL.md +0 -80
- package/skills/pr-consistency-audit/CLAUDE.md +0 -34
- package/skills/pr-consistency-audit/SKILL.md +0 -116
- package/skills/pr-consistency-audit/reference/CLAUDE.md +0 -16
- package/skills/pr-consistency-audit/reference/detection-rules.md +0 -96
- package/skills/pr-consistency-audit/reference/illustrations.md +0 -78
- package/skills/pr-fix-protocol/SKILL.md +0 -65
- package/skills/pr-review-responder/CLAUDE.md +0 -35
- package/skills/pr-review-responder/EXAMPLES.md +0 -590
- package/skills/pr-review-responder/PRINCIPLES.md +0 -533
- package/skills/pr-review-responder/README.md +0 -168
- package/skills/pr-review-responder/SKILL.md +0 -203
- package/skills/pr-review-responder/TESTING.md +0 -350
- package/skills/pr-scope-resolve/SKILL.md +0 -45
- package/skills/pre-compact/CLAUDE.md +0 -24
- package/skills/pre-compact/SKILL.md +0 -134
- package/skills/qbug/CLAUDE.md +0 -40
- package/skills/qbug/SKILL.md +0 -387
- package/skills/qbug/test_qbug_skill_audit_schema.py +0 -152
- package/skills/qbug/test_qbug_skill_post_fix_audit.py +0 -103
- package/skills/refine/CLAUDE.md +0 -44
- package/skills/refine/SKILL.md +0 -262
- package/skills/refine/templates/CLAUDE.md +0 -17
- package/skills/refine/templates/implementation-notes-template.html +0 -56
- package/skills/refine/templates/plan-template.md +0 -60
- package/skills/research-mode/CLAUDE.md +0 -35
- package/skills/research-mode/SKILL.md +0 -53
- package/skills/structure-prompt/CLAUDE.md +0 -42
- package/skills/structure-prompt/SKILL.md +0 -44
- package/skills/structure-prompt/reference/CLAUDE.md +0 -28
- package/skills/structure-prompt/reference/adversarial-tuning.md +0 -62
- package/skills/structure-prompt/reference/block-classification.md +0 -27
- package/skills/structure-prompt/reference/canonical-case.md +0 -48
- package/skills/structure-prompt/reference/citation-depth.md +0 -70
- package/skills/structure-prompt/reference/cleanup.md +0 -33
- package/skills/structure-prompt/reference/constraints.md +0 -33
- package/skills/structure-prompt/reference/directives.md +0 -37
- package/skills/structure-prompt/reference/examples.md +0 -72
- package/skills/structure-prompt/reference/instantiation.md +0 -51
- package/skills/structure-prompt/reference/output-contract.md +0 -72
- package/skills/structure-prompt/reference/per-category.md +0 -23
- package/skills/structure-prompt/reference/persona.md +0 -38
- package/skills/structure-prompt/reference/research.md +0 -33
- package/skills/structure-prompt/reference/structure.md +0 -28
- package/skills/verified-build/CLAUDE.md +0 -33
- package/skills/verified-build/SKILL.md +0 -33
|
@@ -8,6 +8,7 @@ Runtime documents and scripts shared by every PR-loop skill. Changes here affect
|
|
|
8
8
|
|---|---|
|
|
9
9
|
| `audit-contract.md` | Canonical finding schema (Shape A / Shape B) and loop contract; defines the JSON shapes every audit skill must emit |
|
|
10
10
|
| `audit-reply-template.md` | Canonical reply skeleton Claude posts to each unresolved review thread; single source of truth for reply structure |
|
|
11
|
+
| `post-audit-thread-contract.md` | Single source of truth for the `post_audit_thread.py` invocation string, exit-code table, and per-caller policy (bugteam exit 2 = hard blocker; autoconverge clean-audit failed post = recorded bypass) |
|
|
11
12
|
| `fix-protocol.md` | Ordered sequence a fix lens follows: read, capture SHA, TDD, apply, validate, self-audit, commit, push, reply + resolve |
|
|
12
13
|
| `gh-payloads.md` | How to build GitHub review and reply payloads via MCP tools; describes the one-review-per-loop pattern |
|
|
13
14
|
| `state-schema.md` | Fields each PR-loop workflow tracks across iterations; documents common fields and per-skill extensions |
|
|
@@ -120,7 +120,7 @@ Sequence:
|
|
|
120
120
|
2. Apply edits.
|
|
121
121
|
3. Run `py_compile` (or language-equivalent) on each modified file.
|
|
122
122
|
4. Compute `fix_diff` against pre-fix contents for the modified set.
|
|
123
|
-
5. Run `
|
|
123
|
+
5. Run `_shared/pr-loop/scripts/code_rules_gate.py` with explicit paths for every modified file.
|
|
124
124
|
6. Spawn a scoped audit of `fix_diff` with full A–P rigor, Shape A/B contract, adversarial pass, AND Haiku secondary in parallel (paranoid mode on post-fix).
|
|
125
125
|
7. Read the previous loop's outcome XML (`<worktree_path>/.bugteam-pr<N>-loop<L-1>.outcomes.xml`) and obtain its total finding count. If this is the first loop (L <= 1) or the file does not exist, skip this comparison. Compute the post-fix total: previous total minus bugs fixed in this round plus new violations found in the post-fix audit (step 6). If the post-fix total exceeds the previous total, flag all new findings as same-loop fix-targets and revise. An increase in total findings across loop transitions is a regression.
|
|
126
126
|
8. Any new findings become same-loop fix-targets. Internal iteration count increments by one.
|
|
@@ -55,9 +55,9 @@ user-facing output (chat reply to the user) rather than in the PR review body.
|
|
|
55
55
|
|
|
56
56
|
## Review POST failure
|
|
57
57
|
|
|
58
|
-
There is no fallback
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
There is no fallback payload to build. On retry exhaustion
|
|
59
|
+
`post_audit_thread.py` exits `2` and the orchestrator halts — see
|
|
60
|
+
[`./post-audit-thread-contract.md`](./post-audit-thread-contract.md) § Exit codes.
|
|
61
61
|
A hard blocker on the audit-posting path is a halt condition, not a degraded
|
|
62
62
|
flat-issue-comment fall-through.
|
|
63
63
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# post_audit_thread.py invocation contract
|
|
2
|
+
|
|
3
|
+
Single source of truth for how every PR-loop caller runs
|
|
4
|
+
[`scripts/post_audit_thread.py`](scripts/post_audit_thread.py) to post one
|
|
5
|
+
audit review per pass. The script posts an `APPROVE` review on `CLEAN` (an
|
|
6
|
+
empty findings list, zero inline comments) and a `REQUEST_CHANGES` review on
|
|
7
|
+
`DIRTY` (one inline anchored comment per finding). It reads its body skeleton
|
|
8
|
+
from [`audit-reply-template.md`](audit-reply-template.md) at runtime.
|
|
9
|
+
|
|
10
|
+
## Invocation
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
python "<pr-loop-scripts>/post_audit_thread.py" \
|
|
14
|
+
--skill <caller> \
|
|
15
|
+
--owner <owner> \
|
|
16
|
+
--repo <repo> \
|
|
17
|
+
--pr-number <N> \
|
|
18
|
+
--commit <head_sha> \
|
|
19
|
+
--state <CLEAN|DIRTY> \
|
|
20
|
+
--findings-json <path>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Capture `<head_sha>` with `git rev-parse HEAD` in the caller's cwd right before
|
|
24
|
+
the call, so the review attaches to the commit the audit scoped. `--findings-json`
|
|
25
|
+
points to a JSON file whose root is a list; on `CLEAN` the list is empty (`[]`).
|
|
26
|
+
|
|
27
|
+
## Exit codes
|
|
28
|
+
|
|
29
|
+
The script retries on its own with 1s / 4s / 16s backoff across four tries (one
|
|
30
|
+
plus three retries). It then exits:
|
|
31
|
+
|
|
32
|
+
| Exit | Meaning |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `0` | Review posted. The new review's `html_url` is on stdout. |
|
|
35
|
+
| `1` | User input error: bad arguments, malformed findings JSON, or a missing template. |
|
|
36
|
+
| `2` | Retry exhaustion: every try failed. |
|
|
37
|
+
|
|
38
|
+
## Per-caller policy
|
|
39
|
+
|
|
40
|
+
The same exit codes carry different weight per caller:
|
|
41
|
+
|
|
42
|
+
- **bugteam** — an exit `2` is a hard blocker. The lead exits with
|
|
43
|
+
`error: post_audit_thread retry exhausted`, and does not retry or fall back to
|
|
44
|
+
a flat issue comment.
|
|
45
|
+
- **autoconverge clean-audit** — any post that does not land (a denied post, an
|
|
46
|
+
error, or an agent that never ran) is a recorded bypass, not a blocker. Every
|
|
47
|
+
review lens already cleared the HEAD, so the CLEAN post is a record-keeping
|
|
48
|
+
artifact. The run records a bypass note, sets the convergence check's
|
|
49
|
+
`--bugteam-post-blocked` flag, and proceeds to the terminal Bugbot gate. Full
|
|
50
|
+
policy: [`../../skills/autoconverge/reference/stop-conditions.md`](../../skills/autoconverge/reference/stop-conditions.md)
|
|
51
|
+
§ "Clean-audit post bypassed".
|
|
@@ -9,11 +9,11 @@ Runnable helpers used by **bugteam**, **qbug**, **pr-converge**, and related ski
|
|
|
9
9
|
| `preflight.py` | Local checks before a PR-loop run (pytest discovery, optional pre-commit, hooksPath sanity). |
|
|
10
10
|
| `reviewer_availability.py` | Unified availability check for Copilot and Bugbot; reuses `copilot_quota.py` and `reviews_disabled.py` and exits 0 when the named `--reviewer` may be spawned. |
|
|
11
11
|
| `code_rules_gate.py` | CODE_RULES gate over PR-scoped diffs (`--base`, staged-only, path filters). |
|
|
12
|
-
| `fix_hookspath.py` | Repair `core.hooksPath` when it does not point at the packaged git-hooks tree. |
|
|
12
|
+
| `fix_hookspath.py` | Repair `core.hooksPath` when it does not point at the packaged git-hooks tree. Single home for unexpected non-empty git stderr (hard-fail `RuntimeError`); skill wrappers may call it later. |
|
|
13
13
|
| `grant_project_claude_permissions.py` / `revoke_project_claude_permissions.py` | Claude Code permission JSON helpers used during publish-style flows. |
|
|
14
14
|
| `_claude_permissions_common.py` | Shared implementation for the permission scripts. |
|
|
15
15
|
|
|
16
|
-
Configuration lives under `
|
|
16
|
+
Configuration lives under `pr_loop_shared_constants/` next to these scripts (for example `preflight_constants.py`, `code_rules_gate_constants.py`, `fix_hookspath_constants.py`).
|
|
17
17
|
|
|
18
18
|
## Gate semantics
|
|
19
19
|
|
|
@@ -53,6 +53,9 @@ def list_local_core_hooks_path_values(
|
|
|
53
53
|
Returns:
|
|
54
54
|
Non-empty stripped values from ``git config --local --get-all``, or
|
|
55
55
|
an empty list when no values are configured.
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
RuntimeError: When git exits non-zero with a non-empty stderr diagnostic.
|
|
56
59
|
"""
|
|
57
60
|
git_command = [
|
|
58
61
|
"git",
|
|
@@ -75,11 +78,9 @@ def list_local_core_hooks_path_values(
|
|
|
75
78
|
if completed_process.returncode != 0:
|
|
76
79
|
diagnostic_stderr = completed_process.stderr.strip()
|
|
77
80
|
if diagnostic_stderr:
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
f"
|
|
81
|
-
f"{diagnostic_stderr}",
|
|
82
|
-
file=sys.stderr,
|
|
81
|
+
raise RuntimeError(
|
|
82
|
+
f"git read of local core.hooksPath on {repository_root} "
|
|
83
|
+
f"exited {completed_process.returncode}: {diagnostic_stderr}"
|
|
83
84
|
)
|
|
84
85
|
return []
|
|
85
86
|
return [
|
|
@@ -99,8 +100,11 @@ def read_global_core_hooks_path(
|
|
|
99
100
|
forwarded to ``subprocess.run``.
|
|
100
101
|
|
|
101
102
|
Returns:
|
|
102
|
-
The stripped global value, or an empty string when
|
|
103
|
-
|
|
103
|
+
The stripped global value, or an empty string when the key is unset
|
|
104
|
+
(git exits non-zero with empty stderr).
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
RuntimeError: When git exits non-zero with a non-empty stderr diagnostic.
|
|
104
108
|
"""
|
|
105
109
|
git_command = list(ALL_GIT_GLOBAL_GET_CORE_HOOKS_PATH_COMMAND)
|
|
106
110
|
completed_process = subprocess.run(
|
|
@@ -115,10 +119,9 @@ def read_global_core_hooks_path(
|
|
|
115
119
|
if completed_process.returncode != 0:
|
|
116
120
|
diagnostic_stderr = completed_process.stderr.strip()
|
|
117
121
|
if diagnostic_stderr:
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
f"{completed_process.returncode}: {diagnostic_stderr}"
|
|
121
|
-
file=sys.stderr,
|
|
122
|
+
raise RuntimeError(
|
|
123
|
+
f"git read of global core.hooksPath exited "
|
|
124
|
+
f"{completed_process.returncode}: {diagnostic_stderr}"
|
|
122
125
|
)
|
|
123
126
|
return ""
|
|
124
127
|
return completed_process.stdout.strip()
|
|
@@ -280,7 +283,8 @@ def main(
|
|
|
280
283
|
forwarded to every git invocation and to the preflight rerun.
|
|
281
284
|
|
|
282
285
|
Returns:
|
|
283
|
-
Zero on success. Non-zero on the first failing git command
|
|
286
|
+
Zero on success. Non-zero on the first failing git command, on a
|
|
287
|
+
hard-fail git stderr diagnostic (caught ``RuntimeError``), or on a
|
|
284
288
|
non-zero preflight rerun exit code.
|
|
285
289
|
"""
|
|
286
290
|
arguments = parse_arguments(all_arguments)
|
|
@@ -302,6 +306,37 @@ def main(
|
|
|
302
306
|
file=sys.stderr,
|
|
303
307
|
)
|
|
304
308
|
return 1
|
|
309
|
+
try:
|
|
310
|
+
return _repair_hooks_path_then_rerun_preflight(
|
|
311
|
+
repository_root=repository_root,
|
|
312
|
+
canonical_hooks_directory=canonical_hooks_directory,
|
|
313
|
+
all_environment_overrides=all_environment_overrides,
|
|
314
|
+
)
|
|
315
|
+
except RuntimeError as runtime_error:
|
|
316
|
+
print(f"fix_hookspath: {runtime_error}", file=sys.stderr)
|
|
317
|
+
return 1
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _repair_hooks_path_then_rerun_preflight(
|
|
321
|
+
repository_root: Path,
|
|
322
|
+
canonical_hooks_directory: Path,
|
|
323
|
+
all_environment_overrides: dict[str, str] | None,
|
|
324
|
+
) -> int:
|
|
325
|
+
"""Apply local/global hooksPath repairs, then re-run preflight.
|
|
326
|
+
|
|
327
|
+
Args:
|
|
328
|
+
repository_root: Repository root used for local git config and preflight.
|
|
329
|
+
canonical_hooks_directory: Absolute path to the packaged git-hooks tree.
|
|
330
|
+
all_environment_overrides: Optional environment variable mapping
|
|
331
|
+
forwarded to every git invocation and to the preflight rerun.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
Zero on success. Non-zero on the first failing git write or on a
|
|
335
|
+
non-zero preflight rerun exit code.
|
|
336
|
+
|
|
337
|
+
Raises:
|
|
338
|
+
RuntimeError: When a git read exits non-zero with non-empty stderr.
|
|
339
|
+
"""
|
|
305
340
|
local_hooks_path_values = list_local_core_hooks_path_values(
|
|
306
341
|
repository_root,
|
|
307
342
|
all_environment_overrides,
|
|
@@ -483,16 +483,11 @@ def test_check_wrapper_plumb_through_exempts_test_files() -> None:
|
|
|
483
483
|
" return _helper('a', clean_name='b')\n"
|
|
484
484
|
)
|
|
485
485
|
shared_issues = gate_module.check_wrapper_plumb_through(source, "pkg/test_thing.py")
|
|
486
|
-
bugteam_gate = _load_bugteam_gate_module()
|
|
487
|
-
bugteam_issues = bugteam_gate.check_wrapper_plumb_through(source, "pkg/test_thing.py")
|
|
488
486
|
assert shared_issues == [], (
|
|
489
487
|
"a test_* function in a test-file path that calls a module-level helper "
|
|
490
488
|
"exposing an optional kwarg is not a wrapper; the shared gate must exempt "
|
|
491
489
|
"test files and emit zero findings"
|
|
492
490
|
)
|
|
493
|
-
assert bugteam_issues == [], (
|
|
494
|
-
"the bugteam gate copy must apply the identical test-file exemption"
|
|
495
|
-
)
|
|
496
491
|
|
|
497
492
|
|
|
498
493
|
def test_check_wrapper_plumb_through_still_flags_non_test_path_with_test_shape() -> None:
|
|
@@ -1245,8 +1240,6 @@ def test_check_wrapper_plumb_through_dedupes_nested_public_function_calls() -> N
|
|
|
1245
1240
|
assert len(issues) == 1, f"expected 1 finding, got {len(issues)}: {issues!r}"
|
|
1246
1241
|
|
|
1247
1242
|
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
1243
|
def test_check_wrapper_plumb_through_ignores_calls_nested_inside_delegate_arguments() -> None:
|
|
1251
1244
|
"""Regression: nested callees inside another call's arguments are not wrapper sites.
|
|
1252
1245
|
|
|
@@ -1766,68 +1759,6 @@ def test_main_blocks_banned_noun_on_added_lines_past_document_order(
|
|
|
1766
1759
|
)
|
|
1767
1760
|
|
|
1768
1761
|
|
|
1769
|
-
def _load_bugteam_gate_module() -> ModuleType:
|
|
1770
|
-
bugteam_scripts_dir = (
|
|
1771
|
-
Path(__file__).resolve().parents[4]
|
|
1772
|
-
/ "skills"
|
|
1773
|
-
/ "bugteam"
|
|
1774
|
-
/ "scripts"
|
|
1775
|
-
)
|
|
1776
|
-
if str(bugteam_scripts_dir) not in sys.path:
|
|
1777
|
-
sys.path.insert(0, str(bugteam_scripts_dir))
|
|
1778
|
-
module_path = bugteam_scripts_dir / "bugteam_code_rules_gate.py"
|
|
1779
|
-
spec = importlib.util.spec_from_file_location("bugteam_code_rules_gate", module_path)
|
|
1780
|
-
assert spec is not None
|
|
1781
|
-
assert spec.loader is not None
|
|
1782
|
-
module = importlib.util.module_from_spec(spec)
|
|
1783
|
-
spec.loader.exec_module(module)
|
|
1784
|
-
return module
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
def test_both_gates_classify_wrapper_plumb_through_identically() -> None:
|
|
1788
|
-
"""The bugteam and _shared gate copies of check_wrapper_plumb_through must
|
|
1789
|
-
return identical findings. A class method calling a module-level delegate
|
|
1790
|
-
is not a wrapper; both gates must exclude it rather than one emitting a
|
|
1791
|
-
false positive the other does not."""
|
|
1792
|
-
bugteam_gate = _load_bugteam_gate_module()
|
|
1793
|
-
class_method_calling_delegate = (
|
|
1794
|
-
"def fetch(target, *, retries=3):\n"
|
|
1795
|
-
" return target\n"
|
|
1796
|
-
"\n"
|
|
1797
|
-
"class MyService:\n"
|
|
1798
|
-
" def public_method(self, target):\n"
|
|
1799
|
-
" return fetch(target)\n"
|
|
1800
|
-
)
|
|
1801
|
-
nested_call_inside_delegate_argument = (
|
|
1802
|
-
"def delegate(value, *, retries=3):\n"
|
|
1803
|
-
" return value\n"
|
|
1804
|
-
"\n"
|
|
1805
|
-
"def helper(value):\n"
|
|
1806
|
-
" return value\n"
|
|
1807
|
-
"\n"
|
|
1808
|
-
"def public_caller(value):\n"
|
|
1809
|
-
" return delegate(helper(value))\n"
|
|
1810
|
-
)
|
|
1811
|
-
name_call_dropping_kwarg = (
|
|
1812
|
-
"def delegate(value, *, retries=3):\n"
|
|
1813
|
-
" return value\n"
|
|
1814
|
-
"\n"
|
|
1815
|
-
"def public_wrapper(value):\n"
|
|
1816
|
-
" return delegate(value)\n"
|
|
1817
|
-
)
|
|
1818
|
-
for each_source in (
|
|
1819
|
-
class_method_calling_delegate,
|
|
1820
|
-
nested_call_inside_delegate_argument,
|
|
1821
|
-
name_call_dropping_kwarg,
|
|
1822
|
-
):
|
|
1823
|
-
shared_issues = gate_module.check_wrapper_plumb_through(each_source, "module.py")
|
|
1824
|
-
bugteam_issues = bugteam_gate.check_wrapper_plumb_through(each_source, "module.py")
|
|
1825
|
-
assert shared_issues == bugteam_issues, (
|
|
1826
|
-
"both gate copies of check_wrapper_plumb_through must classify "
|
|
1827
|
-
f"identically; shared={shared_issues!r} bugteam={bugteam_issues!r}"
|
|
1828
|
-
)
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
1762
|
def test_check_wrapper_plumb_through_stays_under_function_length_threshold() -> None:
|
|
1832
1763
|
"""check_wrapper_plumb_through must stay under the enforcer's function-length
|
|
1833
1764
|
blocking threshold so editing it (e.g. aligning the two gate copies) does
|