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.
Files changed (186) hide show
  1. package/_shared/pr-loop/audit-contract.md +24 -12
  2. package/_shared/pr-loop/scripts/_claude_permissions_common.py +16 -5
  3. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
  4. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -1
  5. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +8 -0
  6. package/_shared/pr-loop/scripts/reviews_disabled.py +2 -0
  7. package/_shared/pr-loop/scripts/terminology_sweep.py +85 -39
  8. package/_shared/pr-loop/scripts/tests/test__claude_permissions_common.py +212 -0
  9. package/_shared/pr-loop/scripts/tests/test_agent_config_carveout.py +18 -0
  10. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +18 -0
  11. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +37 -0
  12. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +14 -0
  13. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +94 -4
  14. package/agents/clean-coder.md +3 -0
  15. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +1 -1
  16. package/bin/install.mjs +16 -8
  17. package/bin/install.test.mjs +17 -6
  18. package/commands/CLAUDE.md +0 -1
  19. package/docs/CODE_RULES.md +1 -1
  20. package/hooks/blocking/CLAUDE.md +0 -4
  21. package/hooks/blocking/claude_md_orphan_file_blocker.py +1 -1
  22. package/hooks/blocking/code_rules_constants_config.py +5 -0
  23. package/hooks/blocking/code_rules_docstrings.py +133 -19
  24. package/hooks/blocking/code_rules_enforcer.py +4 -0
  25. package/hooks/blocking/code_rules_imports_logging.py +10 -6
  26. package/hooks/blocking/code_rules_magic_values.py +5 -0
  27. package/hooks/blocking/code_rules_naming_collection.py +15 -8
  28. package/hooks/blocking/code_rules_paired_test.py +3 -2
  29. package/hooks/blocking/code_rules_shared.py +34 -0
  30. package/hooks/blocking/code_rules_string_magic.py +1 -1
  31. package/hooks/blocking/code_rules_unused_imports.py +2 -2
  32. package/hooks/blocking/duplicate_rmtree_helper_blocker.py +4 -4
  33. package/hooks/blocking/test_code_rules_enforcer_docstring_args_span_scope.py +29 -0
  34. package/hooks/blocking/test_code_rules_enforcer_docstring_prose_wall_illustration.py +197 -0
  35. package/hooks/blocking/test_code_rules_enforcer_docstring_runon_sentence.py +27 -0
  36. package/hooks/blocking/test_code_rules_enforcer_naive_datetime.py +24 -0
  37. package/hooks/blocking/test_code_rules_enforcer_split_constants_config.py +33 -0
  38. package/hooks/blocking/test_code_rules_enforcer_split_shared.py +23 -0
  39. package/hooks/blocking/test_code_rules_magic_values.py +54 -0
  40. package/hooks/blocking/test_duplicate_rmtree_helper_blocker.py +0 -6
  41. package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +184 -0
  42. package/hooks/blocking/test_shared_stdin_adoption.py +5 -30
  43. package/hooks/hooks_constants/CLAUDE.md +0 -3
  44. package/hooks/hooks_constants/blocking_check_limits.py +4 -0
  45. package/hooks/hooks_constants/code_rules_path_utils_constants.py +1 -1
  46. package/hooks/hooks_constants/duplicate_rmtree_helper_blocker_constants.py +0 -1
  47. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -5
  48. package/hooks/validation/post_tool_use_dispatcher.py +1 -1
  49. package/hooks/validation/test_post_tool_use_dispatcher.py +51 -35
  50. package/hooks/workflow/CLAUDE.md +2 -8
  51. package/package.json +1 -1
  52. package/rules/CLAUDE.md +1 -1
  53. package/rules/docstring-prose-matches-implementation.md +1 -1
  54. package/rules/env-var-table-code-drift.md +1 -1
  55. package/rules/package-inventory-stale-entry.md +1 -1
  56. package/rules/paired-test-coverage.md +1 -1
  57. package/rules/plain-illustrative-docstrings.md +35 -1
  58. package/skills/CLAUDE.md +6 -1
  59. package/skills/_shared/pr-loop/CLAUDE.md +1 -0
  60. package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -0
  61. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -0
  62. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +45 -0
  63. package/skills/_shared/pr-loop/scripts/test_write_handoff.py +201 -0
  64. package/skills/_shared/pr-loop/scripts/write_handoff.py +309 -0
  65. package/skills/autoconverge/SKILL.md +82 -58
  66. package/skills/autoconverge/reference/closing-report.md +6 -6
  67. package/skills/autoconverge/reference/convergence.md +17 -15
  68. package/skills/autoconverge/reference/gotchas.md +6 -3
  69. package/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +2 -9
  70. package/skills/autoconverge/workflow/converge.contract.test.mjs +87 -13
  71. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +1 -1
  72. package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +16 -9
  73. package/skills/autoconverge/workflow/converge.mjs +71 -74
  74. package/skills/autoconverge/workflow/render_report.py +7 -11
  75. package/skills/bugteam/CLAUDE.md +1 -1
  76. package/skills/bugteam/PROMPTS.md +7 -6
  77. package/skills/bugteam/SKILL.md +25 -72
  78. package/skills/bugteam/reference/CLAUDE.md +1 -3
  79. package/skills/bugteam/reference/README.md +1 -1
  80. package/skills/bugteam/reference/audit-and-teammates.md +1 -1
  81. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +1 -1
  82. package/skills/bugteam/reference/team-setup.md +8 -7
  83. package/skills/bugteam/scripts/CLAUDE.md +0 -6
  84. package/skills/bugteam/scripts/README.md +0 -4
  85. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +0 -1
  86. package/skills/code/SKILL.md +2 -0
  87. package/skills/copilot-review/CLAUDE.md +1 -1
  88. package/skills/copilot-review/SKILL.md +25 -23
  89. package/skills/findbugs/CLAUDE.md +2 -2
  90. package/skills/findbugs/SKILL.md +22 -83
  91. package/skills/fixbugs/SKILL.md +2 -4
  92. package/skills/log-audit/CLAUDE.md +20 -0
  93. package/skills/log-audit/SKILL.md +68 -0
  94. package/skills/log-audit/reference/CLAUDE.md +9 -0
  95. package/skills/log-audit/reference/charter.md +52 -0
  96. package/skills/log-audit/scripts/CLAUDE.md +27 -0
  97. package/skills/log-audit/scripts/cluster_recurrences.py +261 -0
  98. package/skills/log-audit/scripts/collect_log_window.py +199 -0
  99. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +12 -0
  100. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +23 -0
  101. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +24 -0
  102. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +49 -0
  103. package/skills/log-audit/scripts/mine_copilot_findings.py +302 -0
  104. package/skills/log-audit/scripts/test_cluster_recurrences.py +160 -0
  105. package/skills/log-audit/scripts/test_collect_log_window.py +111 -0
  106. package/skills/log-audit/scripts/test_mine_copilot_findings.py +126 -0
  107. package/skills/monitor-open-prs/SKILL.md +2 -2
  108. package/skills/post-audit-findings/SKILL.md +84 -0
  109. package/skills/pr-converge/CLAUDE.md +2 -0
  110. package/skills/pr-converge/SKILL.md +99 -60
  111. package/skills/pr-converge/reference/CLAUDE.md +1 -1
  112. package/skills/pr-converge/reference/convergence-gates.md +16 -19
  113. package/skills/pr-converge/reference/examples.md +5 -5
  114. package/skills/pr-converge/reference/fix-protocol.md +16 -43
  115. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +1 -1
  116. package/skills/pr-converge/reference/per-tick.md +24 -45
  117. package/skills/pr-converge/reference/state-schema.md +27 -0
  118. package/skills/pr-converge/scripts/README.md +3 -5
  119. package/skills/pr-fix-protocol/SKILL.md +70 -0
  120. package/skills/pr-loop-lifecycle/SKILL.md +73 -0
  121. package/skills/{bugteam → pr-loop-lifecycle}/reference/teardown-publish-permissions.md +22 -24
  122. package/skills/pr-scope-resolve/SKILL.md +48 -0
  123. package/skills/qbug/CLAUDE.md +4 -4
  124. package/skills/qbug/SKILL.md +46 -144
  125. package/skills/qbug/test_qbug_skill_audit_schema.py +2 -2
  126. package/skills/qbug/test_qbug_skill_post_fix_audit.py +1 -1
  127. package/skills/reviewer-gates/SKILL.md +96 -0
  128. package/skills/session-log/CLAUDE.md +7 -7
  129. package/skills/session-log/SKILL.md +27 -44
  130. package/skills/test_markdown_link_integrity.py +103 -0
  131. package/commands/doc-gist.md +0 -16
  132. package/hooks/blocking/_md_to_html_blocker_test_support.py +0 -65
  133. package/hooks/blocking/conftest.py +0 -30
  134. package/hooks/blocking/md_path_exemptions.py +0 -224
  135. package/hooks/blocking/md_to_html_blocker.py +0 -155
  136. package/hooks/blocking/test_md_to_html_blocker_exemptions.py +0 -434
  137. package/hooks/blocking/test_md_to_html_blocker_extensions.py +0 -157
  138. package/hooks/blocking/test_md_to_html_blocker_path_resolution.py +0 -336
  139. package/hooks/hooks_constants/doc_gist_auto_publish_constants.py +0 -18
  140. package/hooks/hooks_constants/html_companion_constants.py +0 -20
  141. package/hooks/hooks_constants/md_to_html_blocker_constants.py +0 -76
  142. package/hooks/hooks_constants/test_md_to_html_blocker_constants.py +0 -125
  143. package/hooks/workflow/doc_gist_auto_publish.py +0 -144
  144. package/hooks/workflow/md_to_html_companion.py +0 -358
  145. package/hooks/workflow/test_doc_gist_auto_publish.py +0 -117
  146. package/hooks/workflow/test_md_to_html_companion.py +0 -613
  147. package/skills/bugteam/reference/audit-contract.md +0 -163
  148. package/skills/bugteam/scripts/_bugteam_permissions_common.py +0 -455
  149. package/skills/bugteam/scripts/bugteam_scripts_constants/claude_permissions_common_constants.py +0 -69
  150. package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -280
  151. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -266
  152. package/skills/bugteam/scripts/test__bugteam_permissions_common.py +0 -160
  153. package/skills/bugteam/scripts/test_agent_config_carveout.py +0 -356
  154. package/skills/bugteam/scripts/test_bugteam_permissions_common.py +0 -140
  155. package/skills/doc-gist/CLAUDE.md +0 -25
  156. package/skills/doc-gist/SKILL.md +0 -97
  157. package/skills/doc-gist/references/CLAUDE.md +0 -9
  158. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +0 -453
  159. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +0 -515
  160. package/skills/doc-gist/references/examples/03-code-review-pr.html +0 -638
  161. package/skills/doc-gist/references/examples/04-code-understanding.html +0 -491
  162. package/skills/doc-gist/references/examples/05-design-system.html +0 -629
  163. package/skills/doc-gist/references/examples/06-component-variants.html +0 -605
  164. package/skills/doc-gist/references/examples/07-prototype-animation.html +0 -455
  165. package/skills/doc-gist/references/examples/08-prototype-interaction.html +0 -396
  166. package/skills/doc-gist/references/examples/09-slide-deck.html +0 -592
  167. package/skills/doc-gist/references/examples/10-svg-illustrations.html +0 -492
  168. package/skills/doc-gist/references/examples/11-status-report.html +0 -528
  169. package/skills/doc-gist/references/examples/12-incident-report.html +0 -596
  170. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +0 -395
  171. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +0 -381
  172. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +0 -368
  173. package/skills/doc-gist/references/examples/16-implementation-plan.html +0 -702
  174. package/skills/doc-gist/references/examples/17-pr-writeup.html +0 -595
  175. package/skills/doc-gist/references/examples/18-editor-triage-board.html +0 -573
  176. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +0 -663
  177. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +0 -722
  178. package/skills/doc-gist/references/examples/21-decision-signoff.html +0 -546
  179. package/skills/doc-gist/references/examples/CLAUDE.md +0 -25
  180. package/skills/doc-gist/references/examples/README.md +0 -5
  181. package/skills/doc-gist/scripts/CLAUDE.md +0 -27
  182. package/skills/doc-gist/scripts/doc_gist_scripts_constants/CLAUDE.md +0 -10
  183. package/skills/doc-gist/scripts/doc_gist_scripts_constants/gist_upload_constants.py +0 -16
  184. package/skills/doc-gist/scripts/gist_upload.py +0 -177
  185. package/skills/doc-gist/scripts/test_gist_upload.py +0 -51
  186. /package/skills/{doc-gist/scripts/doc_gist_scripts_constants → log-audit/scripts/log_audit_constants}/__init__.py +0 -0
