claude-dev-env 1.93.1 → 1.95.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 (262) hide show
  1. package/_shared/advisor/CLAUDE.md +2 -2
  2. package/_shared/advisor/advisor-protocol.md +35 -27
  3. package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +3 -2
  4. package/_shared/advisor/scripts/model_tier_run_validator.py +23 -15
  5. package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +81 -17
  6. package/_shared/pr-loop/CLAUDE.md +1 -0
  7. package/_shared/pr-loop/audit-contract.md +1 -1
  8. package/_shared/pr-loop/gh-payloads.md +3 -3
  9. package/_shared/pr-loop/post-audit-thread-contract.md +51 -0
  10. package/_shared/pr-loop/scripts/README.md +2 -2
  11. package/_shared/pr-loop/scripts/fix_hookspath.py +47 -12
  12. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -69
  13. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -374
  14. package/_shared/pr-loop/state-schema.md +3 -22
  15. package/bin/CLAUDE.md +11 -2
  16. package/bin/ever-shipped-skills.mjs +70 -0
  17. package/bin/install.mjs +138 -13
  18. package/bin/install.prune.test.mjs +457 -0
  19. package/bin/install.test.mjs +10 -4
  20. package/docs/CODE_RULES.md +1 -1
  21. package/hooks/blocking/CLAUDE.md +2 -0
  22. package/hooks/blocking/code_rules_enforcer.py +4 -0
  23. package/hooks/blocking/code_rules_shared.py +82 -0
  24. package/hooks/blocking/code_rules_test_layout.py +9 -3
  25. package/hooks/blocking/pii_commit_command.py +398 -0
  26. package/hooks/blocking/pii_payload_scan.py +133 -0
  27. package/hooks/blocking/pii_prevention_blocker.py +151 -449
  28. package/hooks/blocking/plain_language_blocker.py +138 -4
  29. package/hooks/blocking/sensitive_file_protector.py +114 -48
  30. package/hooks/blocking/tdd_enforcer.py +9 -2
  31. package/hooks/blocking/test_code_rules_enforcer_scratchpad.py +105 -0
  32. package/hooks/blocking/test_code_rules_shared.py +181 -0
  33. package/hooks/blocking/test_pii_prevention_blocker.py +299 -0
  34. package/hooks/blocking/test_plain_language_blocker_allowlist.py +184 -0
  35. package/hooks/blocking/test_sensitive_file_protector.py +185 -0
  36. package/hooks/blocking/test_tdd_enforcer_scratchpad.py +105 -0
  37. package/hooks/blocking/test_verdict_directory_write_blocker.py +42 -7
  38. package/hooks/hooks_constants/CLAUDE.md +4 -2
  39. package/hooks/hooks_constants/code_rules_path_utils_constants.py +0 -2
  40. package/hooks/hooks_constants/harness_scratchpad_constants.py +17 -0
  41. package/hooks/hooks_constants/local_identity.py +65 -15
  42. package/hooks/hooks_constants/pii_prevention_constants.py +16 -0
  43. package/hooks/hooks_constants/plain_language_blocker_constants.py +5 -0
  44. package/hooks/hooks_constants/pr_description_enforcer_constants.py +1 -1
  45. package/hooks/hooks_constants/sensitive_file_protector_constants.py +42 -0
  46. package/hooks/hooks_constants/test_local_identity.py +68 -0
  47. package/hooks/pyproject.toml +75 -4
  48. package/hooks/validators/CLAUDE.md +1 -1
  49. package/hooks/validators/README.md +2 -0
  50. package/hooks/validators/python_style_checks.py +114 -136
  51. package/hooks/validators/python_style_helpers.py +95 -0
  52. package/hooks/validators/test_python_style_checks.py +0 -164
  53. package/hooks/validators/test_python_style_checks_decorator_gap.py +119 -0
  54. package/hooks/validators/test_python_style_fixes.py +251 -0
  55. package/hooks/validators/test_python_style_helpers.py +125 -0
  56. package/package.json +1 -1
  57. package/rules/CLAUDE.md +1 -0
  58. package/rules/anti-corollary-tests.md +69 -0
  59. package/rules/bdd.md +1 -3
  60. package/rules/code-reviews.md +1 -1
  61. package/rules/gh-paginate.md +1 -1
  62. package/rules/plain-language.md +2 -0
  63. package/scripts/CLAUDE.md +10 -1
  64. package/scripts/Get-SessionAccount.ps1 +210 -0
  65. package/scripts/tests/CLAUDE.md +15 -1
  66. package/scripts/tests/Get-SessionAccount.Tests.ps1 +350 -0
  67. package/skills/CLAUDE.md +6 -27
  68. package/skills/anthropic-plan/SKILL.md +1 -13
  69. package/skills/autoconverge/CLAUDE.md +5 -2
  70. package/skills/autoconverge/SKILL.md +112 -387
  71. package/skills/autoconverge/reference/CLAUDE.md +4 -1
  72. package/skills/autoconverge/reference/closing-report.md +9 -2
  73. package/skills/autoconverge/reference/convergence.md +26 -22
  74. package/skills/autoconverge/reference/headless-safety.md +44 -0
  75. package/skills/autoconverge/reference/multi-pr.md +88 -0
  76. package/skills/autoconverge/reference/self-closing-loop.md +84 -0
  77. package/skills/autoconverge/reference/stop-conditions.md +21 -13
  78. package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +87 -27
  79. package/skills/autoconverge/workflow/converge.contract.test.mjs +40 -10
  80. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +179 -47
  81. package/skills/autoconverge/workflow/converge.fix-progress.test.mjs +1 -1
  82. package/skills/autoconverge/workflow/converge.mjs +286 -96
  83. package/skills/bugteam/CLAUDE.md +1 -1
  84. package/skills/bugteam/CONSTRAINTS.md +3 -3
  85. package/skills/bugteam/PROMPTS.md +8 -19
  86. package/skills/bugteam/SKILL.md +13 -14
  87. package/skills/bugteam/reference/CLAUDE.md +1 -1
  88. package/skills/bugteam/reference/README.md +2 -3
  89. package/skills/bugteam/reference/audit-and-teammates.md +2 -2
  90. package/skills/bugteam/reference/copilot-gap-analysis.md +2 -0
  91. package/skills/bugteam/reference/github-pr-reviews.md +56 -38
  92. package/skills/bugteam/reference/team-setup.md +11 -11
  93. package/skills/bugteam/scripts/CLAUDE.md +6 -6
  94. package/skills/bugteam/scripts/README.md +20 -8
  95. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +13 -1463
  96. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +23 -358
  97. package/skills/bugteam/scripts/bugteam_preflight.py +13 -315
  98. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +2 -3
  99. package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +34 -1053
  100. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +30 -347
  101. package/skills/bugteam/scripts/test_bugteam_preflight.py +30 -305
  102. package/skills/closeout/SKILL.md +153 -0
  103. package/skills/closeout/reference/handoff-prompt-template.md +72 -0
  104. package/skills/closeout/reference/issue-body-templates.md +108 -0
  105. package/skills/closeout/reference/pii-redaction-checklist.md +36 -0
  106. package/skills/copilot-finding-triage/SKILL.md +80 -28
  107. package/skills/copilot-finding-triage/reference/tier-rubric.md +70 -11
  108. package/skills/copilot-finding-triage/templates/notification.md +8 -3
  109. package/skills/everything-search/SKILL.md +1 -2
  110. package/skills/grokify/SKILL.md +58 -0
  111. package/skills/grokify/templates/handoff-template.md +92 -0
  112. package/skills/orchestrator/SKILL.md +35 -25
  113. package/skills/orchestrator-refresh/SKILL.md +15 -11
  114. package/skills/pr-converge/CLAUDE.md +1 -1
  115. package/skills/pr-converge/SKILL.md +132 -233
  116. package/skills/pr-converge/reference/convergence-gates.md +102 -66
  117. package/skills/pr-converge/reference/examples.md +37 -25
  118. package/skills/pr-converge/reference/fix-protocol.md +7 -7
  119. package/skills/pr-converge/reference/multi-pr-orchestration.md +10 -4
  120. package/skills/pr-converge/reference/per-tick.md +64 -41
  121. package/skills/pr-converge/reference/state-schema.md +27 -2
  122. package/skills/pr-converge/scripts/CLAUDE.md +8 -0
  123. package/skills/pr-converge/scripts/README.md +4 -3
  124. package/skills/pr-converge/scripts/_pr_converge_path_setup.py +23 -0
  125. package/skills/pr-converge/scripts/check_convergence.py +189 -645
  126. package/skills/pr-converge/scripts/check_convergence_gates.py +235 -0
  127. package/skills/pr-converge/scripts/check_convergence_thread_gates.py +219 -0
  128. package/skills/pr-converge/scripts/conftest.py +8 -0
  129. package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -0
  130. package/skills/pr-converge/scripts/pr_converge_scripts_constants/convergence_gate_constants.py +36 -0
  131. package/skills/pr-converge/scripts/test__pr_converge_path_setup.py +26 -0
  132. package/skills/pr-converge/scripts/test_check_convergence.py +73 -228
  133. package/skills/pr-converge/scripts/test_check_convergence_contract.py +321 -0
  134. package/skills/pr-converge/scripts/test_check_convergence_gates.py +68 -0
  135. package/skills/pr-converge/scripts/test_check_convergence_thread_gates.py +75 -0
  136. package/skills/pr-fix-protocol/SKILL.md +20 -20
  137. package/skills/privacy-hygiene/SKILL.md +4 -3
  138. package/skills/reviewer-gates/SKILL.md +26 -8
  139. package/skills/session-log/SKILL.md +11 -12
  140. package/skills/session-tidy/SKILL.md +40 -30
  141. package/skills/skill-builder/CLAUDE.md +13 -10
  142. package/skills/skill-builder/SKILL.md +31 -31
  143. package/skills/skill-builder/references/CLAUDE.md +10 -6
  144. package/skills/skill-builder/references/delegation-map.md +13 -4
  145. package/skills/skill-builder/references/description-field.md +113 -0
  146. package/skills/skill-builder/references/self-audit-checklist.md +21 -4
  147. package/skills/skill-builder/references/skill-modularity.md +113 -0
  148. package/skills/skill-builder/references/skill-types.md +4 -0
  149. package/skills/skill-builder/templates/CLAUDE.md +4 -4
  150. package/skills/skill-builder/templates/gap-analysis.md +25 -1
  151. package/skills/skill-builder/workflows/CLAUDE.md +6 -4
  152. package/skills/skill-builder/workflows/improve-skill.md +17 -16
  153. package/skills/skill-builder/workflows/new-skill.md +34 -10
  154. package/skills/skill-builder/workflows/polish-skill.md +59 -43
  155. package/skills/team-advisor/SKILL.md +15 -11
  156. package/skills/usage-pause/SKILL.md +10 -14
  157. package/system-prompts/software-engineer.xml +7 -6
  158. package/hooks/validators/test_verify_paths.py +0 -32
  159. package/hooks/validators/verify_paths.py +0 -57
  160. package/skills/bdd-protocol/CLAUDE.md +0 -26
  161. package/skills/bdd-protocol/SKILL.md +0 -30
  162. package/skills/bdd-protocol/references/CLAUDE.md +0 -10
  163. package/skills/bdd-protocol/references/anti-patterns.md +0 -26
  164. package/skills/bdd-protocol/references/example-mapping.md +0 -23
  165. package/skills/bg-agent/CLAUDE.md +0 -17
  166. package/skills/bg-agent/SKILL.md +0 -69
  167. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_code_rules_gate_constants.py +0 -55
  168. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_fix_hookspath_constants.py +0 -26
  169. package/skills/bugteam/scripts/bugteam_scripts_constants/bugteam_preflight_constants.py +0 -35
  170. package/skills/caveman/CLAUDE.md +0 -15
  171. package/skills/caveman/SKILL.md +0 -38
  172. package/skills/code/CLAUDE.md +0 -17
  173. package/skills/code/SKILL.md +0 -178
  174. package/skills/deep-research/CLAUDE.md +0 -17
  175. package/skills/deep-research/SKILL.md +0 -80
  176. package/skills/findbugs/CLAUDE.md +0 -20
  177. package/skills/findbugs/SKILL.md +0 -241
  178. package/skills/fixbugs/CLAUDE.md +0 -19
  179. package/skills/fixbugs/SKILL.md +0 -142
  180. package/skills/gh-paginate/CLAUDE.md +0 -18
  181. package/skills/gh-paginate/SKILL.md +0 -84
  182. package/skills/gotcha/CLAUDE.md +0 -33
  183. package/skills/gotcha/SKILL.md +0 -73
  184. package/skills/implement/CLAUDE.md +0 -27
  185. package/skills/implement/SKILL.md +0 -66
  186. package/skills/implement/scripts/CLAUDE.md +0 -22
  187. package/skills/implement/scripts/append_note.py +0 -133
  188. package/skills/implement/scripts/implement_scripts_constants/CLAUDE.md +0 -22
  189. package/skills/implement/scripts/implement_scripts_constants/__init__.py +0 -0
  190. package/skills/implement/scripts/implement_scripts_constants/notes_constants.py +0 -12
  191. package/skills/implement/scripts/test_append_note.py +0 -191
  192. package/skills/log-audit/CLAUDE.md +0 -20
  193. package/skills/log-audit/SKILL.md +0 -66
  194. package/skills/log-audit/reference/CLAUDE.md +0 -9
  195. package/skills/log-audit/reference/charter.md +0 -52
  196. package/skills/log-audit/scripts/CLAUDE.md +0 -27
  197. package/skills/log-audit/scripts/cluster_recurrences.py +0 -261
  198. package/skills/log-audit/scripts/collect_log_window.py +0 -199
  199. package/skills/log-audit/scripts/log_audit_constants/CLAUDE.md +0 -12
  200. package/skills/log-audit/scripts/log_audit_constants/__init__.py +0 -0
  201. package/skills/log-audit/scripts/log_audit_constants/cluster_recurrences_constants.py +0 -23
  202. package/skills/log-audit/scripts/log_audit_constants/collect_log_window_constants.py +0 -24
  203. package/skills/log-audit/scripts/log_audit_constants/mine_copilot_findings_constants.py +0 -49
  204. package/skills/log-audit/scripts/mine_copilot_findings.py +0 -302
  205. package/skills/log-audit/scripts/test_cluster_recurrences.py +0 -160
  206. package/skills/log-audit/scripts/test_collect_log_window.py +0 -111
  207. package/skills/log-audit/scripts/test_mine_copilot_findings.py +0 -126
  208. package/skills/logifix/CLAUDE.md +0 -36
  209. package/skills/logifix/SKILL.md +0 -69
  210. package/skills/logifix/scripts/CLAUDE.md +0 -16
  211. package/skills/logifix/scripts/logifix.ps1 +0 -205
  212. package/skills/monitor-open-prs/CLAUDE.md +0 -34
  213. package/skills/monitor-open-prs/SKILL.md +0 -88
  214. package/skills/monitor-open-prs/scripts/CLAUDE.md +0 -17
  215. package/skills/monitor-open-prs/scripts/discover_open_prs.py +0 -69
  216. package/skills/monitor-open-prs/scripts/test_discover_open_prs.py +0 -149
  217. package/skills/monitor-open-prs/test_skill_contract.py +0 -27
  218. package/skills/post-audit-findings/SKILL.md +0 -80
  219. package/skills/pr-consistency-audit/CLAUDE.md +0 -34
  220. package/skills/pr-consistency-audit/SKILL.md +0 -116
  221. package/skills/pr-consistency-audit/reference/CLAUDE.md +0 -16
  222. package/skills/pr-consistency-audit/reference/detection-rules.md +0 -96
  223. package/skills/pr-consistency-audit/reference/illustrations.md +0 -78
  224. package/skills/pr-review-responder/CLAUDE.md +0 -35
  225. package/skills/pr-review-responder/EXAMPLES.md +0 -590
  226. package/skills/pr-review-responder/PRINCIPLES.md +0 -533
  227. package/skills/pr-review-responder/README.md +0 -168
  228. package/skills/pr-review-responder/SKILL.md +0 -203
  229. package/skills/pr-review-responder/TESTING.md +0 -350
  230. package/skills/pr-scope-resolve/SKILL.md +0 -45
  231. package/skills/pre-compact/CLAUDE.md +0 -24
  232. package/skills/pre-compact/SKILL.md +0 -134
  233. package/skills/qbug/CLAUDE.md +0 -40
  234. package/skills/qbug/SKILL.md +0 -387
  235. package/skills/qbug/test_qbug_skill_audit_schema.py +0 -152
  236. package/skills/qbug/test_qbug_skill_post_fix_audit.py +0 -103
  237. package/skills/refine/CLAUDE.md +0 -44
  238. package/skills/refine/SKILL.md +0 -262
  239. package/skills/refine/templates/CLAUDE.md +0 -17
  240. package/skills/refine/templates/implementation-notes-template.html +0 -56
  241. package/skills/refine/templates/plan-template.md +0 -60
  242. package/skills/research-mode/CLAUDE.md +0 -35
  243. package/skills/research-mode/SKILL.md +0 -53
  244. package/skills/structure-prompt/CLAUDE.md +0 -42
  245. package/skills/structure-prompt/SKILL.md +0 -44
  246. package/skills/structure-prompt/reference/CLAUDE.md +0 -28
  247. package/skills/structure-prompt/reference/adversarial-tuning.md +0 -62
  248. package/skills/structure-prompt/reference/block-classification.md +0 -27
  249. package/skills/structure-prompt/reference/canonical-case.md +0 -48
  250. package/skills/structure-prompt/reference/citation-depth.md +0 -70
  251. package/skills/structure-prompt/reference/cleanup.md +0 -33
  252. package/skills/structure-prompt/reference/constraints.md +0 -33
  253. package/skills/structure-prompt/reference/directives.md +0 -37
  254. package/skills/structure-prompt/reference/examples.md +0 -72
  255. package/skills/structure-prompt/reference/instantiation.md +0 -51
  256. package/skills/structure-prompt/reference/output-contract.md +0 -72
  257. package/skills/structure-prompt/reference/per-category.md +0 -23
  258. package/skills/structure-prompt/reference/persona.md +0 -38
  259. package/skills/structure-prompt/reference/research.md +0 -33
  260. package/skills/structure-prompt/reference/structure.md +0 -28
  261. package/skills/verified-build/CLAUDE.md +0 -33
  262. package/skills/verified-build/SKILL.md +0 -33
