claude-dev-env 1.83.0 → 1.85.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/audit-contract.md +24 -12
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
- package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -1
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +8 -0
- package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
- package/_shared/pr-loop/scripts/terminology_sweep.py +85 -39
- package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
- package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
- package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
- package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +94 -4
- package/agents/clean-coder.md +3 -0
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
- package/bin/install.mjs +16 -8
- package/bin/install.test.mjs +17 -6
- package/commands/CLAUDE.md +0 -1
- package/docs/CODE_RULES.md +1 -1
- package/hooks/blocking/CLAUDE.md +0 -4
- package/hooks/blocking/claude_md_orphan_file_blocker.py +1 -1
- package/hooks/blocking/code_rules_constants_config.py +5 -0
- package/hooks/blocking/code_rules_docstrings.py +133 -19
- package/hooks/blocking/code_rules_enforcer.py +4 -0
- package/hooks/blocking/code_rules_imports_logging.py +10 -6
- package/hooks/blocking/code_rules_magic_values.py +5 -0
- package/hooks/blocking/code_rules_naming_collection.py +15 -8
- package/hooks/blocking/code_rules_paired_test.py +3 -2
- package/hooks/blocking/code_rules_shared.py +34 -0
- package/hooks/blocking/code_rules_string_magic.py +1 -1
- package/hooks/blocking/code_rules_unused_imports.py +2 -2
- package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
- package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +29 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
- package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
- package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +24 -0
- package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
- package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
- package/hooks/blocking/test_code_rules_magic_values.py +54 -0
- package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
- package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
- package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
- package/hooks/hooks_constants/CLAUDE.md +0 -3
- package/hooks/hooks_constants/blocking_check_limits.py +4 -0
- package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
- package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
- package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
- package/hooks/validation/post_tool_use_dispatcher.py +1 -1
- package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
- package/hooks/workflow/CLAUDE.md +2 -8
- package/package.json +1 -1
- package/rules/CLAUDE.md +1 -1
- package/rules/docstring-prose-matches-implementation.md +1 -1
- package/rules/env-var-table-code-drift.md +1 -1
- package/rules/package-inventory-stale-entry.md +1 -1
- package/rules/paired-test-coverage.md +1 -1
- package/rules/plain-illustrative-docstrings.md +35 -1
- package/skills/CLAUDE.md +6 -1
- package/skills/_shared/pr-loop/CLAUDE.md +1 -0
- package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -0
- package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +45 -0
- package/skills/_shared/pr-loop/scripts/test_write_handoff.py +201 -0
- package/skills/_shared/pr-loop/scripts/write_handoff.py +309 -0
- package/skills/autoconverge/SKILL.md +82 -58
- package/skills/autoconverge/reference/closing-report.md +6 -6
- package/skills/autoconverge/reference/convergence.md +17 -15
- package/skills/autoconverge/reference/gotchas.md +6 -3
- package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
- package/skills/autoconverge/workflow/converge.contract.test.mjs +87 -13
- package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +1 -1
- package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
- package/skills/autoconverge/workflow/converge.mjs +71 -74
- package/skills/autoconverge/workflow/render_report.py +7 -11
- package/skills/bugteam/CLAUDE.md +1 -1
- package/skills/bugteam/PROMPTS.md +7 -6
- package/skills/bugteam/SKILL.md +25 -72
- package/skills/bugteam/reference/CLAUDE.md +1 -3
- package/skills/bugteam/reference/README.md +1 -1
- package/skills/bugteam/reference/audit-and-teammates.md +1 -1
- package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
- package/skills/bugteam/reference/team-setup.md +8 -7
- package/skills/bugteam/scripts/CLAUDE.md +0 -6
- package/skills/bugteam/scripts/README.md +0 -4
- package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
- package/skills/code/SKILL.md +2 -0
- package/skills/copilot-review/CLAUDE.md +1 -1
- package/skills/copilot-review/SKILL.md +25 -23
- package/skills/findbugs/CLAUDE.md +2 -2
- package/skills/findbugs/SKILL.md +22 -83
- package/skills/fixbugs/SKILL.md +2 -4
- package/skills/log-audit/CLAUDE.md +20 -0
- package/skills/log-audit/SKILL.md +68 -0
- package/skills/log-audit/reference/CLAUDE.md +9 -0
- package/skills/log-audit/reference/charter.md +52 -0
- package/skills/log-audit/scripts/CLAUDE.md +27 -0
- package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
- package/skills/log-audit/scripts/collect_log_window.py +199 -0
- package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
- package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
- package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
- package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
- package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
- package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
- package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
- package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
- package/skills/monitor-open-prs/SKILL.md +2 -2
- package/skills/post-audit-findings/SKILL.md +84 -0
- package/skills/pr-converge/CLAUDE.md +2 -0
- package/skills/pr-converge/SKILL.md +99 -60
- package/skills/pr-converge/reference/CLAUDE.md +1 -1
- package/skills/pr-converge/reference/convergence-gates.md +16 -19
- package/skills/pr-converge/reference/examples.md +5 -5
- package/skills/pr-converge/reference/fix-protocol.md +16 -43
- package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
- package/skills/pr-converge/reference/per-tick.md +24 -45
- package/skills/pr-converge/reference/state-schema.md +27 -0
- package/skills/pr-converge/scripts/README.md +3 -5
- package/skills/pr-fix-protocol/SKILL.md +70 -0
- package/skills/pr-loop-lifecycle/SKILL.md +73 -0
- package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
- package/skills/pr-scope-resolve/SKILL.md +48 -0
- package/skills/qbug/CLAUDE.md +4 -4
- package/skills/qbug/SKILL.md +46 -144
- package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
- package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
- package/skills/reviewer-gates/SKILL.md +96 -0
- package/skills/session-log/CLAUDE.md +7 -7
- package/skills/session-log/SKILL.md +27 -44
- package/skills/test_markdown_link_integrity.py +103 -0
- package/commands/doc-gist.md +0 -16
- package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
- package/hooks/blocking/conftest.py +0 -30
- package/hooks/blocking/md_path_exemptions.py +0 -224
- package/hooks/blocking/md_to_html_blocker.py +0 -155
- package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
- package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
- package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
- package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
- package/hooks/hooks_constants/html_companion_constants.py +0 -20
- package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
- package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
- package/hooks/workflow/doc_gist_auto_publish.py +0 -144
- package/hooks/workflow/md_to_html_companion.py +0 -358
- package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
- package/hooks/workflow/test_md_to_html_companion.py +0 -613
- package/skills/bugteam/reference/audit-contract.md +0 -163
- package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
- package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
- package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
- package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
- package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
- package/skills/doc-gist/CLAUDE.md +0 -25
- package/skills/doc-gist/SKILL.md +0 -97
- package/skills/doc-gist/references/CLAUDE.md +0 -9
- package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
- package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
- package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
- package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
- package/skills/doc-gist/references/examples/05-design-system.html +0 -629
- package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
- package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
- package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
- package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
- package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
- package/skills/doc-gist/references/examples/11-status-report.html +0 -528
- package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
- package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
- package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
- package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
- package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
- package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
- package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
- package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
- package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
- package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
- package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
- package/skills/doc-gist/references/examples/README.md +0 -5
- package/skills/doc-gist/scripts/CLAUDE.md +0 -27
- package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
- package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
- package/skills/doc-gist/scripts/gist_upload.py +0 -177
- package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
- /package/skills/{doc-gist/scripts/doc_gist_scripts_constants → log-audit/scripts/log_audit_constants}/__init__.py +0 -0
|
@@ -26,7 +26,7 @@ const CONFIG = {
|
|
|
26
26
|
copilotMaxPolls: 8,
|
|
27
27
|
sharedScripts: '$HOME/.claude/skills/pr-converge/scripts',
|
|
28
28
|
prLoopScripts: '$HOME/.claude/_shared/pr-loop/scripts',
|
|
29
|
-
bugteamRubric: '$HOME/.claude/
|
|
29
|
+
bugteamRubric: '$HOME/.claude/_shared/pr-loop/audit-contract.md',
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const REVIEWER_GATE_SENTINEL = 'CLAUDE_REVIEWER_GATE=autoconverge '
|
|
@@ -79,38 +79,32 @@ const convergeAgent = (prompt, options) =>
|
|
|
79
79
|
agent(`${HEADLESS_SAFETY_PREAMBLE}${worktreeDirective(activeRepoPath)}${prompt}`, options)
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
|
-
* Spawn a fresh git-utility Explore agent for a specific task.
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* @
|
|
82
|
+
* Spawn a fresh git-utility Explore agent for a specific task. The one task,
|
|
83
|
+
* 'preflight-git', bundles the three mechanical git reads into a single agent
|
|
84
|
+
* startup: it prints the PR HEAD SHA, fetches origin main so the review lenses
|
|
85
|
+
* diff against an up-to-date base, and polls GitHub mergeability, returning
|
|
86
|
+
* {sha, conflicting, fetched} in one structured result. The agent never edits
|
|
87
|
+
* code, so it runs on the cheapest model at low effort.
|
|
88
|
+
* @param {string} task the short task name ('preflight-git')
|
|
89
|
+
* @returns {Promise<object>} the structured PREFLIGHT_GIT_SCHEMA output
|
|
89
90
|
*/
|
|
90
|
-
function runGitTask(task
|
|
91
|
-
if (task
|
|
92
|
-
|
|
93
|
-
`Print the current HEAD SHA of ${prCoordinates}. Run exactly:\n` +
|
|
94
|
-
`gh api repos/${input.owner}/${input.repo}/pulls/${input.prNumber} --jq .head.sha\n` +
|
|
95
|
-
`Return the full 40-character SHA in the sha field. Do not modify any files.`,
|
|
96
|
-
{ label: 'git-utility', phase: 'Converge', schema: HEAD_SCHEMA, agentType: 'Explore' },
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
if (task === 'prefetch-main') {
|
|
100
|
-
return convergeAgent(
|
|
101
|
-
`Refresh the base ref for ${prCoordinates} so the parallel review lenses can diff against an up-to-date origin/main without each running its own fetch. Run exactly:\n` +
|
|
102
|
-
`git fetch origin main\n` +
|
|
103
|
-
`Do not edit, commit, push, rebase, or modify any files — fetch only.`,
|
|
104
|
-
{ label: 'git-utility', phase: 'Converge', agentType: 'Explore' },
|
|
105
|
-
)
|
|
91
|
+
function runGitTask(task) {
|
|
92
|
+
if (task !== 'preflight-git') {
|
|
93
|
+
throw new Error(`runGitTask has no handler for task ${task}`)
|
|
106
94
|
}
|
|
107
95
|
return convergeAgent(
|
|
108
|
-
`
|
|
109
|
-
`
|
|
96
|
+
`Run three read-only git preflight steps for ${prCoordinates}. Do not edit, commit, push, rebase, or modify any files — read only.\n\n` +
|
|
97
|
+
`STEP 1 — resolve HEAD. Print the current PR HEAD SHA. Run exactly:\n` +
|
|
98
|
+
` gh api repos/${input.owner}/${input.repo}/pulls/${input.prNumber} --jq .head.sha\n` +
|
|
99
|
+
`Return the full 40-character SHA in the sha field.\n\n` +
|
|
100
|
+
`STEP 2 — refresh the base ref so the parallel review lenses can diff against an up-to-date origin/main without each running its own fetch. Run exactly:\n` +
|
|
101
|
+
` git fetch origin main\n` +
|
|
102
|
+
`Return fetched:true when the fetch completed, fetched:false when it failed.\n\n` +
|
|
103
|
+
`STEP 3 — report whether the PR has merge conflicts with its base branch. GitHub computes mergeability asynchronously, so .mergeable is null right after a push until it finishes. Poll until it resolves: run\n` +
|
|
110
104
|
` gh api repos/${input.owner}/${input.repo}/pulls/${input.prNumber} --jq '{mergeable: .mergeable, state: .mergeable_state}'\n` +
|
|
111
|
-
`up to 5 times, 5 seconds apart (wait each 5-second interval inside this turn with the Monitor tool, per the WAITS AND POLLS rule above), stopping as soon as mergeable is true or false.\n
|
|
105
|
+
`up to 5 times, 5 seconds apart (wait each 5-second interval inside this turn with the Monitor tool, per the WAITS AND POLLS rule above), stopping as soon as mergeable is true or false.\n` +
|
|
112
106
|
`Return conflicting:true when mergeable is false or state is "dirty" (the branch conflicts with the base). Return conflicting:false when mergeable is true, or when mergeable stays null after the full poll budget — mergeability is unknown, so let the bug checks proceed rather than rebase on a guess.`,
|
|
113
|
-
{ label: 'git-utility', phase: 'Converge', schema:
|
|
107
|
+
{ label: 'git-utility', phase: 'Converge', schema: PREFLIGHT_GIT_SCHEMA, agentType: 'Explore', model: 'haiku', effort: 'low' },
|
|
114
108
|
)
|
|
115
109
|
}
|
|
116
110
|
|
|
@@ -558,11 +552,18 @@ const REVIEWER_AVAILABILITY_SCHEMA = {
|
|
|
558
552
|
required: ['copilot', 'bugbot'],
|
|
559
553
|
}
|
|
560
554
|
|
|
561
|
-
const
|
|
555
|
+
const PREFLIGHT_GIT_SCHEMA = {
|
|
562
556
|
type: 'object',
|
|
563
557
|
additionalProperties: false,
|
|
564
|
-
properties: {
|
|
565
|
-
|
|
558
|
+
properties: {
|
|
559
|
+
sha: { type: 'string', description: 'the full 40-character PR HEAD SHA' },
|
|
560
|
+
conflicting: {
|
|
561
|
+
type: 'boolean',
|
|
562
|
+
description: 'true only when GitHub reports the PR branch conflicts with its base (mergeable:false or mergeable_state:dirty); false when it merges cleanly or mergeability could not be computed',
|
|
563
|
+
},
|
|
564
|
+
fetched: { type: 'boolean', description: 'true when git fetch origin main completed successfully' },
|
|
565
|
+
},
|
|
566
|
+
required: ['sha', 'conflicting', 'fetched'],
|
|
566
567
|
}
|
|
567
568
|
|
|
568
569
|
const FIX_SCHEMA = {
|
|
@@ -602,18 +603,6 @@ const REPAIR_EDIT_SCHEMA = {
|
|
|
602
603
|
required: ['edited', 'rebased', 'resolvedWithoutCommit', 'summary'],
|
|
603
604
|
}
|
|
604
605
|
|
|
605
|
-
const MERGE_CONFLICT_SCHEMA = {
|
|
606
|
-
type: 'object',
|
|
607
|
-
additionalProperties: false,
|
|
608
|
-
properties: {
|
|
609
|
-
conflicting: {
|
|
610
|
-
type: 'boolean',
|
|
611
|
-
description: 'true only when GitHub reports the PR branch conflicts with its base (mergeable:false or mergeable_state:dirty); false when it merges cleanly or mergeability could not be computed',
|
|
612
|
-
},
|
|
613
|
-
},
|
|
614
|
-
required: ['conflicting'],
|
|
615
|
-
}
|
|
616
|
-
|
|
617
606
|
const CONFLICT_EDIT_SCHEMA = {
|
|
618
607
|
type: 'object',
|
|
619
608
|
additionalProperties: false,
|
|
@@ -1003,10 +992,10 @@ function commitNeedsCodeRecovery(commitResult) {
|
|
|
1003
992
|
|
|
1004
993
|
/**
|
|
1005
994
|
* Decide whether a resolved HEAD SHA is safe to spawn lenses against. A dead
|
|
1006
|
-
*
|
|
995
|
+
* preflight-git agent or a malformed result yields a falsy SHA; spawning lenses
|
|
1007
996
|
* against it interpolates the literal string 'HEAD undefined' into their prompts
|
|
1008
997
|
* and produces a spurious clean verdict on a non-existent commit.
|
|
1009
|
-
* @param {string|null|undefined} resolvedHead the SHA from the git-utility '
|
|
998
|
+
* @param {string|null|undefined} resolvedHead the SHA from the git-utility 'preflight-git' task
|
|
1010
999
|
* @returns {boolean} true only when the SHA is a non-empty string
|
|
1011
1000
|
*/
|
|
1012
1001
|
function isResolvedHeadUsable(resolvedHead) {
|
|
@@ -1014,12 +1003,12 @@ function isResolvedHeadUsable(resolvedHead) {
|
|
|
1014
1003
|
}
|
|
1015
1004
|
|
|
1016
1005
|
/**
|
|
1017
|
-
* Decide whether the pre-flight
|
|
1018
|
-
* conflict with its base. A dead
|
|
1006
|
+
* Decide whether the pre-flight mergeability probe found the PR branch in
|
|
1007
|
+
* conflict with its base. A dead preflight agent (null/undefined result) reports
|
|
1019
1008
|
* not-conflicting so the run proceeds straight to the bug checks rather than
|
|
1020
|
-
* force-pushing a rebase on a verdict that does not exist — a transient
|
|
1009
|
+
* force-pushing a rebase on a verdict that does not exist — a transient probe
|
|
1021
1010
|
* failure must never trigger a destructive rebase.
|
|
1022
|
-
* @param {object|null|undefined} mergeState the git-utility '
|
|
1011
|
+
* @param {object|null|undefined} mergeState the git-utility 'preflight-git' task result carrying the conflicting field
|
|
1023
1012
|
* @returns {boolean} true only when the check reported conflicting:true
|
|
1024
1013
|
*/
|
|
1025
1014
|
function isMergeConflicting(mergeState) {
|
|
@@ -1370,7 +1359,7 @@ function runCopilotGate(head) {
|
|
|
1370
1359
|
`Copilot can run out of usage. When the newest Copilot review on HEAD carries an out-of-usage notice — a body stating Copilot was unable to review because the user who requested the review has reached their quota limit, or any equivalent quota / premium-request / usage-limit exhaustion message rather than an actual code review — Copilot is down for this run: return {sha:${'`'}${head}${'`'}, clean:true, down:true, findings:[]} and stop. Do NOT re-request a review, do NOT keep polling, and do NOT treat the notice as a finding.\n\n` +
|
|
1371
1360
|
`1. Read any existing Copilot review on HEAD first: python "${CONFIG.sharedScripts}/fetch_copilot_reviews.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber}. This lists every Copilot review across all commits newest-first; only count entries whose commit_id starts with ${head}. If the newest such HEAD-scoped Copilot review is the out-of-usage notice above -> return the down result and stop. A notice on any earlier commit is NOT down: ignore it and continue. With no Copilot review on HEAD, skip a duplicate request: python "${CONFIG.sharedScripts}/check_pending_reviews.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} --user copilot. Exit 0 means a request is already pending; otherwise request one:\n` +
|
|
1372
1361
|
` ${REVIEWER_GATE_SENTINEL}gh api --method POST repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/requested_reviewers -f 'reviewers[]=copilot-pull-request-reviewer[bot]'\n` +
|
|
1373
|
-
`2. Poll for Copilot's review on HEAD ${head}: up to ${CONFIG.copilotMaxPolls} attempts, 360 seconds apart (wait each 360-second interval inside this turn with the Monitor tool, per the WAITS AND POLLS rule above; if the attempt budget is spent with no review on HEAD, return down: true). Each attempt: python "${CONFIG.sharedScripts}/fetch_copilot_reviews.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} for the top-level review state, plus gh api "repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/comments" --paginate --slurp for inline comment ids (Copilot's login contains "copilot", case-insensitive). Only count entries whose commit_id starts with ${head}.\n` +
|
|
1362
|
+
`2. Poll for Copilot's review on HEAD ${head}: up to ${CONFIG.copilotMaxPolls} attempts, 360 seconds apart (wait each 360-second interval inside this turn with the Monitor tool, per the WAITS AND POLLS rule above; if the attempt budget is spent with no review on HEAD, return the full down result {sha:${'`'}${head}${'`'}, clean:false, down:true, findings:[]}). Each attempt: python "${CONFIG.sharedScripts}/fetch_copilot_reviews.py" --owner ${input.owner} --repo ${input.repo} --pr-number ${input.prNumber} for the top-level review state, plus gh api "repos/${input.owner}/${input.repo}/pulls/${input.prNumber}/comments" --paginate --slurp for inline comment ids (Copilot's login contains "copilot", case-insensitive). Only count entries whose commit_id starts with ${head}.\n` +
|
|
1374
1363
|
` - Out-of-usage notice on HEAD -> return the down result above (clean:true, down:true) and stop.\n` +
|
|
1375
1364
|
` - Copilot review present on HEAD whose state is APPROVED, or COMMENTED with no inline findings -> a clean pass: return {sha:${'`'}${head}${'`'}, clean:true, down:false, findings:[]}.\n` +
|
|
1376
1365
|
` - Copilot findings on HEAD -> return them (each with its inline comment id in replyToCommentId; category 'code-standard' for pure CODE_RULES/style violations with no behavioral impact, 'bug' otherwise), clean:false, down:false.\n` +
|
|
@@ -1432,20 +1421,22 @@ async function repairConvergence(head, failures) {
|
|
|
1432
1421
|
|
|
1433
1422
|
/**
|
|
1434
1423
|
* Pre-flight conflict resolution: when the PR branch conflicts with its base,
|
|
1435
|
-
* rebase it clean before the bug checks run —
|
|
1436
|
-
*
|
|
1437
|
-
*
|
|
1438
|
-
*
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
*
|
|
1442
|
-
*
|
|
1424
|
+
* rebase it clean before the bug checks run — edit (clean-coder rebases and
|
|
1425
|
+
* resolves, no push) -> verify (code-verifier binds a verdict to the rebased
|
|
1426
|
+
* tree) -> commit (clean-coder force-with-lease pushes). The conflict decision
|
|
1427
|
+
* comes from the merged 'preflight-git' probe the caller already ran, so this
|
|
1428
|
+
* function spawns no mergeability agent of its own. Returns the post-rebase
|
|
1429
|
+
* HEAD so the first converge round runs its lenses on the conflict-free diff.
|
|
1430
|
+
* A non-conflicting PR, a rebase the edit step declined, or a failed verdict
|
|
1431
|
+
* returns the unchanged HEAD so the run proceeds to the bug checks unchanged.
|
|
1432
|
+
* A mid-run conflict (origin/main advancing later) is still caught by the
|
|
1433
|
+
* FINALIZE convergence repair, which also rebases.
|
|
1443
1434
|
* @param {string} head PR HEAD SHA before any rebase
|
|
1435
|
+
* @param {boolean} isConflicting the isMergeConflicting decision over the preflight-git result
|
|
1444
1436
|
* @returns {Promise<string>} the HEAD SHA after a successful rebase push, or the unchanged head
|
|
1445
1437
|
*/
|
|
1446
|
-
async function resolveMergeConflicts(head) {
|
|
1447
|
-
|
|
1448
|
-
if (!isMergeConflicting(mergeState)) return head
|
|
1438
|
+
async function resolveMergeConflicts(head, isConflicting) {
|
|
1439
|
+
if (!isConflicting) return head
|
|
1449
1440
|
log(`Pre-flight: ${prCoordinates} conflicts with origin/main — rebasing clean before the bug checks`)
|
|
1450
1441
|
const editResult = await runCodeEditorTask('conflict-edit', { head })
|
|
1451
1442
|
if (editResult?.rebased !== true) return head
|
|
@@ -1655,24 +1646,24 @@ let reuseNote = null
|
|
|
1655
1646
|
let reviewerAvailability = null
|
|
1656
1647
|
const deferredPrs = []
|
|
1657
1648
|
|
|
1658
|
-
const
|
|
1659
|
-
if (isResolvedHeadUsable(
|
|
1660
|
-
await resolveMergeConflicts(
|
|
1649
|
+
const preflight = await runGitTask('preflight-git')
|
|
1650
|
+
if (isResolvedHeadUsable(preflight?.sha)) {
|
|
1651
|
+
head = await resolveMergeConflicts(preflight.sha, isMergeConflicting(preflight))
|
|
1661
1652
|
}
|
|
1662
1653
|
|
|
1663
1654
|
log('Reuse pass: scanning the full diff for certain, behaviorally identical, autonomously implementable reuse improvements before convergence')
|
|
1664
|
-
|
|
1665
|
-
const
|
|
1666
|
-
if (isResolvedHeadUsable(reuseHead)) {
|
|
1667
|
-
await runGitTask('prefetch-main')
|
|
1668
|
-
const reuse = await runReuseAuditPass(reuseHead)
|
|
1655
|
+
if (isResolvedHeadUsable(head)) {
|
|
1656
|
+
const reuse = await runReuseAuditPass(head)
|
|
1669
1657
|
const reuseFindings = reuse?.findings || []
|
|
1670
1658
|
if (reuseFindings.length > 0) {
|
|
1671
1659
|
log(`Reuse pass: ${reuseFindings.length} qualifying reuse improvement(s) — applying before convergence`)
|
|
1672
|
-
const reuseFix = await applyFixes(
|
|
1660
|
+
const reuseFix = await applyFixes(head, reuseFindings, 'reuse-pass')
|
|
1673
1661
|
reuseNote = reuseFix?.pushed === true
|
|
1674
1662
|
? `${reuseFindings.length} reuse improvement(s) applied before convergence (${reuseFix.newSha?.slice(0, SHA_COMPARISON_PREFIX_LENGTH)})`
|
|
1675
1663
|
: `${reuseFindings.length} reuse improvement(s) identified before convergence but not landed — the code-review lens re-surfaces any that remain`
|
|
1664
|
+
if (reuseFix?.pushed === true) {
|
|
1665
|
+
head = isResolvedHeadUsable(reuseFix.newSha) ? reuseFix.newSha : null
|
|
1666
|
+
}
|
|
1676
1667
|
} else {
|
|
1677
1668
|
log('Reuse pass: no reuse case cleared all three criteria — proceeding to convergence')
|
|
1678
1669
|
}
|
|
@@ -1684,13 +1675,14 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
1684
1675
|
iterations += 1
|
|
1685
1676
|
if (phase === 'CONVERGE') {
|
|
1686
1677
|
rounds += 1
|
|
1687
|
-
const headResult = await runGitTask('resolve-head')
|
|
1688
|
-
head = headResult?.sha
|
|
1689
1678
|
if (!isResolvedHeadUsable(head)) {
|
|
1690
|
-
|
|
1679
|
+
const refreshedPreflight = await runGitTask('preflight-git')
|
|
1680
|
+
head = isResolvedHeadUsable(refreshedPreflight?.sha) ? refreshedPreflight.sha : null
|
|
1681
|
+
}
|
|
1682
|
+
if (!isResolvedHeadUsable(head)) {
|
|
1683
|
+
log(`Round ${rounds}: preflight-git agent returned no SHA — retrying without spawning lenses`)
|
|
1691
1684
|
continue
|
|
1692
1685
|
}
|
|
1693
|
-
await runGitTask('prefetch-main')
|
|
1694
1686
|
reviewerAvailability = await runReviewerAvailabilityCheck()
|
|
1695
1687
|
const isBugbotDownPreSpawn = resolveReviewerDown(reviewerAvailability?.bugbot, input.bugbotDisabled || false)
|
|
1696
1688
|
log(`Round ${rounds}: parallel Bugbot + code-review + bug-audit on ${head?.slice(0, 7)}`)
|
|
@@ -1703,6 +1695,7 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
1703
1695
|
const roundOutcome = resolveRoundOutcome(lenses)
|
|
1704
1696
|
if (roundOutcome.allLensesDead) {
|
|
1705
1697
|
log(`Round ${rounds}: every lens agent died — retrying without posting a clean artifact`)
|
|
1698
|
+
head = null
|
|
1706
1699
|
continue
|
|
1707
1700
|
}
|
|
1708
1701
|
const findings = roundOutcome.findings
|
|
@@ -1730,10 +1723,12 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
1730
1723
|
: `fix lens landed no push for ${findings.length} finding(s) on HEAD ${head}`
|
|
1731
1724
|
break
|
|
1732
1725
|
}
|
|
1726
|
+
head = null
|
|
1733
1727
|
continue
|
|
1734
1728
|
}
|
|
1735
1729
|
if (!roundOutcome.roundClean) {
|
|
1736
1730
|
log(`Round ${rounds}: a lens reported not-clean with no findings on ${head?.slice(0, 7)} — re-converging without a clean artifact`)
|
|
1731
|
+
head = null
|
|
1737
1732
|
continue
|
|
1738
1733
|
}
|
|
1739
1734
|
log(`Round ${rounds}: all lenses clean on ${head?.slice(0, 7)} — posting clean audit artifact`)
|
|
@@ -1790,6 +1785,7 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
1790
1785
|
: `copilot fix lens landed no push for ${copilotOutcome.findings.length} finding(s) on HEAD ${head}`
|
|
1791
1786
|
break
|
|
1792
1787
|
}
|
|
1788
|
+
head = null
|
|
1793
1789
|
phase = 'CONVERGE'
|
|
1794
1790
|
continue
|
|
1795
1791
|
}
|
|
@@ -1817,6 +1813,7 @@ while (iterations < CONFIG.maxIterations) {
|
|
|
1817
1813
|
}
|
|
1818
1814
|
log(`Convergence check failed: ${convergenceOutcome.failures.join('; ')} — repairing then re-converging`)
|
|
1819
1815
|
await repairConvergence(head, convergenceOutcome.failures)
|
|
1816
|
+
head = null
|
|
1820
1817
|
phase = 'CONVERGE'
|
|
1821
1818
|
continue
|
|
1822
1819
|
}
|
|
@@ -17,8 +17,7 @@ from autoconverge_report_constants.render_report_constants import (
|
|
|
17
17
|
DEFAULT_FINDING_CATEGORY,
|
|
18
18
|
DEFAULT_FINDING_SEVERITY,
|
|
19
19
|
DEFAULT_ISSUE_ICON,
|
|
20
|
-
|
|
21
|
-
HTML_HEAD_TEMPLATE,
|
|
20
|
+
HTML_TITLE_AND_STYLE_TEMPLATE,
|
|
22
21
|
HTML_STYLE_BLOCK,
|
|
23
22
|
ISO_DATE_LENGTH,
|
|
24
23
|
ISSUE_CLASS_FIELD_AFTER_LINES,
|
|
@@ -890,7 +889,9 @@ def render_report_html(
|
|
|
890
889
|
generated_date: ISO date string derived from the journal timestamp.
|
|
891
890
|
|
|
892
891
|
Returns:
|
|
893
|
-
A
|
|
892
|
+
A page-content HTML string (a title, a style block, and the body
|
|
893
|
+
markup) with no surrounding <!DOCTYPE>, <html>, <head>, or <body>
|
|
894
|
+
tags, ready for the Artifact tool to wrap and publish.
|
|
894
895
|
"""
|
|
895
896
|
short_sha_length = SHORT_SHA_LENGTH
|
|
896
897
|
pr_number = pr_metadata.number
|
|
@@ -899,7 +900,7 @@ def render_report_html(
|
|
|
899
900
|
final_sha_short = pr_metadata.final_sha[:short_sha_length]
|
|
900
901
|
round_count = pr_metadata.round_count
|
|
901
902
|
|
|
902
|
-
|
|
903
|
+
title_and_style_html = HTML_TITLE_AND_STYLE_TEMPLATE.format(
|
|
903
904
|
pr_number=pr_number,
|
|
904
905
|
style_block=HTML_STYLE_BLOCK,
|
|
905
906
|
)
|
|
@@ -933,15 +934,10 @@ def render_report_html(
|
|
|
933
934
|
)
|
|
934
935
|
|
|
935
936
|
return (
|
|
936
|
-
f"{
|
|
937
|
-
f"<html lang='en'>\n"
|
|
938
|
-
f"{head_html}\n"
|
|
939
|
-
f"<body>\n"
|
|
937
|
+
f"{title_and_style_html}\n"
|
|
940
938
|
f'<div class="container">\n'
|
|
941
939
|
f"{body_content}\n"
|
|
942
|
-
f"</div
|
|
943
|
-
f"</body>\n"
|
|
944
|
-
f"</html>"
|
|
940
|
+
f"</div>"
|
|
945
941
|
)
|
|
946
942
|
|
|
947
943
|
|
package/skills/bugteam/CLAUDE.md
CHANGED
|
@@ -10,7 +10,7 @@ Each loop: a `code-quality-agent` (fresh context, all A–P audit categories) pr
|
|
|
10
10
|
|
|
11
11
|
| File | Purpose |
|
|
12
12
|
|---|---|
|
|
13
|
-
| `SKILL.md` | Hub — pre-flight call, refusals, audit-posting
|
|
13
|
+
| `SKILL.md` | Hub — pre-flight call, refusals, the audit-posting step (applies the `post-audit-findings` skill), progress checklist, and situation-to-reference table. Read this first. |
|
|
14
14
|
| `PROMPTS.md` | Spawn XML, A–P category bindings, outcome XML schemas. |
|
|
15
15
|
| `CONSTRAINTS.md` | Invariants — what the loop must never violate. |
|
|
16
16
|
| `EXAMPLES.md` | Exit scenarios: converged, cap-reached, stuck, refusal, mixed-outcome. |
|
|
@@ -278,7 +278,7 @@ cd into `<worktree_path>` before any git or file operation.
|
|
|
278
278
|
[ ] git add + commit
|
|
279
279
|
[ ] git push
|
|
280
280
|
[ ] Per finding: atomically post the unified-template reply, then call resolve_thread (no yield between them)
|
|
281
|
-
[ ] Publish fix summary via
|
|
281
|
+
[ ] Publish fix summary via the Artifact tool, capture URL
|
|
282
282
|
[ ] Append fix summary URL to parent review via add_reply_to_pull_request_comment
|
|
283
283
|
[ ] Write fix outcomes XML
|
|
284
284
|
</self_audit_checklist>
|
|
@@ -343,14 +343,15 @@ cd into `<worktree_path>` before any git or file operation.
|
|
|
343
343
|
`loop_comment_index` entry alongside `finding_comment_id`, see
|
|
344
344
|
[reference/obstacles/fix-resolve-thread.md](reference/obstacles/fix-resolve-thread.md)).
|
|
345
345
|
|
|
346
|
-
9.
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
9. Write the fix summary (what was fixed, what was skipped, what was left
|
|
347
|
+
unaddressed) to a self-contained HTML file, load the `artifact-design`
|
|
348
|
+
skill, then publish it with the `Artifact` tool. Capture the returned
|
|
349
|
+
URL.
|
|
349
350
|
|
|
350
|
-
10. Append the fix summary
|
|
351
|
+
10. Append the fix summary URL (from step 9) to the parent review
|
|
351
352
|
via `add_reply_to_pull_request_comment(commentId=<id>, body=...,
|
|
352
353
|
owner=<O>, repo=<R>, pullNumber=<N>)`. The body carries the
|
|
353
|
-
|
|
354
|
+
artifact URL plus a one-line summary of fixes applied this loop.
|
|
354
355
|
|
|
355
356
|
11. Write `.bugteam-pr<N>-loop<L>.fix-outcomes.xml` inside
|
|
356
357
|
`<worktree_path>` (schema below) and return its path.
|
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -36,7 +36,8 @@ First match wins; respond with the quoted line exactly and stop:
|
|
|
36
36
|
token `bugteam` (comma-separated, case-insensitive, whitespace-tolerant):
|
|
37
37
|
`/bugteam is disabled via CLAUDE_REVIEWS_DISABLED.` The pre-flight script
|
|
38
38
|
also exits 7 in this case so any caller invoking it directly halts on the
|
|
39
|
-
same signal.
|
|
39
|
+
same signal. Gate semantics live in the `reviewer-gates` skill
|
|
40
|
+
([../reviewer-gates/SKILL.md](../reviewer-gates/SKILL.md)).
|
|
40
41
|
- **No PR or upstream diff.** `No PR or upstream diff. /bugteam needs a target.`
|
|
41
42
|
- **Dirty tree.** `Uncommitted changes detected. Stash, commit, or revert before
|
|
42
43
|
/bugteam.`
|
|
@@ -46,74 +47,26 @@ First match wins; respond with the quoted line exactly and stop:
|
|
|
46
47
|
|
|
47
48
|
## Audit posting
|
|
48
49
|
|
|
49
|
-
Every internal audit pass (CLEAN or DIRTY) ends with one
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
the
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- `GH_TOKEN` / `GITHUB_TOKEN` env vars take precedence over the toggle.
|
|
71
|
-
Set them when you need to pin a specific reviewer identity by token
|
|
72
|
-
rather than by account login.
|
|
73
|
-
- `BUGTEAM_REVIEWER_ACCOUNT` env var names which authenticated alternate
|
|
74
|
-
to prefer when a toggle is needed (for example,
|
|
75
|
-
`BUGTEAM_REVIEWER_ACCOUNT=jl-cmd`). When unset, the script falls back
|
|
76
|
-
to the first alternate account `gh auth status` reports.
|
|
77
|
-
- The named alternate must be logged in (`gh auth login -h github.com -u
|
|
78
|
-
<login>`) before the audit skill runs. The script exits 1 with a
|
|
79
|
-
pointing-at-`gh auth login` message when self-PR is detected and no
|
|
80
|
-
usable alternate is authenticated.
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py" \
|
|
84
|
-
--skill bugteam \
|
|
85
|
-
--owner <owner> \
|
|
86
|
-
--repo <repo> \
|
|
87
|
-
--pr-number <N> \
|
|
88
|
-
--commit <head_sha> \
|
|
89
|
-
--state <CLEAN|DIRTY> \
|
|
90
|
-
--findings-json <path>
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
`--findings-json` points to a JSON file whose root is a list of objects
|
|
94
|
-
shaped `{path, line, side, severity, description, fix_summary}`. The
|
|
95
|
-
audit agent's persisted finding output maps as follows: finding `file`
|
|
96
|
-
→ `path`, and the agent's `failure_mode` field carries both the failure
|
|
97
|
-
narrative AND the `Fix:` / `Validation:` text per
|
|
98
|
-
[`agents/code-quality-agent.md`](../../agents/code-quality-agent.md)
|
|
99
|
-
("The `failure_mode` field is the audit-to-fix handoff"). Split
|
|
100
|
-
`failure_mode` at the literal `Fix:` heading: the prefix (the failure
|
|
101
|
-
narrative) becomes `description`, and the suffix starting at `Fix:`
|
|
102
|
-
(including the trailing `Validation:` clause) becomes `fix_summary`.
|
|
103
|
-
When the agent omits the `Fix:` heading on a given finding, write the
|
|
104
|
-
full `failure_mode` text to BOTH `description` and `fix_summary` so the
|
|
105
|
-
script's body template (`INLINE_COMMENT_BODY_TEMPLATE` in
|
|
106
|
-
[`_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py))
|
|
107
|
-
still renders coherently. Set `side="RIGHT"` for every entry. On CLEAN,
|
|
108
|
-
pass an empty array (`[]`) so the script posts an APPROVE review
|
|
109
|
-
(GitHub stores it as `state=APPROVED`) with a "no findings" summary and
|
|
110
|
-
zero inline comments.
|
|
111
|
-
|
|
112
|
-
Exit codes: `0` on success (emits the new review's `html_url` to
|
|
113
|
-
stdout); `1` on user input error; `2` on retry exhaustion (1s / 4s /
|
|
114
|
-
16s backoff across four attempts total). Exit 2 is a hard blocker; the
|
|
115
|
-
lead halts the loop and exits `error: post_audit_thread retry
|
|
116
|
-
exhausted` without retrying.
|
|
50
|
+
Every internal audit pass (CLEAN or DIRTY) ends with one posted GitHub PR
|
|
51
|
+
review; the mandate applies whether bugteam runs inside `/pr-converge` or
|
|
52
|
+
standalone. Apply the `post-audit-findings` skill
|
|
53
|
+
([../post-audit-findings/SKILL.md](../post-audit-findings/SKILL.md)) with
|
|
54
|
+
`--skill bugteam`: it covers the findings-JSON mapping (the `failure_mode`
|
|
55
|
+
split at the literal `Fix:` heading), the anchored-vs-unanchored partition,
|
|
56
|
+
the `post_audit_thread.py` invocation, the self-PR reviewer toggle
|
|
57
|
+
(`BUGTEAM_REVIEWER_ACCOUNT`), the exit codes, and the id harvest.
|
|
58
|
+
|
|
59
|
+
Bugteam-only obligations:
|
|
60
|
+
|
|
61
|
+
- The lead runs the posting step; the FIX teammate waits for the harvested
|
|
62
|
+
ids before replying or resolving.
|
|
63
|
+
- Record each harvested `{finding_comment_id, finding_comment_url,
|
|
64
|
+
thread_node_id}` triple into `loop_comment_index` (per-loop scope; see
|
|
65
|
+
[reference/team-setup.md](reference/team-setup.md) § Loop state block) so
|
|
66
|
+
the matching FIX action owns the reply-and-resolve unit.
|
|
67
|
+
- Exit 2 from `post_audit_thread.py` is a hard blocker: the lead halts the
|
|
68
|
+
loop and exits `error: post_audit_thread retry exhausted` without
|
|
69
|
+
retrying.
|
|
117
70
|
|
|
118
71
|
## Progress checklist
|
|
119
72
|
|
|
@@ -143,13 +96,13 @@ end-to-end mental model before starting Step 0.
|
|
|
143
96
|
| `--bugbot-retrigger` flag behavior | [reference/team-setup.md](reference/team-setup.md) |
|
|
144
97
|
| AUDIT action and code-rules pre-audit gate, pre-cycle walk, cycle decision tree | [reference/audit-and-teammates.md](reference/audit-and-teammates.md) |
|
|
145
98
|
| FIX action and verify-push semantics | [reference/audit-and-teammates.md](reference/audit-and-teammates.md) |
|
|
146
|
-
| Posting the end-of-pass audit review
|
|
99
|
+
| Posting the end-of-pass audit review (APPROVE on CLEAN, REQUEST_CHANGES with inline anchored comments on DIRTY) | [§ Audit posting](#audit-posting), which applies [../post-audit-findings/SKILL.md](../post-audit-findings/SKILL.md) |
|
|
147
100
|
| Posting per-finding fix replies via GitHub MCP `add_reply_to_pull_request_comment` (rendered with the unified template at [`_shared/pr-loop/audit-reply-template.md`](../../_shared/pr-loop/audit-reply-template.md)) | [reference/github-pr-reviews.md](reference/github-pr-reviews.md) |
|
|
148
|
-
| Teardown, PR description rewrite via `pr-description-writer`, permission revoke, final report | [reference/teardown-publish-permissions.md](reference/teardown-publish-permissions.md) |
|
|
101
|
+
| Teardown, PR description rewrite via `pr-description-writer`, permission revoke, final report | [../pr-loop-lifecycle/reference/teardown-publish-permissions.md](../pr-loop-lifecycle/reference/teardown-publish-permissions.md) |
|
|
149
102
|
| Spawn-prompt XML, A–P category bindings, outcome XML schemas | [PROMPTS.md](PROMPTS.md) |
|
|
150
103
|
| Per-category audit content (sub-buckets, decision criteria, ready-to-send Variant C templates) | `$HOME/.claude/audit-rubrics/{category_rubrics,prompts}/` |
|
|
151
104
|
| Invariants and design rationale | [CONSTRAINTS.md](CONSTRAINTS.md), [reference/design-rationale.md](reference/design-rationale.md) |
|
|
152
|
-
| Audit-contract finding shape (Shape A / B), Haiku secondary, post-fix self-audit | [
|
|
105
|
+
| Audit-contract finding shape (Shape A / B), Haiku secondary, post-fix self-audit | [../../_shared/pr-loop/audit-contract.md](../../_shared/pr-loop/audit-contract.md) |
|
|
153
106
|
| Exit-scenario examples (converged, cap-reached, stuck, refusal, mixed-outcome) | [EXAMPLES.md](EXAMPLES.md) |
|
|
154
107
|
| Doc URLs and verbatim quotes | [sources.md](sources.md) |
|
|
155
108
|
| Historical Copilot gap analysis (superseded) | [reference/copilot-gap-analysis.md](reference/copilot-gap-analysis.md) |
|
|
@@ -7,11 +7,9 @@ Expanded workflow detail for the `bugteam` skill. Load a file from this director
|
|
|
7
7
|
| File | Purpose |
|
|
8
8
|
|---|---|
|
|
9
9
|
| `README.md` | Index of all files in this directory with one-line domain summaries. |
|
|
10
|
-
| `team-setup.md` | Permissions grant, PR scope resolution, run name, temp dir, and loop state. |
|
|
10
|
+
| `team-setup.md` | Permissions grant, PR scope resolution (applies the `pr-scope-resolve` skill), run name, temp dir, and loop state. |
|
|
11
11
|
| `audit-and-teammates.md` | Pre-audit CODE_RULES gate, full cycle numbering, AUDIT and FIX action detail. |
|
|
12
|
-
| `audit-contract.md` | Finding shape (Shape A / B), Haiku secondary merge rules, post-fix self-audit. |
|
|
13
12
|
| `github-pr-reviews.md` | Per-loop review posting, `jq`+`gh api` payloads, inline anchors, fallbacks, REST endpoints. |
|
|
14
|
-
| `teardown-publish-permissions.md` | Teardown steps, PR description rewrite via `pr-description-writer`, permission revoke, final report. |
|
|
15
13
|
| `design-rationale.md` | Why clean-room subagents, when `/bugteam` applies, refusal reasons. |
|
|
16
14
|
| `copilot-gap-analysis.md` | Historical gap analysis (reference only). |
|
|
17
15
|
|
|
@@ -8,7 +8,7 @@ Expanded material that used to live inline in `SKILL.md`. Load a file when the o
|
|
|
8
8
|
| [`team-setup.md`](team-setup.md) | Permissions grant (`CLAUDE_SKILL_DIR`), PR scope, run name / temp dir / loop state |
|
|
9
9
|
| [`github-pr-reviews.md`](github-pr-reviews.md) | Per-loop reviews, `jq` + `gh api` payloads, anchors, fallbacks, REST endpoints |
|
|
10
10
|
| [`audit-and-teammates.md`](audit-and-teammates.md) | Pre-audit gate, full cycle numbering, AUDIT and FIX actions |
|
|
11
|
-
| [
|
|
11
|
+
| [`../../pr-loop-lifecycle/reference/teardown-publish-permissions.md`](../../pr-loop-lifecycle/reference/teardown-publish-permissions.md) | Utility scripts note, teardown, PR description rewrite, revoke, final report |
|
|
12
12
|
|
|
13
13
|
Canonical documentation quotes: [`../sources.md`](../sources.md).
|
|
14
14
|
|
|
@@ -153,7 +153,7 @@ Agent(
|
|
|
153
153
|
|
|
154
154
|
The teammate sees only the latest audit’s findings — each `Agent` call starts with a fresh context window; prior-loop findings, fix history, and chat stay in the lead.
|
|
155
155
|
|
|
156
|
-
Pass finding comment URL, comment id, and thread node id for each finding (from `loop_comment_index`) in the XML prompt so the teammate owns both the reply and the thread resolution. After commit, the teammate posts one reply per finding using the unified template at [`../../../_shared/pr-loop/audit-reply-template.md`](../../../_shared/pr-loop/audit-reply-template.md) — the full header / horizontal rule / `<action_heading> ✅` / explanation / anchored-bullet / closing-paragraph skeleton, with `<status_line>` set per the path (`Fixed in <short_sha>` for `status=fixed`, `Could not address this loop` for `status=could_not_address`, `Hook blocked the fix commit` for `status=hook_blocked`). Per-thread reply and `resolve_thread` are atomic
|
|
156
|
+
Pass finding comment URL, comment id, and thread node id for each finding (from `loop_comment_index`) in the XML prompt so the teammate owns both the reply and the thread resolution. After commit, the teammate posts one reply per finding using the unified template at [`../../../_shared/pr-loop/audit-reply-template.md`](../../../_shared/pr-loop/audit-reply-template.md) — the full header / horizontal rule / `<action_heading> ✅` / explanation / anchored-bullet / closing-paragraph skeleton, with `<status_line>` set per the path (`Fixed in <short_sha>` for `status=fixed`, `Could not address this loop` for `status=could_not_address`, `Hook blocked the fix commit` for `status=hook_blocked`). Per-thread reply and `resolve_thread` are atomic; the mechanics follow the `pr-fix-protocol` skill ([`../../pr-fix-protocol/SKILL.md`](../../pr-fix-protocol/SKILL.md)), which frames the shared 13-step sequence in [`../../../_shared/pr-loop/fix-protocol.md`](../../../_shared/pr-loop/fix-protocol.md) (step 12 carries the exact reply-and-resolve sequence). Same identity model as bugfind: teammate posts; lead waits.
|
|
157
157
|
|
|
158
158
|
After replies, the teammate writes outcome XML (schema in [`../PROMPTS.md`](../PROMPTS.md)).
|
|
159
159
|
|
|
@@ -8,7 +8,7 @@ Bugteam-specific utilities (preflight, fix_hookspath, grant, revoke) live in
|
|
|
8
8
|
the skill-local [`scripts/`](../scripts/) directory. Shared utilities remain in
|
|
9
9
|
[`_shared/pr-loop/scripts/`](../../_shared/pr-loop/scripts/) (run, do not paste
|
|
10
10
|
into context). Utility scripts are **executed**, not loaded as primary context
|
|
11
|
-
([`sources.md`](sources.md) § Progressive disclosure and utility scripts).
|
|
11
|
+
([`sources.md`](../sources.md) § Progressive disclosure and utility scripts).
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
python "${CLAUDE_SKILL_DIR}/scripts/bugteam_preflight.py"
|
|
@@ -53,7 +53,7 @@ the auto-remediation only applies to the `core.hooksPath` failure mode.
|
|
|
53
53
|
Before spawning any subagents, grant the session write access to the project's `.claude/**` tree:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
python "${CLAUDE_SKILL_DIR}/scripts/grant_project_claude_permissions.py"
|
|
56
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/grant_project_claude_permissions.py"
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
`${CLAUDE_SKILL_DIR}` is a Claude Code host-managed token, pre-substituted by the runtime before any shell sees it. Unlike `${TMPDIR}` and similar shell parameter expansions, it does not depend on the shell’s expansion semantics, so it behaves the same on Unix and Windows shells.
|
|
@@ -64,11 +64,12 @@ This is the **first** action of every `/bugteam` invocation, before any subagent
|
|
|
64
64
|
|
|
65
65
|
## Step 1 — Resolve PR scope (detail)
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
Apply the `pr-scope-resolve` skill
|
|
68
|
+
([../../pr-scope-resolve/SKILL.md](../../pr-scope-resolve/SKILL.md)) with
|
|
69
|
+
caller `bugteam`. Its resolution ladder hands back `owner`, `repo`, `number`,
|
|
70
|
+
`head_ref`, `base_ref`, `url`, and `head_sha`; when no PR and no upstream
|
|
71
|
+
diff exist, respond exactly `No PR or upstream diff. /bugteam needs a
|
|
72
|
+
target.` and stop.
|
|
72
73
|
|
|
73
74
|
Capture `<owner>/<repo>`, head branch, base branch, PR number, PR URL. This scope persists across every loop — `/bugteam` runs to completion from the single up-front confirmation.
|
|
74
75
|
|
|
@@ -9,9 +9,6 @@ Python scripts executed by the bugteam lead or teammates at runtime. These are n
|
|
|
9
9
|
| `bugteam_preflight.py` | Run pytest and optional `pre-commit` before the first loop. Skips pytest when `BUGTEAM_PREFLIGHT_SKIP=1` or no test files exist. |
|
|
10
10
|
| `bugteam_fix_hookspath.py` | Auto-remediate a stale `core.hooksPath` override, set the canonical global value, re-run preflight. |
|
|
11
11
|
| `bugteam_code_rules_gate.py` | Run `validate_content` from `code_rules_enforcer.py` on PR-scoped files. Exit 1 on mandatory rule failures. |
|
|
12
|
-
| `grant_project_claude_permissions.py` | Grant Edit/Write/Read on `cwd/.claude/**` in `~/.claude/settings.json`. |
|
|
13
|
-
| `revoke_project_claude_permissions.py` | Remove the matching grant entries from `~/.claude/settings.json`. |
|
|
14
|
-
| `_bugteam_permissions_common.py` | Shared helpers for grant/revoke (atomic JSON writes, settings sections). |
|
|
15
12
|
| `windows_safe_rmtree.py` | Remove a directory tree on Windows by stripping ReadOnly attributes and retrying on failure. |
|
|
16
13
|
| `probe_code_rules_enforcer_check.py` | Load `code_rules_enforcer.py` and invoke a named check function against a fixture file. |
|
|
17
14
|
| `reflow_skill_md.py` | Reflow the bugteam SKILL.md body to fit line-length limits. |
|
|
@@ -23,9 +20,6 @@ Python scripts executed by the bugteam lead or teammates at runtime. These are n
|
|
|
23
20
|
| `test_bugteam_preflight.py` | `bugteam_preflight.py` |
|
|
24
21
|
| `test_bugteam_code_rules_gate.py` | `bugteam_code_rules_gate.py` |
|
|
25
22
|
| `test_bugteam_fix_hookspath.py` | `bugteam_fix_hookspath.py` |
|
|
26
|
-
| `test_bugteam_permissions_common.py` | `_bugteam_permissions_common.py` |
|
|
27
|
-
| `test__bugteam_permissions_common.py` | Internal helpers in `_bugteam_permissions_common.py` |
|
|
28
|
-
| `test_agent_config_carveout.py` | `.claude/**` grant/revoke carveout logic |
|
|
29
23
|
| `test_probe_code_rules_enforcer_check.py` | `probe_code_rules_enforcer_check.py` |
|
|
30
24
|
| `test_windows_safe_rmtree.py` | `windows_safe_rmtree.py` |
|
|
31
25
|
|
|
@@ -7,10 +7,6 @@ Scripts in this directory are **executed** by the lead or teammates. They are no
|
|
|
7
7
|
| `bugteam_preflight.py` | Run pytest (when configured) and optional `pre-commit` before `/bugteam`. |
|
|
8
8
|
| `bugteam_fix_hookspath.py` | Auto-remediate a stale local `core.hooksPath` override, set canonical global value, re-run `bugteam_preflight.py`. Invoked by Claude when preflight reports a `core.hooksPath` failure. |
|
|
9
9
|
| `bugteam_code_rules_gate.py` | Run `validate_content` from `code-rules-enforcer.py` on PR-scoped files (`git diff` vs merge-base). Exit `1` if any mandatory rule fails. Invoked **before each audit**; the fixer clears it before the auditor runs. |
|
|
10
|
-
| `grant_project_claude_permissions.py` | Idempotent grant of Edit/Write/Read on `cwd/.claude/**` into `~/.claude/settings.json`. |
|
|
11
|
-
| `revoke_project_claude_permissions.py` | Removes the matching grant entries from `~/.claude/settings.json`. |
|
|
12
|
-
| `test_claude_permissions_common.py` | Pytest module for path normalization and glob-metacharacter guards in `_claude_permissions_common.py`. |
|
|
13
|
-
| `_claude_permissions_common.py` | Shared helpers for the grant/revoke scripts (atomic JSON writes, settings sections). |
|
|
14
10
|
| `windows_safe_rmtree.py` | Recursively remove a directory tree on Windows by stripping ReadOnly attributes and retrying the failing syscall. Invoked from SKILL.md Step 4 to delete `<run_temp_dir>` after teardown. |
|
|
15
11
|
| `probe_code_rules_enforcer_check.py` | Dynamically load `~/.claude/hooks/blocking/code_rules_enforcer.py` and invoke a named check function against a fixture file. Used by the historical Copilot gap-analysis investigation as a verification shape (see `reference/copilot-gap-analysis.md`). |
|
|
16
12
|
|
|
@@ -9,7 +9,6 @@ Python package of named constants imported by the bugteam scripts. Each module h
|
|
|
9
9
|
| `bugteam_preflight_constants.py` | `bugteam_preflight.py` — env var name, hooks path suffix, exit codes, ignore dirs, argument tuples, config filenames. |
|
|
10
10
|
| `bugteam_code_rules_gate_constants.py` | `bugteam_code_rules_gate.py` — gate-related path and exit-code constants. |
|
|
11
11
|
| `bugteam_fix_hookspath_constants.py` | `bugteam_fix_hookspath.py` — canonical hooks path, remediation message strings. |
|
|
12
|
-
| `claude_permissions_common_constants.py` | `_bugteam_permissions_common.py` — settings JSON keys, glob patterns for the grant/revoke scripts. |
|
|
13
12
|
| `probe_code_rules_enforcer_check_constants.py` | `probe_code_rules_enforcer_check.py` — enforcer module path and function name constants. |
|
|
14
13
|
| `reflow_skill_md_constants.py` | `reflow_skill_md.py` — line-length and formatting constants. |
|
|
15
14
|
| `windows_safe_rmtree_constants.py` | `windows_safe_rmtree.py` — retry count and wait constants. |
|