claude-dev-env 1.37.0 → 1.38.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 +3 -0
- package/_shared/pr-loop/audit-contract.md +4 -3
- package/_shared/pr-loop/fix-protocol.md +2 -0
- package/_shared/pr-loop/gh-payloads.md +38 -37
- package/_shared/pr-loop/scripts/README.md +0 -1
- package/_shared/pr-loop/scripts/preflight.py +2 -1
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +2 -2
- package/_shared/pr-loop/scripts/tests/test_preflight.py +22 -0
- package/_shared/pr-loop/state-schema.md +10 -10
- package/agents/clean-coder.md +4 -0
- package/agents/code-quality-agent.md +23 -85
- package/agents/groq-coder.md +8 -6
- package/hooks/blocking/__init__.py +0 -0
- package/hooks/blocking/hedging_language_blocker.py +2 -2
- package/hooks/blocking/state_description_blocker.py +243 -0
- package/hooks/blocking/tdd_enforcer.py +94 -0
- package/hooks/blocking/test_hedging_language_blocker.py +1 -1
- package/hooks/blocking/test_state_description_blocker.py +618 -0
- package/hooks/blocking/test_tdd_enforcer.py +152 -0
- package/hooks/config/state_description_blocker_constants.py +130 -0
- package/hooks/hooks.json +10 -0
- package/package.json +1 -1
- package/rules/gh-paginate.md +4 -50
- package/rules/no-historical-clutter.md +57 -0
- package/scripts/config/groq_bugteam_config.py +13 -5
- package/skills/bugteam/CONSTRAINTS.md +20 -27
- package/skills/bugteam/EXAMPLES.md +1 -1
- package/skills/bugteam/PROMPTS.md +78 -42
- package/skills/bugteam/SKILL.md +76 -63
- package/skills/bugteam/SKILL_EVALS.md +12 -12
- package/skills/bugteam/reference/audit-and-teammates.md +21 -48
- package/skills/bugteam/reference/audit-contract.md +7 -7
- package/skills/bugteam/reference/github-pr-reviews.md +31 -31
- package/skills/bugteam/reference/team-setup.md +1 -1
- package/skills/bugteam/reference/teardown-publish-permissions.md +4 -4
- package/skills/copilot-review/SKILL.md +7 -14
- package/skills/findbugs/SKILL.md +2 -2
- package/skills/fixbugs/SKILL.md +1 -1
- package/skills/monitor-open-prs/SKILL.md +6 -6
- package/skills/pr-converge/SKILL.md +7 -6
- package/skills/pr-converge/reference/convergence-gates.md +46 -44
- package/skills/pr-converge/reference/examples.md +4 -4
- package/skills/pr-converge/reference/fix-protocol.md +8 -8
- package/skills/pr-converge/reference/multi-pr-orchestration.md +10 -10
- package/skills/pr-converge/reference/per-tick.md +24 -36
- package/skills/pr-converge/reference/stop-conditions.md +7 -7
- package/skills/pr-converge/scripts/README.md +65 -117
- package/skills/pr-review-responder/EXAMPLES.md +2 -2
- package/skills/pr-review-responder/PRINCIPLES.md +2 -8
- package/skills/pr-review-responder/README.md +7 -48
- package/skills/pr-review-responder/SKILL.md +2 -3
- package/skills/pr-review-responder/TESTING.md +8 -65
- package/skills/qbug/SKILL.md +10 -16
- package/_shared/pr-loop/scripts/config/gh_util_constants.py +0 -31
- package/_shared/pr-loop/scripts/gh_util.py +0 -193
- package/_shared/pr-loop/scripts/tests/test_gh_util.py +0 -257
- package/_shared/pr-loop/scripts/tests/test_gh_util_constants.py +0 -61
- package/skills/pr-converge/scripts/check_pr_mergeability.py +0 -78
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +0 -118
- package/skills/pr-converge/scripts/config/test_pr_converge_constants.py +0 -152
- package/skills/pr-converge/scripts/fetch_bugbot_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_bugbot_reviews.py +0 -57
- package/skills/pr-converge/scripts/fetch_claude_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_claude_reviews.py +0 -61
- package/skills/pr-converge/scripts/fetch_copilot_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +0 -61
- package/skills/pr-converge/scripts/mark_pr_ready.py +0 -54
- package/skills/pr-converge/scripts/post-bugbot-run.helpers.ps1 +0 -49
- package/skills/pr-converge/scripts/post-bugbot-run.ps1 +0 -33
- package/skills/pr-converge/scripts/reply_to_inline_comment.py +0 -84
- package/skills/pr-converge/scripts/request_copilot_review.py +0 -71
- package/skills/pr-converge/scripts/resolve_pr_head.py +0 -58
- package/skills/pr-converge/scripts/review_field_helpers.py +0 -43
- package/skills/pr-converge/scripts/reviewer_fetch_core.py +0 -153
- package/skills/pr-converge/scripts/reviewer_specs.py +0 -98
- package/skills/pr-converge/scripts/test_check_pr_mergeability.py +0 -126
- package/skills/pr-converge/scripts/test_fetch_bugbot_inline_comments.py +0 -443
- package/skills/pr-converge/scripts/test_fetch_bugbot_reviews.py +0 -299
- package/skills/pr-converge/scripts/test_fetch_claude_inline_comments.py +0 -485
- package/skills/pr-converge/scripts/test_fetch_claude_reviews.py +0 -368
- package/skills/pr-converge/scripts/test_fetch_copilot_inline_comments.py +0 -440
- package/skills/pr-converge/scripts/test_fetch_copilot_reviews.py +0 -366
- package/skills/pr-converge/scripts/test_mark_pr_ready.py +0 -69
- package/skills/pr-converge/scripts/test_post_bugbot_run.py +0 -195
- package/skills/pr-converge/scripts/test_reply_to_inline_comment.py +0 -159
- package/skills/pr-converge/scripts/test_request_copilot_review.py +0 -101
- package/skills/pr-converge/scripts/test_resolve_pr_head.py +0 -79
- package/skills/pr-converge/scripts/test_review_field_helpers.py +0 -80
- package/skills/pr-converge/scripts/test_reviewer_fetch_core.py +0 -448
- package/skills/pr-converge/scripts/test_reviewer_specs.py +0 -107
- package/skills/pr-converge/scripts/test_trigger_bugbot.py +0 -139
- package/skills/pr-converge/scripts/test_view_pr_context.py +0 -111
- package/skills/pr-converge/scripts/trigger_bugbot.py +0 -77
- package/skills/pr-converge/scripts/view_pr_context.py +0 -47
- package/skills/pr-review-responder/scripts/respond_to_reviews.py +0 -376
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
"""Configuration constants for the pr-converge skill scripts.
|
|
2
|
-
|
|
3
|
-
Path templates accept ``str.format(**kwargs)`` substitution; bugbot strings
|
|
4
|
-
match the literal phrasing the Cursor Bugbot reviewer emits.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import re
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
CURSOR_BOT_LOGIN: str = "cursor[bot]"
|
|
11
|
-
|
|
12
|
-
CURSOR_LOGIN_FILTER_SUBSTRING: str = "cursor"
|
|
13
|
-
|
|
14
|
-
COPILOT_REVIEWER_LOGIN: str = "copilot-pull-request-reviewer[bot]"
|
|
15
|
-
|
|
16
|
-
COPILOT_REVIEWER_REQUEST_ID: str = COPILOT_REVIEWER_LOGIN
|
|
17
|
-
|
|
18
|
-
COPILOT_LOGIN_FILTER_SUBSTRING: str = "copilot"
|
|
19
|
-
|
|
20
|
-
COPILOT_CLEAN_REVIEW_STATE: str = "APPROVED"
|
|
21
|
-
|
|
22
|
-
ALL_COPILOT_DIRTY_REVIEW_STATES: tuple[str, ...] = ("CHANGES_REQUESTED", "COMMENTED")
|
|
23
|
-
|
|
24
|
-
COPILOT_SOFT_DIRTY_REVIEW_STATE: str = "COMMENTED"
|
|
25
|
-
|
|
26
|
-
CLAUDE_REVIEWER_LOGIN: str = "claude[bot]"
|
|
27
|
-
|
|
28
|
-
CLAUDE_REVIEWER_REQUEST_ID: str = CLAUDE_REVIEWER_LOGIN
|
|
29
|
-
|
|
30
|
-
CLAUDE_LOGIN_FILTER_SUBSTRING: str = "claude"
|
|
31
|
-
|
|
32
|
-
CLAUDE_CLEAN_REVIEW_STATE: str = "APPROVED"
|
|
33
|
-
|
|
34
|
-
ALL_CLAUDE_DIRTY_REVIEW_STATES: tuple[str, ...] = ("CHANGES_REQUESTED", "COMMENTED")
|
|
35
|
-
|
|
36
|
-
CLAUDE_SOFT_DIRTY_REVIEW_STATE: str = "COMMENTED"
|
|
37
|
-
|
|
38
|
-
BUGBOT_DIRTY_BODY_REGEX: str = (
|
|
39
|
-
r"Cursor Bugbot has reviewed your changes and found \d+ potential issue"
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
GH_REVIEWS_PATH_TEMPLATE: str = (
|
|
43
|
-
"repos/{owner}/{repo}/pulls/{number}/reviews?per_page=100"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
GH_INLINE_COMMENTS_PATH_TEMPLATE: str = (
|
|
47
|
-
"repos/{owner}/{repo}/pulls/{number}/comments?per_page=100"
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
GH_PR_OBJECT_PATH_TEMPLATE: str = "repos/{owner}/{repo}/pulls/{number}"
|
|
51
|
-
|
|
52
|
-
GH_INLINE_COMMENT_REPLY_PATH_TEMPLATE: str = (
|
|
53
|
-
"repos/{owner}/{repo}/pulls/{number}/comments/{comment_id}/replies"
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
GH_REQUESTED_REVIEWERS_PATH_TEMPLATE: str = (
|
|
57
|
-
"repos/{owner}/{repo}/pulls/{number}/requested_reviewers"
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
GH_REQUESTED_REVIEWERS_FIELD_TEMPLATE: str = "reviewers[]={reviewer_id}"
|
|
61
|
-
|
|
62
|
-
BUGBOT_RUN_TRIGGER_PHRASE: str = "bugbot run\n"
|
|
63
|
-
|
|
64
|
-
BUGBOT_RUN_TEMPFILE_SUFFIX: str = ".md"
|
|
65
|
-
|
|
66
|
-
BUGBOT_RUN_TEMPFILE_PREFIX: str = "pr-converge-bugbot-run-"
|
|
67
|
-
|
|
68
|
-
PR_CONTEXT_FIELDS: str = "number,url,headRefOid,baseRefName,headRefName,isDraft"
|
|
69
|
-
|
|
70
|
-
MERGEABILITY_FIELDS: str = "mergeable,mergeStateStatus,headRefOid"
|
|
71
|
-
|
|
72
|
-
GH_FIELD_BODY_AT_PREFIX: str = "body=@"
|
|
73
|
-
|
|
74
|
-
GH_REPO_ARG_TEMPLATE: str = "{owner}/{repo}"
|
|
75
|
-
|
|
76
|
-
SKILL_REFLOW_MAXIMUM_WIDTH: int = 80
|
|
77
|
-
|
|
78
|
-
PR_CONVERGE_SKILL_PATH: Path = Path(__file__).resolve().parent.parent.parent / "SKILL.md"
|
|
79
|
-
|
|
80
|
-
MARKDOWN_CODE_FENCE_MARKER: str = "```"
|
|
81
|
-
|
|
82
|
-
YAML_FRONT_MATTER_DELIMITER: str = "---"
|
|
83
|
-
|
|
84
|
-
YAML_DESCRIPTION_PREFIX: str = "description: >-"
|
|
85
|
-
|
|
86
|
-
EXAMPLE_OPEN_TAG: str = "<example>"
|
|
87
|
-
|
|
88
|
-
EXAMPLE_CLOSE_TAG: str = "</example>"
|
|
89
|
-
|
|
90
|
-
BASH_FENCE_LANGUAGE: str = "bash"
|
|
91
|
-
|
|
92
|
-
BASH_LINE_CONTINUATION_SUFFIX: str = " \\"
|
|
93
|
-
|
|
94
|
-
BASH_CONTINUATION_INDENT: str = " "
|
|
95
|
-
|
|
96
|
-
REFLOW_FRONT_MATTER_ERROR: str = "expected YAML front matter starting with ---"
|
|
97
|
-
|
|
98
|
-
ORDERED_MARKDOWN_LIST_PATTERN: re.Pattern[str] = re.compile(
|
|
99
|
-
r"^(?P<leading_whitespace>\s*)(?P<marker>\d+\.\s)(?P<body>.*)$"
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
BULLET_MARKDOWN_LIST_PATTERN: re.Pattern[str] = re.compile(
|
|
103
|
-
r"^(?P<leading_whitespace>\s*)(?P<marker>[-*]\s)(?P<body>.*)$"
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
UNFINISHED_MARKDOWN_LINK_TARGET_PATTERN: re.Pattern[str] = re.compile(r"\]\([^)]*$")
|
|
107
|
-
|
|
108
|
-
MARKDOWN_HEADING_PATTERN: re.Pattern[str] = re.compile(r"^#{1,6}\s+.+$")
|
|
109
|
-
|
|
110
|
-
MARKDOWN_REFERENCE_DEFINITION_PATTERN: re.Pattern[str] = re.compile(r"^\[[^\]]+\]:\s+\S+")
|
|
111
|
-
|
|
112
|
-
BASH_LINE_CONTINUATION_MARKER_WIDTH: int = 2
|
|
113
|
-
|
|
114
|
-
CODE_FENCE_MARKER_LENGTH: int = 3
|
|
115
|
-
|
|
116
|
-
BASH_MINIMUM_SEGMENT_WIDTH: int = 1
|
|
117
|
-
|
|
118
|
-
LONG_ROW_PREVIEW_LIMIT: int = 20
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
"""Tests for pr_converge_constants.
|
|
2
|
-
|
|
3
|
-
Verifies that path templates accept the documented format substitutions
|
|
4
|
-
(owner, repo, number, comment_id) and the bugbot regex matches dirty review
|
|
5
|
-
bodies but not clean ones.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import importlib.util
|
|
11
|
-
import re
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from types import ModuleType
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def _load_module() -> ModuleType:
|
|
17
|
-
module_path = Path(__file__).parent / "pr_converge_constants.py"
|
|
18
|
-
spec = importlib.util.spec_from_file_location("pr_converge_constants", module_path)
|
|
19
|
-
assert spec is not None
|
|
20
|
-
assert spec.loader is not None
|
|
21
|
-
module = importlib.util.module_from_spec(spec)
|
|
22
|
-
spec.loader.exec_module(module)
|
|
23
|
-
return module
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
pr_converge_constants_module = _load_module()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def test_reviews_path_template_accepts_owner_repo_number() -> None:
|
|
30
|
-
rendered = pr_converge_constants_module.GH_REVIEWS_PATH_TEMPLATE.format(
|
|
31
|
-
owner="acme", repo="widget", number=42
|
|
32
|
-
)
|
|
33
|
-
assert rendered == "repos/acme/widget/pulls/42/reviews?per_page=100"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def test_inline_comments_path_template_accepts_owner_repo_number() -> None:
|
|
37
|
-
rendered = pr_converge_constants_module.GH_INLINE_COMMENTS_PATH_TEMPLATE.format(
|
|
38
|
-
owner="acme", repo="widget", number=42
|
|
39
|
-
)
|
|
40
|
-
assert rendered == "repos/acme/widget/pulls/42/comments?per_page=100"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def test_pr_object_path_template_accepts_owner_repo_number() -> None:
|
|
44
|
-
rendered = pr_converge_constants_module.GH_PR_OBJECT_PATH_TEMPLATE.format(
|
|
45
|
-
owner="acme", repo="widget", number=42
|
|
46
|
-
)
|
|
47
|
-
assert rendered == "repos/acme/widget/pulls/42"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_inline_comment_reply_path_template_accepts_all_substitutions() -> None:
|
|
51
|
-
rendered = (
|
|
52
|
-
pr_converge_constants_module.GH_INLINE_COMMENT_REPLY_PATH_TEMPLATE.format(
|
|
53
|
-
owner="acme", repo="widget", number=42, comment_id=12345
|
|
54
|
-
)
|
|
55
|
-
)
|
|
56
|
-
assert rendered == "repos/acme/widget/pulls/42/comments/12345/replies"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def test_bugbot_dirty_body_regex_distinguishes_findings_from_clean_bodies() -> None:
|
|
60
|
-
dirty_body = "Cursor Bugbot has reviewed your changes and found 3 potential issues."
|
|
61
|
-
clean_body = "Bugbot reviewed your changes and found no new issues!"
|
|
62
|
-
compiled_pattern = re.compile(pr_converge_constants_module.BUGBOT_DIRTY_BODY_REGEX)
|
|
63
|
-
dirty_match = compiled_pattern.search(dirty_body)
|
|
64
|
-
assert dirty_match is not None
|
|
65
|
-
assert "found 3 potential issue" in dirty_match.group(0)
|
|
66
|
-
assert compiled_pattern.search(clean_body) is None
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def test_cursor_bot_login_matches_github_login_string() -> None:
|
|
70
|
-
assert pr_converge_constants_module.CURSOR_BOT_LOGIN == "cursor[bot]"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_bugbot_run_trigger_phrase_ends_with_newline() -> None:
|
|
74
|
-
assert pr_converge_constants_module.BUGBOT_RUN_TRIGGER_PHRASE == "bugbot run\n"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def test_pr_context_fields_lists_documented_field_names() -> None:
|
|
78
|
-
fields_arg = pr_converge_constants_module.PR_CONTEXT_FIELDS
|
|
79
|
-
for required_field in (
|
|
80
|
-
"number",
|
|
81
|
-
"url",
|
|
82
|
-
"headRefOid",
|
|
83
|
-
"baseRefName",
|
|
84
|
-
"headRefName",
|
|
85
|
-
"isDraft",
|
|
86
|
-
):
|
|
87
|
-
assert required_field in fields_arg
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_gh_field_body_at_prefix_matches_gh_field_from_file_form() -> None:
|
|
91
|
-
assert pr_converge_constants_module.GH_FIELD_BODY_AT_PREFIX == "body=@"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def test_gh_repo_arg_template_renders_owner_slash_repo() -> None:
|
|
95
|
-
rendered = pr_converge_constants_module.GH_REPO_ARG_TEMPLATE.format(
|
|
96
|
-
owner="acme", repo="widget"
|
|
97
|
-
)
|
|
98
|
-
assert rendered == "acme/widget"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def test_copilot_reviewer_login_carries_bot_suffix() -> None:
|
|
102
|
-
assert (
|
|
103
|
-
pr_converge_constants_module.COPILOT_REVIEWER_LOGIN
|
|
104
|
-
== "copilot-pull-request-reviewer[bot]"
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def test_copilot_reviewer_request_id_reuses_login_constant() -> None:
|
|
109
|
-
request_id = pr_converge_constants_module.COPILOT_REVIEWER_REQUEST_ID
|
|
110
|
-
login = pr_converge_constants_module.COPILOT_REVIEWER_LOGIN
|
|
111
|
-
assert request_id == login
|
|
112
|
-
assert request_id is login
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def test_copilot_clean_review_state_is_approved() -> None:
|
|
116
|
-
assert pr_converge_constants_module.COPILOT_CLEAN_REVIEW_STATE == "APPROVED"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def test_copilot_dirty_review_states_lists_changes_requested_and_commented() -> None:
|
|
120
|
-
dirty_states = pr_converge_constants_module.ALL_COPILOT_DIRTY_REVIEW_STATES
|
|
121
|
-
assert "CHANGES_REQUESTED" in dirty_states
|
|
122
|
-
assert "COMMENTED" in dirty_states
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def test_copilot_soft_dirty_review_state_is_commented() -> None:
|
|
126
|
-
assert pr_converge_constants_module.COPILOT_SOFT_DIRTY_REVIEW_STATE == "COMMENTED"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def test_mergeability_fields_lists_required_field_names() -> None:
|
|
130
|
-
fields_arg = pr_converge_constants_module.MERGEABILITY_FIELDS
|
|
131
|
-
for required_field in ("mergeable", "mergeStateStatus", "headRefOid"):
|
|
132
|
-
assert required_field in fields_arg
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def test_requested_reviewers_path_template_accepts_owner_repo_number() -> None:
|
|
136
|
-
rendered = (
|
|
137
|
-
pr_converge_constants_module.GH_REQUESTED_REVIEWERS_PATH_TEMPLATE.format(
|
|
138
|
-
owner="acme", repo="widget", number=42
|
|
139
|
-
)
|
|
140
|
-
)
|
|
141
|
-
assert rendered == "repos/acme/widget/pulls/42/requested_reviewers"
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def test_requested_reviewers_field_template_accepts_reviewer_id() -> None:
|
|
145
|
-
rendered = (
|
|
146
|
-
pr_converge_constants_module.GH_REQUESTED_REVIEWERS_FIELD_TEMPLATE.format(
|
|
147
|
-
reviewer_id="copilot-pull-request-reviewer[bot]"
|
|
148
|
-
)
|
|
149
|
-
)
|
|
150
|
-
assert rendered == "reviewers[]=copilot-pull-request-reviewer[bot]"
|
|
151
|
-
|
|
152
|
-
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"""Fetch unaddressed Cursor Bugbot inline comments for the latest Bugbot review on a commit.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_inline_comments``
|
|
4
|
-
parameterised by ``bugbot_spec``. The ``fetch_bugbot_reviews`` call lives here
|
|
5
|
-
(rather than inside the core) so tests can patch it on this module to exercise
|
|
6
|
-
the inline-comments fetch in isolation.
|
|
7
|
-
|
|
8
|
-
Wraps the gh CLI invocation required by the gh-paginate rule for the comments
|
|
9
|
-
list: ``gh api`` on ``repos/{owner}/{repo}/pulls/{number}/comments`` with
|
|
10
|
-
``--paginate --slurp`` and external JSON handling.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
import argparse
|
|
16
|
-
import json
|
|
17
|
-
import sys
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
22
|
-
|
|
23
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
24
|
-
|
|
25
|
-
evict_cached_config_modules()
|
|
26
|
-
|
|
27
|
-
from fetch_bugbot_reviews import fetch_bugbot_reviews
|
|
28
|
-
from reviewer_fetch_core import fetch_reviewer_inline_comments
|
|
29
|
-
from reviewer_specs import bugbot_spec
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_bugbot_inline_comments(
|
|
33
|
-
*,
|
|
34
|
-
owner: str,
|
|
35
|
-
repo: str,
|
|
36
|
-
number: int,
|
|
37
|
-
current_head: str,
|
|
38
|
-
) -> list[dict[str, object]]:
|
|
39
|
-
"""Return Bugbot inline comments for the latest Bugbot review on ``current_head``."""
|
|
40
|
-
all_bugbot_reviews = fetch_bugbot_reviews(owner=owner, repo=repo, number=number)
|
|
41
|
-
return fetch_reviewer_inline_comments(
|
|
42
|
-
bugbot_spec,
|
|
43
|
-
owner=owner,
|
|
44
|
-
repo=repo,
|
|
45
|
-
number=number,
|
|
46
|
-
current_head=current_head,
|
|
47
|
-
all_reviews=all_bugbot_reviews,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def main() -> int:
|
|
52
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
53
|
-
parser.add_argument("--owner", required=True)
|
|
54
|
-
parser.add_argument("--repo", required=True)
|
|
55
|
-
parser.add_argument("--number", required=True, type=int)
|
|
56
|
-
parser.add_argument("--commit", required=True, dest="current_head")
|
|
57
|
-
parsed_arguments = parser.parse_args()
|
|
58
|
-
all_comments = fetch_bugbot_inline_comments(
|
|
59
|
-
owner=parsed_arguments.owner,
|
|
60
|
-
repo=parsed_arguments.repo,
|
|
61
|
-
number=parsed_arguments.number,
|
|
62
|
-
current_head=parsed_arguments.current_head,
|
|
63
|
-
)
|
|
64
|
-
json.dump(all_comments, sys.stdout)
|
|
65
|
-
sys.stdout.write("\n")
|
|
66
|
-
return 0
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if __name__ == "__main__":
|
|
70
|
-
sys.exit(main())
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"""Fetch Cursor Bugbot reviews newest-first, classified as dirty or clean.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_reviews`` parameterised
|
|
4
|
-
by ``bugbot_spec``. Wraps the gh CLI invocation required by the gh-paginate
|
|
5
|
-
rule: ``gh api '...?per_page=100' --paginate --slurp`` piped through external
|
|
6
|
-
Python JSON handling (instead of ``gh --jq``, which runs per-page and breaks
|
|
7
|
-
cross-page operations like sort/reverse - see GitHub CLI issue 10459).
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import argparse
|
|
13
|
-
import json
|
|
14
|
-
import sys
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
18
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
19
|
-
|
|
20
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
21
|
-
|
|
22
|
-
evict_cached_config_modules()
|
|
23
|
-
|
|
24
|
-
from reviewer_fetch_core import fetch_reviewer_reviews
|
|
25
|
-
from reviewer_specs import bugbot_spec
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def fetch_bugbot_reviews(
|
|
29
|
-
*,
|
|
30
|
-
owner: str,
|
|
31
|
-
repo: str,
|
|
32
|
-
number: int,
|
|
33
|
-
) -> list[dict[str, object]]:
|
|
34
|
-
"""Return Cursor Bugbot reviews newest-first, each with a classification."""
|
|
35
|
-
return fetch_reviewer_reviews(
|
|
36
|
-
bugbot_spec, owner=owner, repo=repo, number=number
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def main() -> int:
|
|
41
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
42
|
-
parser.add_argument("--owner", required=True)
|
|
43
|
-
parser.add_argument("--repo", required=True)
|
|
44
|
-
parser.add_argument("--number", required=True, type=int)
|
|
45
|
-
parsed_arguments = parser.parse_args()
|
|
46
|
-
all_reviews = fetch_bugbot_reviews(
|
|
47
|
-
owner=parsed_arguments.owner,
|
|
48
|
-
repo=parsed_arguments.repo,
|
|
49
|
-
number=parsed_arguments.number,
|
|
50
|
-
)
|
|
51
|
-
json.dump(all_reviews, sys.stdout)
|
|
52
|
-
sys.stdout.write("\n")
|
|
53
|
-
return 0
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if __name__ == "__main__":
|
|
57
|
-
sys.exit(main())
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"""Fetch unaddressed Claude inline comments for the latest Claude review on a commit.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_inline_comments``
|
|
4
|
-
parameterised by ``claude_spec``. The ``fetch_claude_reviews`` call lives here
|
|
5
|
-
(rather than inside the core) so tests can patch it on this module to exercise
|
|
6
|
-
the inline-comments fetch in isolation.
|
|
7
|
-
|
|
8
|
-
Wraps the gh CLI invocation required by the gh-paginate rule for the comments
|
|
9
|
-
list: ``gh api`` on ``repos/{owner}/{repo}/pulls/{number}/comments`` with
|
|
10
|
-
``--paginate --slurp`` and external JSON handling.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
import argparse
|
|
16
|
-
import json
|
|
17
|
-
import sys
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
22
|
-
|
|
23
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
24
|
-
|
|
25
|
-
evict_cached_config_modules()
|
|
26
|
-
|
|
27
|
-
from fetch_claude_reviews import fetch_claude_reviews
|
|
28
|
-
from reviewer_fetch_core import fetch_reviewer_inline_comments
|
|
29
|
-
from reviewer_specs import claude_spec
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_claude_inline_comments(
|
|
33
|
-
*,
|
|
34
|
-
owner: str,
|
|
35
|
-
repo: str,
|
|
36
|
-
number: int,
|
|
37
|
-
current_head: str,
|
|
38
|
-
) -> list[dict[str, object]]:
|
|
39
|
-
"""Return Claude inline comments for the latest Claude review on ``current_head``."""
|
|
40
|
-
all_claude_reviews = fetch_claude_reviews(owner=owner, repo=repo, number=number)
|
|
41
|
-
return fetch_reviewer_inline_comments(
|
|
42
|
-
claude_spec,
|
|
43
|
-
owner=owner,
|
|
44
|
-
repo=repo,
|
|
45
|
-
number=number,
|
|
46
|
-
current_head=current_head,
|
|
47
|
-
all_reviews=all_claude_reviews,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def main() -> int:
|
|
52
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
53
|
-
parser.add_argument("--owner", required=True)
|
|
54
|
-
parser.add_argument("--repo", required=True)
|
|
55
|
-
parser.add_argument("--number", required=True, type=int)
|
|
56
|
-
parser.add_argument("--commit", required=True, dest="current_head")
|
|
57
|
-
parsed_arguments = parser.parse_args()
|
|
58
|
-
all_comments = fetch_claude_inline_comments(
|
|
59
|
-
owner=parsed_arguments.owner,
|
|
60
|
-
repo=parsed_arguments.repo,
|
|
61
|
-
number=parsed_arguments.number,
|
|
62
|
-
current_head=parsed_arguments.current_head,
|
|
63
|
-
)
|
|
64
|
-
json.dump(all_comments, sys.stdout)
|
|
65
|
-
sys.stdout.write("\n")
|
|
66
|
-
return 0
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if __name__ == "__main__":
|
|
70
|
-
sys.exit(main())
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"""Fetch Claude reviewer-bot reviews newest-first, classified as dirty or clean.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_reviews`` parameterised
|
|
4
|
-
by ``claude_spec``. Classification follows the review's ``state`` field
|
|
5
|
-
(``APPROVED`` -> clean; ``CHANGES_REQUESTED`` -> dirty; ``COMMENTED`` with
|
|
6
|
-
non-empty body -> dirty; everything else -> clean) - see ``reviewer_specs``.
|
|
7
|
-
|
|
8
|
-
Wraps the gh CLI invocation required by the gh-paginate rule:
|
|
9
|
-
``gh api '...?per_page=100' --paginate --slurp`` piped through external Python
|
|
10
|
-
JSON handling (instead of ``gh --jq``, which runs per-page and breaks
|
|
11
|
-
cross-page operations like sort/reverse - see GitHub CLI issue 10459).
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
|
|
16
|
-
import argparse
|
|
17
|
-
import json
|
|
18
|
-
import sys
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
22
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
23
|
-
|
|
24
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
25
|
-
|
|
26
|
-
evict_cached_config_modules()
|
|
27
|
-
|
|
28
|
-
from reviewer_fetch_core import fetch_reviewer_reviews
|
|
29
|
-
from reviewer_specs import claude_spec
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_claude_reviews(
|
|
33
|
-
*,
|
|
34
|
-
owner: str,
|
|
35
|
-
repo: str,
|
|
36
|
-
number: int,
|
|
37
|
-
) -> list[dict[str, object]]:
|
|
38
|
-
"""Return Claude reviews newest-first, each with a classification."""
|
|
39
|
-
return fetch_reviewer_reviews(
|
|
40
|
-
claude_spec, owner=owner, repo=repo, number=number
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def main() -> int:
|
|
45
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
46
|
-
parser.add_argument("--owner", required=True)
|
|
47
|
-
parser.add_argument("--repo", required=True)
|
|
48
|
-
parser.add_argument("--number", required=True, type=int)
|
|
49
|
-
parsed_arguments = parser.parse_args()
|
|
50
|
-
all_reviews = fetch_claude_reviews(
|
|
51
|
-
owner=parsed_arguments.owner,
|
|
52
|
-
repo=parsed_arguments.repo,
|
|
53
|
-
number=parsed_arguments.number,
|
|
54
|
-
)
|
|
55
|
-
json.dump(all_reviews, sys.stdout)
|
|
56
|
-
sys.stdout.write("\n")
|
|
57
|
-
return 0
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if __name__ == "__main__":
|
|
61
|
-
sys.exit(main())
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
"""Fetch unaddressed Copilot inline comments for the latest Copilot review on a commit.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_inline_comments``
|
|
4
|
-
parameterised by ``copilot_spec``. The ``fetch_copilot_reviews`` call lives
|
|
5
|
-
here (rather than inside the core) so tests can patch it on this module to
|
|
6
|
-
exercise the inline-comments fetch in isolation.
|
|
7
|
-
|
|
8
|
-
Wraps the gh CLI invocation required by the gh-paginate rule for the comments
|
|
9
|
-
list: ``gh api`` on ``repos/{owner}/{repo}/pulls/{number}/comments`` with
|
|
10
|
-
``--paginate --slurp`` and external JSON handling.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
import argparse
|
|
16
|
-
import json
|
|
17
|
-
import sys
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
21
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
22
|
-
|
|
23
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
24
|
-
|
|
25
|
-
evict_cached_config_modules()
|
|
26
|
-
|
|
27
|
-
from fetch_copilot_reviews import fetch_copilot_reviews
|
|
28
|
-
from reviewer_fetch_core import fetch_reviewer_inline_comments
|
|
29
|
-
from reviewer_specs import copilot_spec
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_copilot_inline_comments(
|
|
33
|
-
*,
|
|
34
|
-
owner: str,
|
|
35
|
-
repo: str,
|
|
36
|
-
number: int,
|
|
37
|
-
current_head: str,
|
|
38
|
-
) -> list[dict[str, object]]:
|
|
39
|
-
"""Return Copilot inline comments for the latest Copilot review on ``current_head``."""
|
|
40
|
-
all_copilot_reviews = fetch_copilot_reviews(owner=owner, repo=repo, number=number)
|
|
41
|
-
return fetch_reviewer_inline_comments(
|
|
42
|
-
copilot_spec,
|
|
43
|
-
owner=owner,
|
|
44
|
-
repo=repo,
|
|
45
|
-
number=number,
|
|
46
|
-
current_head=current_head,
|
|
47
|
-
all_reviews=all_copilot_reviews,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def main() -> int:
|
|
52
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
53
|
-
parser.add_argument("--owner", required=True)
|
|
54
|
-
parser.add_argument("--repo", required=True)
|
|
55
|
-
parser.add_argument("--number", required=True, type=int)
|
|
56
|
-
parser.add_argument("--commit", required=True, dest="current_head")
|
|
57
|
-
parsed_arguments = parser.parse_args()
|
|
58
|
-
all_comments = fetch_copilot_inline_comments(
|
|
59
|
-
owner=parsed_arguments.owner,
|
|
60
|
-
repo=parsed_arguments.repo,
|
|
61
|
-
number=parsed_arguments.number,
|
|
62
|
-
current_head=parsed_arguments.current_head,
|
|
63
|
-
)
|
|
64
|
-
json.dump(all_comments, sys.stdout)
|
|
65
|
-
sys.stdout.write("\n")
|
|
66
|
-
return 0
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if __name__ == "__main__":
|
|
70
|
-
sys.exit(main())
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"""Fetch GitHub Copilot reviewer reviews newest-first, classified as dirty or clean.
|
|
2
|
-
|
|
3
|
-
Thin wrapper around ``reviewer_fetch_core.fetch_reviewer_reviews`` parameterised
|
|
4
|
-
by ``copilot_spec``. Classification follows the review's ``state`` field
|
|
5
|
-
(``APPROVED`` -> clean; ``CHANGES_REQUESTED`` -> dirty; ``COMMENTED`` with
|
|
6
|
-
non-empty body -> dirty; everything else -> clean) - see ``reviewer_specs``.
|
|
7
|
-
|
|
8
|
-
Wraps the gh CLI invocation required by the gh-paginate rule:
|
|
9
|
-
``gh api '...?per_page=100' --paginate --slurp`` piped through external Python
|
|
10
|
-
JSON handling (instead of ``gh --jq``, which runs per-page and breaks
|
|
11
|
-
cross-page operations like sort/reverse - see GitHub CLI issue 10459).
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
|
|
16
|
-
import argparse
|
|
17
|
-
import json
|
|
18
|
-
import sys
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
if str(Path(__file__).resolve().parent) not in sys.path:
|
|
22
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
23
|
-
|
|
24
|
-
from evict_cached_config_modules import evict_cached_config_modules
|
|
25
|
-
|
|
26
|
-
evict_cached_config_modules()
|
|
27
|
-
|
|
28
|
-
from reviewer_fetch_core import fetch_reviewer_reviews
|
|
29
|
-
from reviewer_specs import copilot_spec
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def fetch_copilot_reviews(
|
|
33
|
-
*,
|
|
34
|
-
owner: str,
|
|
35
|
-
repo: str,
|
|
36
|
-
number: int,
|
|
37
|
-
) -> list[dict[str, object]]:
|
|
38
|
-
"""Return Copilot reviews newest-first, each with a classification."""
|
|
39
|
-
return fetch_reviewer_reviews(
|
|
40
|
-
copilot_spec, owner=owner, repo=repo, number=number
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def main() -> int:
|
|
45
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
46
|
-
parser.add_argument("--owner", required=True)
|
|
47
|
-
parser.add_argument("--repo", required=True)
|
|
48
|
-
parser.add_argument("--number", required=True, type=int)
|
|
49
|
-
parsed_arguments = parser.parse_args()
|
|
50
|
-
all_reviews = fetch_copilot_reviews(
|
|
51
|
-
owner=parsed_arguments.owner,
|
|
52
|
-
repo=parsed_arguments.repo,
|
|
53
|
-
number=parsed_arguments.number,
|
|
54
|
-
)
|
|
55
|
-
json.dump(all_reviews, sys.stdout)
|
|
56
|
-
sys.stdout.write("\n")
|
|
57
|
-
return 0
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if __name__ == "__main__":
|
|
61
|
-
sys.exit(main())
|