@@ -1,205 +0,0 @@
1
- <#
2
- .SYNOPSIS
3
- Restores the Logitech Gaming Software (LCore) tray icon when it is missing on Windows.
4
-
5
- .DESCRIPTION
6
- Reproduces the verified recovery procedure from
7
- sessions/System Support/2. Logitech Tray Icon Fix Recurrence.md (2026-04-25):
8
- 1. Stops LCore in user context.
9
- 2. Single elevated UAC step:
10
- - Starts LogiRegistryService (handles the case where it is Stopped).
11
- - Stops explorer.exe and lets Windows shell auto-respawn rebuild it.
12
- Deliberately omits Start-Process explorer from the elevated block to
13
- avoid the duplicate admin-context explorer that blocked tray registration
14
- during Session 2.
15
- 3. Waits for shell auto-respawn.
16
- 4. Verifies a single user-session explorer.
17
- 5. Performs LCoreRelaunchAttemptCount full stop-then-launch cycles of
18
- LCore /minimized. Always runs the full count: a responsive LCore on the
19
- first attempt does NOT imply Shell_NotifyIcon registered, per Session 2
20
- gotcha #2 (responsive process, no tray icon).
21
-
22
- .PARAMETER ExplorerAutoRespawnWaitSeconds
23
- Seconds to wait after the elevated explorer kill before verifying respawn.
24
-
25
- .PARAMETER LCoreInitializationWaitSeconds
26
- Seconds to wait after each LCore relaunch before checking responsiveness.
27
-
28
- .PARAMETER LCoreRelaunchAttemptCount
29
- Total number of LCore relaunch cycles to perform (default 2). The full count
30
- always runs, because the documented failure mode is a responsive LCore that
31
- never registered a tray icon -- only a second stop+launch reliably triggers
32
- Shell_NotifyIcon registration.
33
- #>
34
-
35
- [CmdletBinding()]
36
- param(
37
- [int] $ExplorerAutoRespawnWaitSeconds = 5,
38
- [int] $LCoreInitializationWaitSeconds = 5,
39
- [int] $LCoreRelaunchAttemptCount = 2
40
- )
41
-
42
- Set-StrictMode -Version Latest
43
- $ErrorActionPreference = 'Stop'
44
-
45
- $script:LCoreExecutablePath = 'C:\Program Files\Logitech Gaming Software\LCore.exe'
46
- $script:LCoreProcessName = 'LCore'
47
-
48
- function Get-CurrentInteractiveSessionId {
49
- [OutputType([int])]
50
- param()
51
- return (Get-CimInstance Win32_Process -Filter "ProcessId=$PID").SessionId
52
- }
53
-
54
- function Get-ExplorerProcessesInSession {
55
- [OutputType([object[]])]
56
- param([Parameter(Mandatory)] [int] $TargetSessionId)
57
- $allExplorers = Get-CimInstance Win32_Process -Filter "Name='explorer.exe'"
58
- $matchingExplorers = @()
59
- foreach ($eachExplorer in $allExplorers) {
60
- if ($eachExplorer.SessionId -ne $TargetSessionId) { continue }
61
- $ownerInfo = Invoke-CimMethod -InputObject $eachExplorer -MethodName GetOwner -ErrorAction SilentlyContinue
62
- $matchingExplorers += [PSCustomObject]@{
63
- ProcessId = $eachExplorer.ProcessId
64
- SessionId = $eachExplorer.SessionId
65
- OwnerUser = if ($ownerInfo) { $ownerInfo.User } else { $null }
66
- CreationDate = $eachExplorer.CreationDate
67
- }
68
- }
69
- return ,$matchingExplorers
70
- }
71
-
72
- function Stop-LCoreIfRunning {
73
- [OutputType([void])]
74
- param()
75
- $stopSettleMilliseconds = 500
76
- Stop-Process -Name $script:LCoreProcessName -Force -ErrorAction SilentlyContinue
77
- Start-Sleep -Milliseconds $stopSettleMilliseconds
78
- }
79
-
80
- function Invoke-ElevatedExplorerRebuild {
81
- [OutputType([bool])]
82
- param()
83
- $elevatedScriptBlockText = @'
84
- Start-Service -Name LogiRegistryService -ErrorAction SilentlyContinue
85
- Stop-Process -Name explorer -Force -ErrorAction SilentlyContinue
86
- '@
87
- $encodedElevatedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($elevatedScriptBlockText))
88
- try {
89
- Start-Process -FilePath 'pwsh' `
90
- -ArgumentList '-NoProfile', '-EncodedCommand', $encodedElevatedCommand `
91
- -Verb RunAs `
92
- -Wait `
93
- -ErrorAction Stop
94
- return $true
95
- } catch {
96
- Write-Warning "Elevated step did not run: $($_.Exception.Message)"
97
- return $false
98
- }
99
- }
100
-
101
- function Start-LCoreMinimized {
102
- [OutputType([void])]
103
- param()
104
- $launchArguments = '/minimized'
105
- Start-Process -FilePath $script:LCoreExecutablePath -ArgumentList $launchArguments
106
- }
107
-
108
- function Test-LCoreIsResponding {
109
- [OutputType([bool])]
110
- param([Parameter(Mandatory)] [int] $WaitSeconds)
111
- Start-Sleep -Seconds $WaitSeconds
112
- $lcoreProcesses = Get-Process -Name $script:LCoreProcessName -ErrorAction SilentlyContinue
113
- if (-not $lcoreProcesses) { return $false }
114
- foreach ($eachLCore in @($lcoreProcesses)) {
115
- if (-not $eachLCore.Responding) { return $false }
116
- }
117
- return $true
118
- }
119
-
120
- function Write-StateSnapshot {
121
- [OutputType([void])]
122
- param([Parameter(Mandatory)] [string] $Label)
123
- $logitechServiceNamesToVerify = @('LogiRegistryService', 'logi_lamparray_service')
124
- Write-Host ""
125
- Write-Host "=== $Label ==="
126
- $sessionId = Get-CurrentInteractiveSessionId
127
- $explorersInSession = Get-ExplorerProcessesInSession -TargetSessionId $sessionId
128
- Write-Host "Explorer instances in session ${sessionId}: $($explorersInSession.Count)"
129
- if ($explorersInSession.Count -gt 0) {
130
- $explorersInSession | Format-Table ProcessId, OwnerUser, CreationDate -AutoSize | Out-String | Write-Host
131
- }
132
- $servicesObserved = Get-Service -Name $logitechServiceNamesToVerify -ErrorAction SilentlyContinue
133
- if ($servicesObserved) {
134
- $servicesObserved | Format-Table Name, Status -AutoSize | Out-String | Write-Host
135
- }
136
- $lcoreProcessesObserved = Get-Process -Name $script:LCoreProcessName -ErrorAction SilentlyContinue
137
- if ($lcoreProcessesObserved) {
138
- $lcoreProcessesObserved | Select-Object Id, Responding | Format-Table -AutoSize | Out-String | Write-Host
139
- } else {
140
- Write-Host "LCore not running."
141
- }
142
- }
143
-
144
- function Invoke-LogifixRecovery {
145
- [OutputType([void])]
146
- param()
147
-
148
- Write-StateSnapshot -Label 'Before'
149
-
150
- if (-not (Test-Path -Path $script:LCoreExecutablePath)) {
151
- Write-Error "LCore.exe not found at expected path: $script:LCoreExecutablePath"
152
- return
153
- }
154
-
155
- Stop-LCoreIfRunning
156
-
157
- $elevatedSucceeded = Invoke-ElevatedExplorerRebuild
158
- if (-not $elevatedSucceeded) {
159
- Write-Warning "UAC was canceled or the elevated step failed."
160
- Write-Warning "Fallback: open Task Manager (Ctrl+Shift+Esc), find 'Windows Explorer', right-click, Restart. Then re-run /logifix."
161
- return
162
- }
163
-
164
- Start-Sleep -Seconds $ExplorerAutoRespawnWaitSeconds
165
-
166
- $sessionId = Get-CurrentInteractiveSessionId
167
- $explorersAfterRespawn = Get-ExplorerProcessesInSession -TargetSessionId $sessionId
168
- $explorerCountAfterRespawn = @($explorersAfterRespawn).Count
169
- if ($explorerCountAfterRespawn -ne 1) {
170
- if ($explorerCountAfterRespawn -eq 0) {
171
- Write-Warning "No explorer.exe found in session $sessionId after $ExplorerAutoRespawnWaitSeconds-second wait."
172
- } else {
173
- Write-Warning "Expected exactly 1 explorer.exe in session $sessionId after shell auto-respawn, but found $explorerCountAfterRespawn."
174
- Write-Warning "Multiple explorer.exe processes in the same session reproduce the Session 2 duplicate-explorer failure mode that blocks tray icon registration."
175
- $explorersAfterRespawn | Format-Table ProcessId, OwnerUser, CreationDate -AutoSize | Out-String | Write-Host
176
- }
177
- Write-Warning "Restart Explorer manually via Task Manager (Ctrl+Shift+Esc, Windows Explorer, Restart), then re-run /logifix."
178
- return
179
- }
180
-
181
- $lastAttemptResponded = $false
182
- for ($attemptIndex = 1; $attemptIndex -le $LCoreRelaunchAttemptCount; $attemptIndex++) {
183
- Stop-LCoreIfRunning
184
- Start-LCoreMinimized
185
- $lastAttemptResponded = Test-LCoreIsResponding -WaitSeconds $LCoreInitializationWaitSeconds
186
- if ($lastAttemptResponded) {
187
- Write-Host "LCore relaunch attempt ${attemptIndex}: process is responding."
188
- } else {
189
- Write-Warning "LCore relaunch attempt ${attemptIndex}: process not responding."
190
- }
191
- }
192
-
193
- Write-StateSnapshot -Label 'After'
194
-
195
- if (-not $lastAttemptResponded) {
196
- Write-Warning "LCore did not respond after $LCoreRelaunchAttemptCount attempts."
197
- Write-Warning "Use Task Manager to Restart Windows Explorer, then re-run /logifix."
198
- return
199
- }
200
-
201
- Write-Host ""
202
- Write-Host "Recovery complete ($LCoreRelaunchAttemptCount stop+launch cycles performed). If the tray icon is still not visible, use Task Manager to Restart Windows Explorer (guaranteed correct session/elevation), then re-run /logifix."
203
- }
204
-
205
- Invoke-LogifixRecovery
@@ -1,34 +0,0 @@
1
- # monitor-open-prs skill
2
-
3
- Discovers every open pull request across the `jl-cmd/*` and `JonEcho/*` owner scopes, dispatches `/bugteam` on each with the `--bugbot-retrigger` flag, and polls for new Cursor bugbot replies after each bugteam run.
4
-
5
- **Trigger:** `/monitor-open-prs`, "sweep the open PRs", "audit the open PR backlog".
6
-
7
- ## Key files
8
-
9
- | File | Purpose |
10
- |---|---|
11
- | `SKILL.md` | Full workflow: refusal cases, discovery, dispatch, post-convergence polling, final report |
12
- | `test_skill_contract.py` | Contract tests for the skill |
13
- | `packages/claude-dev-env/skills/monitor-open-prs/scripts/discover_open_prs.py` | Shells out to `gh search prs` per owner scope and flattens results to a uniform dict shape |
14
- | `packages/claude-dev-env/skills/monitor-open-prs/scripts/test_discover_open_prs.py` | Tests for the discovery helper |
15
-
16
- ## Subdirectories
17
-
18
- | Directory | Role |
19
- |---|---|
20
- | `scripts/` | Discovery helper and its tests |
21
-
22
- ## Workflow summary
23
-
24
- 1. Call `discover_open_prs.discover_open_prs(all_owners=["jl-cmd", "JonEcho"])` to get the full open-PR list.
25
- 2. For each PR, invoke `/bugteam <pr_number>`; include `--bugbot-retrigger` only when bugbot is enabled (`reviews_disabled.py --reviewer bugbot` exits 1).
26
- 3. After each bugteam run, poll for new bugbot comments on a 60s → 120s → 240s → 480s → 960s backoff. Re-invoke bugteam if new findings appear.
27
- 4. Emit a sweep summary when all PRs exit polling.
28
-
29
- ## Refusals (checked first)
30
-
31
- - `CLAUDE_REVIEWS_DISABLED` has `bugteam` → stop with a message.
32
- - GitHub API not accessible → stop.
33
- - Uncommitted changes in the caller's repo → stop.
34
- - Required subagent types missing (`code-quality-agent`, `clean-coder`) → stop.
@@ -1,88 +0,0 @@
1
- ---
2
- name: monitor-open-prs
3
- description: >-
4
- Discover every open pull request across the jl-cmd/* and JonEcho/*
5
- owner scopes, spawn /bugteam on each in parallel with the bugbot
6
- re-trigger flag (--bugbot-retrigger), and poll Cursor's bugbot replies
7
- after convergence so any post-bugteam findings loop back through
8
- /bugteam. Triggers: '/monitor-open-prs', 'sweep the open PRs',
9
- 'audit the open PR backlog'.
10
- ---
11
-
12
- # Monitor Open PRs
13
-
14
- **Core principle:** One sweep covers every open PR across both owner scopes. Claude discovers PRs live via `scripts/discover_open_prs.py` which shells out to `gh search prs --owner <owner> --state open --json ...`, dispatches `/bugteam --bugbot-retrigger` per PR, then polls Cursor's bugbot replies until each PR is quiet for a full backoff cycle.
15
-
16
- ## Contents
17
-
18
- - Transport check — gh presence and auth route the sweep local or through the cloud transport
19
- - When this skill applies — refusal cases and trigger conditions
20
- - Discovery — `scripts/discover_open_prs.py` queries via `gh search prs` across both owner scopes
21
- - Dispatch — `/bugteam --bugbot-retrigger <pr_numbers...>`
22
- - Post-convergence polling — bugbot replies and re-invocation
23
- - `scripts/discover_open_prs.py` — the discovery helper
24
-
25
- ## Transport check (before any GitHub step)
26
-
27
- Run `command -v gh`; when it succeeds, run `gh auth status`; for each PR the sweep dispatches, `gh api repos/<owner>/<repo> --jq .permissions.push` must print `true`. When any check fails, run the `pr-loop-cloud-transport` skill first and route every `gh` operation in this skill through its substitution matrix, including the discovery query (`mcp__github__search_pull_requests` with `perPage` in place of `gh search prs`).
28
-
29
- ## When this skill applies
30
-
31
- `/monitor-open-prs` authorizes one full sweep over all open PRs in both owner scopes.
32
-
33
- Refusals — first match wins; respond with the quoted line exactly and stop:
34
-
35
- - **Disabled via environment.** When `CLAUDE_REVIEWS_DISABLED` (comma-separated, case-insensitive, whitespace-tolerant) has the token `bugteam`: `/monitor-open-prs is a /bugteam dispatcher and /bugteam is disabled via CLAUDE_REVIEWS_DISABLED.` Gate semantics live in the `reviewer-gates` skill ([../reviewer-gates/SKILL.md](../reviewer-gates/SKILL.md)).
36
- - **GitHub API not accessible.** `get_me failed. /monitor-open-prs needs active GitHub MCP credentials.`
37
- - **Dirty tree on the caller's repo.** `Uncommitted changes detected. Stash, commit, or revert before /monitor-open-prs.`
38
- - **Required subagents missing.** Confirm `code-quality-agent` and `clean-coder` exist. Else: `Required subagent type <name> not installed.`
39
-
40
- ## Discovery
41
-
42
- Call `scripts/discover_open_prs.discover_open_prs(all_owners=["jl-cmd", "JonEcho"])` to merge the live open-PR list across both scopes. The helper shells out to `gh search prs --owner <owner> --state open --json number,repository,url,headRefName,baseRefName` for each owner scope and flattens the result to a uniform dict shape with keys `number`, `owner`, `repo`, `head_ref`, `base_ref`, `url`. Empty scopes contribute empty lists; an entirely empty sweep returns `[]` and exits cleanly.
43
-
44
- ## Dispatch
45
-
46
- For each discovered PR:
47
-
48
- 1. Resolve the PR's repo checkout (existing worktree or fresh `git clone`).
49
- 2. From that checkout, invoke `/bugteam <pr_number>`. Include `--bugbot-retrigger` only when bugbot is enabled for the run — when `python "$HOME/.claude/_shared/pr-loop/scripts/reviews_disabled.py" --reviewer bugbot` exits 1. On exit 0 (bugbot disabled — the default) omit `--bugbot-retrigger` so the bugbot leg sits out the run.
50
- 3. The `--bugbot-retrigger` flag tells bugteam to post `bugbot run` as an issue comment after every successful FIX push so Cursor's bugbot re-evaluates the new commit.
51
- 4. Bugteam runs its own 20-loop audit/fix cycle per PR; this skill waits for each bugteam invocation to return before dispatching the next (or fanning out — see below).
52
-
53
- **Fan-out (optional):** when the discovered list has more than one PR, the skill may spawn `/bugteam` dispatches in parallel by issuing multiple `Agent` calls in a single assistant message. Each dispatch operates in its own per-PR worktree (bugteam Step 1.1). Serialize when the caller sets an explicit `--serial` flag.
54
-
55
- ## Post-Convergence Polling
56
-
57
- After a `/bugteam` invocation returns (converged, cap reached, stuck, or error), the PR may accumulate new Cursor bugbot comments within minutes. Poll for them:
58
-
59
- 1. Baseline: capture `since_timestamp` as the PR's last commit timestamp.
60
- 2. Every 60 seconds, call `pull_request_read(method="get", pullNumber=<pr_number>, owner=<owner>, repo=<repo>)` and filter the response's `comments` array for entries whose `.author.login` matches `"bugbot"` or `"cursor"` and `.createdAt` is after `<since_timestamp>`.
61
- 3. Back off: 60s → 120s → 240s → 480s → 960s. If five successive polls return empty, exit polling for this PR.
62
- 4. If bugbot posts a new finding in any poll, re-invoke `/bugteam <pr_number>` with the bugbot finding text seeded into the invocation's `bugs_to_fix` preamble. Reset the backoff.
63
-
64
- ### Polling Cost and Cadence
65
-
66
- The five-step backoff sums to `60 + 120 + 240 + 480 + 960 = 1860` seconds (~31 minutes) of idle polling per PR before the skill declares bugbot quiet. A sweep over ten open PRs therefore retains up to ~5 wall-clock hours of bugbot-watch time beyond the active `/bugteam` work. Callers who need faster turnaround should pass `--serial` to disable fan-out (so polling starts only after the previous PR finishes) or accept the tradeoff: the backoff exists specifically to catch late bugbot analyses that can take several minutes to appear after a push.
67
-
68
- ## Final Report
69
-
70
- After every PR has exited polling, emit:
71
-
72
- ```
73
- /monitor-open-prs sweep summary
74
- PRs discovered: <N>
75
- jl-cmd/*: <count>
76
- JonEcho/*: <count>
77
- PRs converged clean: <count>
78
- PRs hit 20-loop cap: <count>
79
- PRs stuck: <count>
80
- PRs errored: <count>
81
- Bugbot re-triggers fired: <count>
82
- ```
83
-
84
- ## Non-Negotiable Guardrails
85
-
86
- - Never pass `--no-verify` or `--no-gpg-sign` to git in any dispatched bugteam run.
87
- - Never open a PR from this skill; only comment on existing ones.
88
- - Never merge or close PRs; the skill is read + audit + patch only.
@@ -1,17 +0,0 @@
1
- # monitor-open-prs/scripts
2
-
3
- Discovery helper for the `monitor-open-prs` skill.
4
-
5
- ## Key files
6
-
7
- | File | Purpose |
8
- |---|---|
9
- | `discover_open_prs.py` | Queries `gh search prs` for each owner scope and flattens results to a uniform list of dicts |
10
- | `test_discover_open_prs.py` | Tests for the discovery helper |
11
-
12
- ## Conventions
13
-
14
- - `discover_open_prs(all_owners: list[str]) -> list[dict]` is the single entry point. It shells out to `gh search prs --owner <owner> --state open --json number,repository,url,headRefName,baseRefName` once per owner and merges the results.
15
- - Each returned dict has keys: `number`, `owner`, `repo`, `head_ref`, `base_ref`, `url`.
16
- - An empty scope or an empty sweep returns an empty list and exits cleanly with no errors.
17
- - The module is stateless and has no filesystem side effects.
@@ -1,69 +0,0 @@
1
- """Discover every open pull request across a list of owner scopes.
2
-
3
- Shells out to ``gh search prs --owner <owner> --state open --json ...`` once per
4
- owner, parses the JSON output, and flattens each entry to a uniform dict shape.
5
- The module is stateless, takes no filesystem side effects, and exposes a single
6
- ``discover_open_prs`` entry point consumed by the monitor-open-prs skill.
7
- """
8
-
9
- from __future__ import annotations
10
-
11
- import json
12
- import subprocess
13
-
14
-
15
- def build_gh_search_argv(owner: str) -> list[str]:
16
- gh_command_name = "gh"
17
- search_subcommand = ("search", "prs")
18
- owner_flag = "--owner"
19
- state_flag = "--state"
20
- state_open_value = "open"
21
- json_fields_flag = "--json"
22
- json_fields_value = "number,repository,url,headRefName,baseRefName"
23
- return [
24
- gh_command_name,
25
- *search_subcommand,
26
- owner_flag,
27
- owner,
28
- state_flag,
29
- state_open_value,
30
- json_fields_flag,
31
- json_fields_value,
32
- ]
33
-
34
-
35
- def split_repository_name(name_with_owner: str) -> tuple[str, str]:
36
- repo_separator = "/"
37
- if repo_separator not in name_with_owner:
38
- return "", name_with_owner
39
- owner_segment, repository_segment = name_with_owner.split(repo_separator, 1)
40
- return owner_segment, repository_segment
41
-
42
-
43
- def flatten_pr_entry(raw_pr_entry: dict) -> dict:
44
- name_with_owner = raw_pr_entry.get("repository", {}).get("nameWithOwner", "")
45
- owner_segment, repository_segment = split_repository_name(name_with_owner)
46
- return {
47
- "number": raw_pr_entry.get("number"),
48
- "owner": owner_segment,
49
- "repo": repository_segment,
50
- "head_ref": raw_pr_entry.get("headRefName", ""),
51
- "base_ref": raw_pr_entry.get("baseRefName", ""),
52
- "url": raw_pr_entry.get("url", ""),
53
- }
54
-
55
-
56
- def fetch_open_prs_for_owner(owner: str) -> list[dict]:
57
- search_argv = build_gh_search_argv(owner)
58
- completed_process = subprocess.run(
59
- search_argv, check=True, capture_output=True, text=True
60
- )
61
- raw_pr_entries = json.loads(completed_process.stdout)
62
- return [flatten_pr_entry(each_entry) for each_entry in raw_pr_entries]
63
-
64
-
65
- def discover_open_prs(all_owners: list[str]) -> list[dict]:
66
- all_discovered: list[dict] = []
67
- for each_owner in all_owners:
68
- all_discovered.extend(fetch_open_prs_for_owner(each_owner))
69
- return all_discovered
@@ -1,149 +0,0 @@
1
- """Tests for discover_open_prs.py — merges gh-search output across owners."""
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import json
7
- import pathlib
8
- import sys
9
-
10
- import pytest
11
-
12
-
13
- def _load_discovery_module():
14
- scripts_directory = pathlib.Path(__file__).parent
15
- sys.path.insert(0, str(scripts_directory))
16
- module_path = scripts_directory / "discover_open_prs.py"
17
- module_spec = importlib.util.spec_from_file_location(
18
- "discover_open_prs", module_path
19
- )
20
- loaded_module = importlib.util.module_from_spec(module_spec)
21
- sys.modules["discover_open_prs"] = loaded_module
22
- module_spec.loader.exec_module(loaded_module)
23
- return loaded_module
24
-
25
-
26
- discover_open_prs = _load_discovery_module()
27
-
28
-
29
- def _make_fake_gh(responses_by_owner: dict):
30
- """Return a callable whose behavior mocks subprocess.run for gh search."""
31
-
32
- class FakeCompletedProcess:
33
- def __init__(self, stdout_text: str):
34
- self.stdout = stdout_text
35
- self.returncode = 0
36
-
37
- def fake_run(command_argv, check, capture_output, text):
38
- owner = _extract_owner_argument(command_argv)
39
- stdout_text = json.dumps(responses_by_owner.get(owner, []))
40
- return FakeCompletedProcess(stdout_text)
41
-
42
- return fake_run
43
-
44
-
45
- def _extract_owner_argument(command_argv) -> str:
46
- for each_index, each_token in enumerate(command_argv):
47
- if each_token == "--owner":
48
- return command_argv[each_index + 1]
49
- return ""
50
-
51
-
52
- class TestDiscoverOpenPrsBothOwnersReturnResults:
53
- def test_merges_prs_across_both_owners(self, monkeypatch):
54
- first_owner_prs = [
55
- {
56
- "number": 1,
57
- "repository": {"nameWithOwner": "jl-cmd/alpha"},
58
- "url": "https://github.com/jl-cmd/alpha/pull/1",
59
- "headRefName": "feat-one",
60
- "baseRefName": "main",
61
- }
62
- ]
63
- second_owner_prs = [
64
- {
65
- "number": 2,
66
- "repository": {"nameWithOwner": "JonEcho/beta"},
67
- "url": "https://github.com/JonEcho/beta/pull/2",
68
- "headRefName": "feat-two",
69
- "baseRefName": "main",
70
- }
71
- ]
72
- fake_run = _make_fake_gh(
73
- {"jl-cmd": first_owner_prs, "JonEcho": second_owner_prs}
74
- )
75
- monkeypatch.setattr(discover_open_prs.subprocess, "run", fake_run)
76
-
77
- all_discovered = discover_open_prs.discover_open_prs(
78
- all_owners=["jl-cmd", "JonEcho"]
79
- )
80
-
81
- assert len(all_discovered) == 2
82
- discovered_numbers = sorted(each["number"] for each in all_discovered)
83
- assert discovered_numbers == [1, 2]
84
-
85
-
86
- class TestDiscoverOpenPrsOneOwnerEmpty:
87
- def test_handles_single_owner_returning_empty_list(self, monkeypatch):
88
- first_owner_prs = [
89
- {
90
- "number": 5,
91
- "repository": {"nameWithOwner": "jl-cmd/gamma"},
92
- "url": "https://github.com/jl-cmd/gamma/pull/5",
93
- "headRefName": "feat-five",
94
- "baseRefName": "main",
95
- }
96
- ]
97
- fake_run = _make_fake_gh({"jl-cmd": first_owner_prs, "JonEcho": []})
98
- monkeypatch.setattr(discover_open_prs.subprocess, "run", fake_run)
99
-
100
- all_discovered = discover_open_prs.discover_open_prs(
101
- all_owners=["jl-cmd", "JonEcho"]
102
- )
103
-
104
- assert len(all_discovered) == 1
105
- assert all_discovered[0]["number"] == 5
106
-
107
-
108
- class TestDiscoverOpenPrsBothEmpty:
109
- def test_returns_empty_list_when_no_owner_has_open_prs(self, monkeypatch):
110
- fake_run = _make_fake_gh({"jl-cmd": [], "JonEcho": []})
111
- monkeypatch.setattr(discover_open_prs.subprocess, "run", fake_run)
112
-
113
- all_discovered = discover_open_prs.discover_open_prs(
114
- all_owners=["jl-cmd", "JonEcho"]
115
- )
116
-
117
- assert all_discovered == []
118
-
119
-
120
- class TestDiscoverOpenPrsEntryShape:
121
- def test_each_entry_exposes_number_owner_repo_refs_and_url(self, monkeypatch):
122
- fake_run = _make_fake_gh(
123
- {
124
- "jl-cmd": [
125
- {
126
- "number": 42,
127
- "repository": {"nameWithOwner": "jl-cmd/demo"},
128
- "url": "https://github.com/jl-cmd/demo/pull/42",
129
- "headRefName": "feat-demo",
130
- "baseRefName": "main",
131
- }
132
- ],
133
- "JonEcho": [],
134
- }
135
- )
136
- monkeypatch.setattr(discover_open_prs.subprocess, "run", fake_run)
137
-
138
- all_discovered = discover_open_prs.discover_open_prs(
139
- all_owners=["jl-cmd", "JonEcho"]
140
- )
141
-
142
- assert len(all_discovered) == 1
143
- only_entry = all_discovered[0]
144
- assert only_entry["number"] == 42
145
- assert only_entry["owner"] == "jl-cmd"
146
- assert only_entry["repo"] == "demo"
147
- assert only_entry["head_ref"] == "feat-demo"
148
- assert only_entry["base_ref"] == "main"
149
- assert only_entry["url"].endswith("/pull/42")
@@ -1,27 +0,0 @@
1
- """Markdown assertion tests for monitor-open-prs SKILL.md."""
2
-
3
- from __future__ import annotations
4
-
5
- import pathlib
6
-
7
-
8
- def _read_skill_text() -> str:
9
- skill_path = pathlib.Path(__file__).parent / "SKILL.md"
10
- return skill_path.read_text(encoding="utf-8")
11
-
12
-
13
- def test_skill_has_frontmatter_name():
14
- skill_text = _read_skill_text()
15
- assert skill_text.startswith("---\n")
16
- assert "name: monitor-open-prs" in skill_text
17
-
18
-
19
- def test_skill_references_bugbot_retrigger_flag():
20
- skill_text = _read_skill_text()
21
- assert "--bugbot-retrigger" in skill_text
22
-
23
-
24
- def test_skill_enumerates_both_owner_scopes():
25
- skill_text = _read_skill_text()
26
- assert "jl-cmd" in skill_text
27
- assert "JonEcho" in skill_text