@@ -138,6 +138,8 @@ def load_config(config_path: str) -> AppConfig:
138
138
  """
139
139
  ```
140
140
 
141
+ For a public function whose behavior needs a picture, lead the narrative with a diagram: one summary line, then a `::` literal block or a doctest showing a concrete input and its marked outcome, then a couple of short prose lines, then the `Args:` / `Returns:` sections. See `../../rules/plain-illustrative-docstrings.md` for the shape and a worked example.
142
+
141
143
  ### 13. Build infrastructure
142
144
 
143
145
  The project under development must contain:
@@ -4,7 +4,7 @@ Spawns a background subagent that polls the GitHub Copilot reviewer on the curre
4
4
 
5
5
  ## Purpose
6
6
 
7
- The main session gathers PR context (number, HEAD SHA, owner/repo, branch), spawns a self-terminating background subagent with a fully filled-in prompt, and returns control at once. The subagent loops on a 5-minute `ScheduleWakeup` cadence: fetch Copilot's latest review, TDD-fix any inline findings, push a commit, reply inline, re-request review. It stops on convergence, a persistent blocker, `TaskStop`, or after 20 ticks.
7
+ The main session gathers PR context (number, HEAD SHA, owner/repo, branch), spawns a self-terminating background subagent with a fully filled-in prompt, and returns control at once. The subagent loops on a 6-minute `ScheduleWakeup` cadence: fetch Copilot's latest review, TDD-fix any inline findings, push a commit, reply inline, resolve each addressed thread, re-request review. It stops on convergence, a persistent blocker, `TaskStop`, three consecutive ticks with no Copilot review at the current HEAD, or after 20 ticks.
8
8
 
9
9
  ## Key file
10
10
 
@@ -2,10 +2,11 @@
2
2
  name: copilot-review
3
3
  description: >-
4
4
  Spawns a background subagent that babysits the GitHub Copilot reviewer on the current
5
- PR: each ~5-min tick it fetches the latest copilot-pull-request-reviewer[bot] review,
6
- fixes unaddressed findings against HEAD (commit, push, inline replies), re-requests
7
- review, and exits on convergence. Triggers: '/copilot-review', 'watch copilot',
8
- 'babysit copilot review', 'keep re-requesting copilot'.
5
+ PR: each ~6-min tick it fetches the latest copilot-pull-request-reviewer[bot] review,
6
+ fixes unaddressed findings against HEAD (commit, push, inline replies, thread
7
+ resolution), re-requests review, and exits on convergence. Triggers:
8
+ '/copilot-review', 'watch copilot', 'babysit copilot review', 'keep re-requesting
9
+ copilot'.
9
10
  ---
10
11
 
11
12
  # Copilot Review
@@ -20,20 +21,18 @@ The user is on a PR branch, wants Copilot (the GitHub Copilot reviewer bot) to k
20
21
 
21
22
  ### Step 0: Opt-out check
22
23
 
23
- Before any other work, inspect the `CLAUDE_REVIEWS_DISABLED` environment
24
- variable. Treat the value as a comma-separated list of skill tokens
25
- (case-insensitive, whitespace-tolerant). When the parsed list contains
26
- `copilot`, respond with the literal line `/copilot-review is disabled via
27
- CLAUDE_REVIEWS_DISABLED.` and stop — do not spawn the subagent, do not call
28
- the Copilot reviewer API, do not run any other step of this skill.
24
+ Before any other work, run:
29
25
 
30
- PowerShell probe (Windows):
31
-
32
- ```pwsh
33
- $disabled = ($env:CLAUDE_REVIEWS_DISABLED -split ',' | ForEach-Object { $_.Trim().ToLowerInvariant() })
34
- if ($disabled -contains 'copilot') { '/copilot-review is disabled via CLAUDE_REVIEWS_DISABLED.' }
26
+ ```bash
27
+ python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer copilot
35
28
  ```
36
29
 
30
+ Exit 0 — Copilot reviews are disabled: respond with the literal line
31
+ `/copilot-review is disabled via CLAUDE_REVIEWS_DISABLED.` and stop — do not
32
+ spawn the subagent, do not call the Copilot reviewer API, do not run any
33
+ other step of this skill. Exit 1 — continue. Gate semantics live in the
34
+ `reviewer-gates` skill ([../reviewer-gates/SKILL.md](../reviewer-gates/SKILL.md)).
35
+
37
36
  ### Step 1: Gather PR context
38
37
 
39
38
  From the current repo:
@@ -74,25 +73,27 @@ Pass this verbatim to the subagent (substituting the bracketed values):
74
73
  > 2. Fetch latest Copilot review via `pull_request_read(method="get_reviews", pullNumber=[NUMBER], owner="[OWNER]", repo="[REPO]")`.
75
74
  > Capture `commit_id`, `state`, `submitted_at`, `id`.
76
75
  > 3. Decide the branch:
77
- > - **No review exists:** re-request (step 4), schedule next wakeup, return.
78
- > - **Latest review's `commit_id` != current HEAD:** re-request (step 4), schedule next wakeup, return.
79
- > - **Latest review's `commit_id` == current HEAD with unresolved inline findings:** TDD-fix them, push, reply inline on each thread, re-request (step 4), schedule next wakeup, return.
76
+ > - **No review exists:** increment `no_review_count` (see escalation rule below), re-request (step 4), schedule next wakeup, return.
77
+ > - **Latest review's `commit_id` != current HEAD:** increment `no_review_count`, re-request (step 4), schedule next wakeup, return.
78
+ > - **Latest review's `commit_id` == current HEAD with unresolved inline findings:** reset `no_review_count` to 0, TDD-fix them, push, reply inline on each thread, resolve each addressed thread, re-request (step 4), schedule next wakeup, return.
80
79
  > - **Latest review's `commit_id` == current HEAD and clean:** report convergence to the parent with a one-sentence summary and terminate. The loop is done; skip the ScheduleWakeup call.
80
+ >
81
+ > **Escalation rule:** `no_review_count` starts at 0, counts consecutive ticks where no Copilot review exists at the current HEAD, and resets to 0 on every push and every review sighted at HEAD. When it reaches 3, Copilot is not delivering reviews — report the stall to the parent with the count and the last request timestamp, then terminate without scheduling another wakeup.
81
82
  > 4. Re-request Copilot via `request_copilot_review(owner="[OWNER]", repo="[REPO]", pullNumber=[NUMBER])`.
82
83
  > The reviewer ID **must** be `copilot-pull-request-reviewer[bot]` with the `[bot]` suffix — empirically verified: `Copilot`, `copilot`, and `github-copilot` all return `requested_reviewers: []` with no error, silently no-op.
83
84
  > 5. Schedule the next wakeup with `ScheduleWakeup`:
84
- > - `delaySeconds: 300`
85
+ > - `delaySeconds: 360`
85
86
  > - `reason`: one short sentence on what you are waiting for.
86
87
  > - `prompt`: the literal sentinel `<<autonomous-loop-dynamic>>` so the next firing re-enters these instructions.
87
88
  >
88
89
  > **Fix protocol** (step 3, third branch):
89
90
  >
91
+ > - Read `$HOME/.claude/skills/pr-fix-protocol/SKILL.md` and apply it — it carries the shared fix sequence, the reply-and-resolve unit, and the unresolved-thread sweep.
90
92
  > - Read each referenced file:line.
91
93
  > - Write a failing test first when the finding has behavior to test. For pure doc or comment nits that have no behavior, go straight to the fix.
92
- > - Implement the fix.
93
94
  > - Stage the fix and create one new commit on the existing branch: `git add <files> && git commit -m "fix(review): ..."`.
94
95
  > - Push the new commit: `git push origin [BRANCH]`.
95
- > - Reply inline on each comment thread with `add_reply_to_pull_request_comment(owner="[OWNER]", repo="[REPO]", pullNumber=[NUMBER], body="...", commentId=<comment_id>)`, referencing the new commit SHA.
96
+ > - Reply inline via `add_reply_to_pull_request_comment(owner="[OWNER]", repo="[REPO]", pullNumber=[NUMBER], body="...", commentId=<comment_id>)`, referencing the new commit SHA; then resolve each addressed thread via `pull_request_review_write(method="resolve_thread", pullNumber=[NUMBER], owner="[OWNER]", repo="[REPO]", threadId="<PRRT id>")`, harvesting the `PRRT_…` id from `pull_request_read(method="get_review_comments", ...)`. Reply first, then resolve — atomic per thread, per the protocol.
96
97
  >
97
98
  > When a pre-push, pre-commit, or other hook rejects the change, solve it. Read the hook's error message, diagnose the root cause in the code or test, and fix that. Then rerun the commit or push. Hooks exist to catch real problems; treat each rejection as new evidence to act on.
98
99
  >
@@ -101,8 +102,9 @@ Pass this verbatim to the subagent (substituting the bracketed values):
101
102
  > - Convergence (clean review against HEAD): report one-sentence summary to parent and terminate.
102
103
  > - Blocker you have exhausted fix attempts on (API auth failure persists, CI regression whose root cause falls outside this PR, a hook you have investigated and cannot resolve in one commit): report the specific blocker and its diagnosis to the parent, then terminate without scheduling another wakeup.
103
104
  > - Parent sends `TaskStop`: terminate immediately.
105
+ > - `no_review_count` reaches 3 (escalation rule above): report the stall and terminate.
104
106
  >
105
- > **Safety cap:** after 20 ticks without convergence, stop and report. That many rounds means something structural is wrong with the loop.
107
+ > **Safety cap:** after 20 ticks without convergence, stop and report. This is the total-tick runaway guard, distinct from the 3-consecutive-no-review escalation; that many rounds means something structural is wrong with the loop.
106
108
 
107
109
  ### Step 4: Report back to the user
108
110
 
@@ -142,7 +144,7 @@ Subagent: [re-requests review, schedules next wakeup, returns]
142
144
 
143
145
  <example>
144
146
  Subagent tick fires, Copilot has 2 unaddressed inline findings on HEAD.
145
- Subagent: [TDD-fixes both, one commit, pushes, replies inline on both threads, re-requests review, schedules next wakeup]
147
+ Subagent: [TDD-fixes both, one commit, pushes, replies inline on both threads, resolves both threads, re-requests review, schedules next wakeup]
146
148
  </example>
147
149
 
148
150
  <example>
@@ -4,13 +4,13 @@ Audits the current branch's pull request for bugs by spawning the `code-quality-
4
4
 
5
5
  ## Purpose
6
6
 
7
- Read-only. The skill resolves PR scope, writes the diff to a scoped temp file, and spawns two `code-quality-agent` instances (primary sonnet + secondary haiku) with a self-contained, context-free prompt covering all A–P audit categories. After both return it merges findings (de-dup, max-wins severity), posts one audit review to the PR via `post_audit_thread.py` (APPROVE on clean, REQUEST_CHANGES with inline anchored comments on dirty), and reports totals and cleared categories to the user.
7
+ Read-only. The skill resolves PR scope via the `pr-scope-resolve` skill, writes the diff to a scoped temp file, and spawns two `code-quality-agent` instances (primary sonnet + secondary haiku) with a self-contained, context-free prompt covering all A–P audit categories. After both return it merges findings (de-dup, max-wins severity), posts one audit review to the PR via the `post-audit-findings` skill (APPROVE on clean, REQUEST_CHANGES with inline anchored comments on dirty), and reports totals and cleared categories to the user.
8
8
 
9
9
  ## Key file
10
10
 
11
11
  | File | Purpose |
12
12
  |---|---|
13
- | `SKILL.md` | Five-step process: resolve scope, capture diff to a scoped temp path, spawn agents (clean-room prompt XML), post audit review via `post_audit_thread.py`, surface findings and offer `/fixbugs`. Includes refusals, output format, and the anchored-vs-unanchored finding split. |
13
+ | `SKILL.md` | Five-step process: resolve scope (`pr-scope-resolve` skill), capture diff to a scoped temp path, spawn agents (clean-room prompt XML), post audit review (`post-audit-findings` skill), surface findings and offer `/fixbugs`. Includes refusals and the output format. |
14
14
 
15
15
  ## Constraints
16
16
 
@@ -22,21 +22,21 @@ If the current branch has no associated PR and no diff against the default branc
22
22
 
23
23
  First match wins; respond with the quoted line exactly and stop:
24
24
 
25
- - **Disabled via environment.** When `CLAUDE_REVIEWS_DISABLED` contains the
26
- token `bugteam` (comma-separated, case-insensitive, whitespace-tolerant):
27
- `/findbugs is disabled via CLAUDE_REVIEWS_DISABLED.` `/findbugs` is a PR
28
- bug-audit skill in the same family as `/bugteam` and `/qbug`, so the
29
- shared `bugteam` token disables all three.
25
+ - **Disabled via environment.** When `CLAUDE_REVIEWS_DISABLED` carries the
26
+ token `bugteam`:
27
+ `/findbugs is disabled via CLAUDE_REVIEWS_DISABLED.` Run the check via
28
+ `python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer bugteam`
29
+ (exit 0 = disabled). `/findbugs` is a PR bug-audit skill in the same family
30
+ as `/bugteam` and `/qbug`, so the shared `bugteam` token disables all three.
31
+ The gate semantics live in the `reviewer-gates` skill (`../reviewer-gates/SKILL.md`).
30
32
 
31
33
  ## The Process
32
34
 
33
35
  ### Step 1: Resolve PR scope
34
36
 
35
- Determine the audit target in this order:
37
+ Apply the `pr-scope-resolve` skill (`../pr-scope-resolve/SKILL.md`) with caller `findbugs`. Findbugs consumes the resolved `owner`, `repo`, `number`, `head_ref`, `base_ref`, and `url`; when no PR exists, the ladder's merge-base rung sets the audit scope. When no target exists, respond exactly with the sub-skill's canonical refusal line and stop:
36
38
 
37
- 1. **Open PR for current branch.** Call `pull_request_read(method="get", pullNumber=N, owner=O, repo=R)` for the current branch (`N` comes from the parent skill's context, or fall back to `search_issues` MCP with the current branch name to recover the PR number). If a PR exists, capture its number, base ref, head ref, and URL.
38
- 2. **No PR but a remote default branch exists.** Diff against the default branch's merge-base: `git merge-base HEAD origin/<default>` then `git diff <merge-base>...HEAD`. Treat this as the audit scope.
39
- 3. **Neither.** Respond exactly: `No PR or upstream diff found. Push the branch or open a PR first.` and stop.
39
+ `No PR or upstream diff. /findbugs needs a target.`
40
40
 
41
41
  ### Step 2: Capture the full PR diff
42
42
 
@@ -102,6 +102,8 @@ The XML prompt skeleton:
102
102
  L. Behavior-equivalence for refactors
103
103
  M. Producer/consumer cardinality vs collection-type contract
104
104
  N. Test-name scenario verifier
105
+ O. Docstring / fixture-prose vs implementation drift
106
+ P. Name / regex / word-list vs behavior-contract precision
105
107
 
106
108
  The category list above is a summary. The binding definition of each
107
109
  category is its rubric file under $HOME/.claude/audit-rubrics/category_rubrics/
@@ -117,7 +119,7 @@ The XML prompt skeleton:
117
119
  </constraints>
118
120
 
119
121
  <output_format>
120
- Follow the shared audit contract at ../bugteam/reference/audit-contract.md:
122
+ Follow the shared audit contract at $HOME/.claude/_shared/pr-loop/audit-contract.md:
121
123
 
122
124
  - Severity: P0 = will not run / data corruption; P1 = regression or silent
123
125
  failure; P2 = dead code, minor smell.
@@ -139,81 +141,18 @@ returns findings without posting them as inline comments is invisible
139
141
  to the gate. Findbugs remains read-only on code — the review post is
140
142
  the only side effect.
141
143
 
142
- **Self-PR auto-toggle.** GitHub rejects both `APPROVE` and
143
- `REQUEST_CHANGES` reviews with HTTP 422 when the authenticated identity
144
- matches the PR author ("Cannot approve/request changes on your own pull
145
- request"). `post_audit_thread.py` detects this case via `gh api user` +
146
- `gh api repos/<o>/<r>/pulls/<n>` and auto-resolves an alternate gh
147
- account's token for the reviews POST — the active `gh auth` account is
148
- not mutated; only the bearer token sent on the request changes. After
149
- the POST the active account is still whoever it was before, so no
150
- "swap back" step is needed.
151
-
152
- Configuration:
153
-
154
- - `GH_TOKEN` / `GITHUB_TOKEN` env vars take precedence over the toggle.
155
- Set them when you need to pin a specific reviewer identity by token
156
- rather than by account login.
157
- - `BUGTEAM_REVIEWER_ACCOUNT` env var names which authenticated alternate
158
- to prefer when a toggle is needed (for example,
159
- `BUGTEAM_REVIEWER_ACCOUNT=jl-cmd`). The env var name is shared across
160
- every skill that invokes `post_audit_thread.py`. When unset, the
161
- script falls back to the first alternate account `gh auth status`
162
- reports.
163
- - The named alternate must be logged in (`gh auth login -h github.com -u
164
- <login>`) before the audit skill runs. The script exits 1 with a
165
- pointing-at-`gh auth login` message when self-PR is detected and no
166
- usable alternate is authenticated.
167
-
168
- After the agent (and Haiku secondary) return and the merge is complete,
169
- serialize the merged findings to a JSON file and call
170
- `post_audit_thread.py`:
171
-
172
- ```
173
- python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py" \
174
- --skill findbugs \
175
- --owner <owner> \
176
- --repo <repo> \
177
- --pr-number <N> \
178
- --commit <head_sha> \
179
- --state <CLEAN|DIRTY> \
180
- --findings-json <path>
181
- ```
182
-
183
- The findings JSON root is a list of objects shaped
184
- `{path, line, side, severity, description, fix_summary}`. Before
185
- serializing, partition the merged findings into anchored (line appears
186
- in the captured diff) and unanchored (line is not in the diff) buckets.
187
- Only anchored findings are serialized to the JSON — the GitHub reviews
188
- API rejects the entire POST if any inline comment in `comments[]`
189
- targets a line not in the diff at `--commit`, so a single unanchored
190
- entry breaks the whole review. Unanchored findings are surfaced via
191
- Step 5's user-facing output rather than as inline anchored comments.
192
- For each anchored finding, map `file` → `path`; split the finding's
193
- `failure_mode` at the literal `Fix:` heading so the failure narrative
194
- becomes `description` and the suffix beginning at `Fix:` (including
195
- the trailing `Validation:` clause) becomes `fix_summary` (the
196
- `failure_mode` field carries the full audit-to-fix handoff per
197
- [`agents/code-quality-agent.md`](../../agents/code-quality-agent.md)).
198
- When a finding's `failure_mode` omits the `Fix:` heading, write the
199
- full text to BOTH `description` and `fix_summary`. Set `side="RIGHT"`
200
- for every entry. Zero anchored findings → `--state CLEAN` with the
201
- findings file holding an empty array (`[]`); one or more anchored
202
- findings → `--state DIRTY` with the full list. CLEAN posts an APPROVE review (the
203
- request event; GitHub stores it as `state=APPROVED`) with a "no
204
- findings" summary; DIRTY posts a REQUEST_CHANGES review with one inline
205
- anchored comment per finding (each becomes its own resolvable thread on
206
- the PR).
207
-
208
144
  Capture `<head_sha>` once at the start of Step 4 via `git rev-parse
209
145
  HEAD` in the worktree the diff was scoped against.
210
146
 
211
- Exit codes: `0` on success (emits the new review's `html_url` to
212
- stdout, surface alongside the totals in Step 5); `1` on user input
213
- error; `2` on retry exhaustion (1s / 4s / 16s backoff across four
214
- attempts). On exit 2, tell the user the review post failed and that
215
- the unresolved-thread gate will not see this audit pass; do not retry
216
- silently.
147
+ After the agent (and Haiku secondary) return and the merge is complete,
148
+ apply the `post-audit-findings` skill (`../post-audit-findings/SKILL.md`)
149
+ with `--skill findbugs`. That skill owns the findings-JSON mapping, the
150
+ anchored-only serialization (unanchored findings surface via Step 5's
151
+ user-facing output), the CLEAN/DIRTY decision, the self-PR reviewer
152
+ toggle, and the exit codes. On exit 0, surface the emitted review
153
+ `html_url` alongside the totals in Step 5. On exit 2, tell the user the
154
+ review post failed and that the unresolved-thread gate will not see this
155
+ audit pass; do not retry silently.
217
156
 
218
157
  ### Step 5: Surface findings, then clean up
219
158
 
@@ -285,7 +224,7 @@ Claude: [resolves PR #42 from current branch, fetches full diff, spawns code-qua
285
224
 
286
225
  <example>
287
226
  User: `/findbugs`
288
- Claude: `No PR or upstream diff found. Push the branch or open a PR first.`
227
+ Claude: `No PR or upstream diff. /findbugs needs a target.`
289
228
  </example>
290
229
 
291
230
  <example>
@@ -47,11 +47,9 @@ If the filtered set is empty, refuse per the refusal cases above.
47
47
 
48
48
  ### Step 2: Re-resolve PR scope
49
49
 
50
- Re-establish the same PR target `/findbugs` used:
50
+ Apply the `pr-scope-resolve` skill (`../pr-scope-resolve/SKILL.md`) with caller `fixbugs` to resolve the same PR target `/findbugs` used — the fixes stay scoped to the files the `/findbugs` findings from Step 1 name. When no target exists, respond with the sub-skill's canonical refusal line and stop:
51
51
 
52
- 1. `pull_request_read(method="get", pullNumber=N, owner=O, repo=R)` for the current branch (`N` comes from the parent skill's PR context, or fall back to `search_issues` MCP with the current branch name to recover the PR number).
53
- 2. Fall back to `git merge-base HEAD origin/<default>` then `git diff <merge-base>...HEAD`.
54
- 3. Neither → respond `No PR or upstream diff. Cannot scope fixes.` and stop.
52
+ `No PR or upstream diff. /fixbugs needs a target.`
55
53
 
56
54
  Capture: `<owner>/<repo>`, head branch, base branch, PR number, PR URL.
57
55
 
@@ -0,0 +1,20 @@
1
+ # log-audit
2
+
3
+ Reads this repository's own logs, finds recurring errors and timing regressions, and turns each real pattern into a tracked fix. Triggered by `/log-audit`, `audit the logs`, `what keeps failing`, or `what's getting slower`.
4
+
5
+ ## Purpose
6
+
7
+ The skill runs as a background agent on a recurring schedule. Each cycle it reads the hook block log and the diagnostic extractor pipeline, clusters recurring errors and timing regressions, opens a grouped draft fix pull request or a tracked optimization issue per finding, and mines the defects Copilot and Bugbot keep catching into skill-edit proposals. Cycle state lives under `~/.claude/runtime/log-audit/`, so a restart resumes the same run.
8
+
9
+ ## Key files
10
+
11
+ | File | Purpose |
12
+ |---|---|
13
+ | `SKILL.md` | Full instructions: the cycle steps, the three scripts and how to pipe them, the log sources in and out of scope, finding-filing rules, reviewer mining, cycle state, and cadence. |
14
+
15
+ ## Subdirectories
16
+
17
+ | Directory | Role |
18
+ |---|---|
19
+ | `reference/` | The agent charter — the fixed contract the skill answers to. |
20
+ | `scripts/` | The collect, cluster, and mine scripts and their constants package. |
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: log-audit
3
+ description: >-
4
+ Watches this repo's own logs for patterns worth acting on. Use for /log-audit,
5
+ "audit the logs", "what keeps failing", or "what's getting slower". Reads the
6
+ hook block log and the diagnostic extractor pipeline, clusters recurring errors
7
+ and timing regressions, opens a grouped fix PR or a tracked optimization issue
8
+ per real finding, and mines the defects Copilot and Bugbot keep catching into
9
+ skill-edit proposals. Runs as a background agent that resumes after a restart.
10
+ ---
11
+
12
+ # log-audit
13
+
14
+ Read the logs this repo writes about itself, find what keeps going wrong or keeps getting slower, and turn each real pattern into a tracked fix. `reference/charter.md` holds the full contract; this file is how to run a cycle.
15
+
16
+ ## One cycle
17
+
18
+ 1. **Collect.** Run `scripts/collect_log_window.py` to read the recent window of the hook block log into records.
19
+ 2. **Cluster.** Pipe those records into `scripts/cluster_recurrences.py` to group them by a normalized signature and rank the loudest first. When timing samples are on hand, the same module flags operations whose recent runs have grown slower than their earlier runs.
20
+ 3. **Mine reviewers.** Run `scripts/mine_copilot_findings.py` to sort recent reviewer-bot comments into defect classes and print a skill-edit proposal for each class.
21
+ 4. **File findings.** For each real finding, open a grouped fix pull request as a draft, or file a tracked optimization issue for a delay.
22
+ 5. **Report.** Write the per-cycle report: delays removed, pull requests opened, skill improvements suggested.
23
+ 6. **Re-arm.** Save cycle state and schedule the next cycle.
24
+
25
+ ## Scripts
26
+
27
+ | File | What it does |
28
+ |---|---|
29
+ | `scripts/collect_log_window.py` | Tails the JSON-lines hook block log and prints the block records inside a time window as JSON. `--hours` sets the window; `--log-path` overrides the log location. |
30
+ | `scripts/cluster_recurrences.py` | Reads that JSON on stdin, groups records by a normalized message signature, and prints the clusters ranked by recency-weighted count. Its `detect_timing_regressions` flags an operation whose recent runs are slower than its earliest runs. |
31
+ | `scripts/mine_copilot_findings.py` | Reads a repo's reviewer-bot comments through `gh`, sorts them into defect classes, and prints one skill-edit proposal per class, most frequent first. Takes `--repo owner/name`. |
32
+
33
+ Run the first two as a pipeline:
34
+
35
+ ```
36
+ python scripts/collect_log_window.py --hours 24 | python scripts/cluster_recurrences.py
37
+ ```
38
+
39
+ ## What it reads
40
+
41
+ In scope:
42
+
43
+ - The hook block log at `~/.claude/logs/hook-blocks.log`, written by `hook_block_logger`.
44
+ - The `hooks/diagnostic/` extractor pipeline. When Neon is set up, read through that pipeline's SQL — the shape of `queries/blocks_by_category.sql` and its siblings against the `hook_events` table, which carries `duration_ms` for timing work. When Neon is not set up, read the flat `hook-blocks.log` directly. Reuse the diagnostic pipeline's helpers; do not hold a second copy.
45
+
46
+ Out of scope: Samsung-automation logs. Read this repo's log surfaces only.
47
+
48
+ ## Filing findings
49
+
50
+ - A pull request or optimization issue carries its body in a file passed by path, following the `gh-body-file` rule.
51
+ - Any paginated GitHub read follows the `gh-paginate` rule.
52
+ - Group the related fixes for one finding into a single draft pull request rather than one PR per line.
53
+
54
+ ## Reviewer-defect mining
55
+
56
+ `mine_copilot_findings.py` names a skill or rule edit for each defect class the reviewers keep catching — an edit that would block that class at write time rather than at review. These are proposals. A human applies them through review; the agent does not commit them on its own.
57
+
58
+ ## Cycle state and restart survival
59
+
60
+ The agent keeps its state in a JSON file under `~/.claude/runtime/log-audit/` — the last window it read, the signatures it already reported, and the open items it filed. At the start of each cycle, read that file; at the end, write it back. Because the state lives in the durable runtime directory rather than the OS temp directory, a restart reads the same file and resumes the same run.
61
+
62
+ ## Cadence
63
+
64
+ The agent runs on a recurring schedule following the repository's Scheduled Task Cadence: a sub-hour interval, with a 30-minute default. Re-arm the next cycle with `ScheduleWakeup` for a self-paced loop, or register a cron routine through `/schedule` for a fixed clock cadence.
65
+
66
+ ## Per-cycle report
67
+
68
+ Each cycle ends with a short report: the delays removed, the pull requests opened, and the skill improvements suggested.
@@ -0,0 +1,9 @@
1
+ # log-audit/reference
2
+
3
+ Reference material for the `log-audit` skill.
4
+
5
+ ## Key files
6
+
7
+ | File | Purpose |
8
+ |---|---|
9
+ | `charter.md` | The agent's contract: what it watches (this repo's hook-block log and diagnostic extractor pipeline), what it looks for (recurring errors and timing regressions), what it files per finding (grouped draft fix PR or tracked optimization issue), how it mines reviewer defect patterns into skill-definition proposals, and the per-cycle report it emits. Cycle state lives under `~/.claude/runtime/log-audit/`; the agent runs on a sub-hour cadence. |
@@ -0,0 +1,52 @@
1
+ # Log-Audit Agent Charter
2
+
3
+ The contract for the log-audit agent: what it watches, what it looks for, and what it produces each cycle. The skill body (`SKILL.md`) and its scripts carry out this contract; this document is the fixed reference they answer to.
4
+
5
+ ## What the agent is
6
+
7
+ A background agent that reads this repository's own log surfaces, finds patterns worth acting on, and turns each real pattern into a tracked fix. It runs on its own without a person driving it and picks up where it left off after a restart.
8
+
9
+ ## Cycle state and cadence
10
+
11
+ The agent keeps its own state on disk under `~/.claude/runtime/log-audit/`. This directory holds durable cycle state — the last window it read, the signatures it already reported, and the open items it filed — so a restart resumes the same run rather than starting over. The OS temp directory is not a home for this state, because temp files can be cleared between sessions.
12
+
13
+ The agent runs on a recurring schedule. It follows the repository's Scheduled Task Cadence: a sub-hour interval, with a 30-minute default.
14
+
15
+ ## Log sources it reads
16
+
17
+ In scope:
18
+
19
+ - The hook block log at `~/.claude/logs/hook-blocks.log`, written by `hook_block_logger`. Each line is one JSON record naming the hook that blocked, the event, the reason, the tool, and a short input excerpt.
20
+ - The `hooks/diagnostic/` extractor pipeline. When Neon is configured, the agent reads through the pipeline's SQL — the shape of `queries/blocks_by_category.sql` and its siblings against the `hook_events` table, which carries `duration_ms` for timing work. When Neon is not configured, the agent reads the flat `hook-blocks.log` directly. It reuses the diagnostic pipeline's helpers rather than holding a second copy of them.
21
+
22
+ Out of scope:
23
+
24
+ - Samsung-automation logs. The agent reads this repository's log surfaces only.
25
+
26
+ ## What it looks for
27
+
28
+ Two kinds of pattern:
29
+
30
+ - Recurring errors. The same failure showing up again and again. The agent groups log records by a normalized message signature — the message with its digits, paths, and hashes stripped — so records that differ only in those details fall into one cluster. It ranks clusters by count weighted toward recent activity.
31
+ - Timing regressions. The same operation taking longer over time. When a repeated operation's duration climbs across cycles, the agent flags it as an unnecessary delay, separate from any error.
32
+
33
+ ## What it does per finding
34
+
35
+ For each real finding, the agent takes one of two tracked actions:
36
+
37
+ - Opens a grouped fix pull request as a draft, gathering the related fixes into one branch.
38
+ - Files a tracked optimization issue when the finding is a delay to chase rather than a fix to write.
39
+
40
+ Both paths carry their body in a file passed by path, following the `gh-body-file` rule, and any paginated GitHub read follows the `gh-paginate` rule.
41
+
42
+ ## Reviewer-defect mining
43
+
44
+ The agent also reads the defect patterns that Copilot and Bugbot catch again and again across recent pull requests. It clusters those comments into defect classes and proposes concrete edits to the skill definitions that would block each class upstream, at the point of writing, rather than at review. These are proposals: they land through review, not by the agent applying them on its own.
45
+
46
+ ## Per-cycle report
47
+
48
+ Each cycle ends with a short report covering:
49
+
50
+ - Delays removed.
51
+ - Pull requests opened.
52
+ - Skill improvements suggested.
@@ -0,0 +1,27 @@
1
+ # log-audit/scripts
2
+
3
+ The collect, cluster, and mine scripts for the `log-audit` skill, plus their constants package.
4
+
5
+ ## Files
6
+
7
+ | File | Purpose |
8
+ |---|---|
9
+ | `collect_log_window.py` | Tails the JSON-lines hook block log and prints the block records inside a time window as JSON. |
10
+ | `test_collect_log_window.py` | Tests for `collect_log_window.py`. |
11
+ | `cluster_recurrences.py` | Groups block records by a normalized signature, ranks them by recency-weighted count, and flags timing regressions. |
12
+ | `test_cluster_recurrences.py` | Tests for `cluster_recurrences.py`. |
13
+ | `mine_copilot_findings.py` | Sorts reviewer-bot comments into defect classes and prints one skill-edit proposal per class. |
14
+ | `test_mine_copilot_findings.py` | Tests for `mine_copilot_findings.py`. |
15
+
16
+ ## Subdirectories
17
+
18
+ | Directory | Role |
19
+ |---|---|
20
+ | `log_audit_constants/` | Named constants imported by the three scripts. |
21
+
22
+ ## Running
23
+
24
+ ```
25
+ python collect_log_window.py --hours 24 | python cluster_recurrences.py
26
+ python mine_copilot_findings.py --repo owner/name
27
+ ```