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
@@ -31,26 +31,7 @@ Adds nothing beyond common. Single subagent loops internally and returns a final
31
31
 
32
32
  ### pr-converge
33
33
 
34
- Adds the same **traffic** fields whether they live in **`state.json`** or in the **conversation state line**; only the **store** differs.
35
-
36
- | Field | Type | Purpose |
37
- |---|---|---|
38
- | `phase` | enum | `BUGBOT`, `BUGTEAM` — which reviewer the current tick drives |
39
- | `current_head` | str | PR `.head.sha` / `git rev-parse` for the PR under work (each tick; from `pull_request_read(method="get")` when no file store) |
40
- | `bugbot_clean_at` | str \| null | HEAD SHA at which Cursor Bugbot last reported clean, or `null` (reset on every push) |
41
- | `copilot_clean_at` | str \| null | HEAD SHA at which the GitHub Copilot reviewer (`copilot-pull-request-reviewer[bot]`) last reported clean (review `state == "APPROVED"`), or `null`. Reset on every push. Convergence gates require this equals `current_head` after bugbot+bugteam are clean (see `skills/pr-converge/SKILL.md` § Convergence gates). |
42
- | `merge_state_status` | str \| null | Last-observed `mergeable_state` from `pull_request_read(method="get")` (e.g., `clean`, `dirty`, `blocked`, `behind`, `unknown`), or `null` before the first check. Reset on every push. `dirty` triggers the rebase invocation; non-`clean` non-`dirty` is a hard blocker per pr-converge `Stop conditions`. |
43
- | `inline_lag_streak` | int | Consecutive ticks where bugbot's review body claims findings but inline-comments API returns zero rows for `current_head` |
44
- | `tick_count` | int | Observability only — **no ceiling**; loop ends on convergence or **Stop conditions** in `pr-converge` |
45
-
46
- **Dual persistence** (normative: `skills/pr-converge/SKILL.md` § State across ticks, § Multi-PR orchestration model):
47
-
48
- | Mode | When it applies | Source of truth | `tick_count` bump |
49
- |---|---|---|---|
50
- | **`state.json`** | File exists at `<TMPDIR>/pr-converge-<session_id>/state.json` (multi-PR orchestration or other file-backed session) | JSON: top-level `session_id`; per-PR objects under `prs[<number>]` with `owner`, `repo`, `branch`, `phase`, `current_head`, `bugbot_clean_at`, `inline_lag_streak`, `tick_count`, `last_action`, `status`, `last_updated`. Optional sibling `converged.log` (append-only; multi-PR only). Writes use lock + atomic replace per skill **Concurrency** | **Orchestrator only** at tick start (locked merge for every non-terminal PR); **never** bump `tick_count` in Step 1 when this file is in use |
51
- | **Conversation state line** | **No** `state.json` (typical single-PR `/pr-converge` in Cursor) | Persist **`phase`**, **`bugbot_clean_at`**, **`inline_lag_streak`**, **`tick_count`** as **plain text** in each assistant turn; next tick reads them from the **most recent assistant message**. **`current_head` is not serialized in that line** — re-resolve each tick via `pull_request_read(method="get")` (same contract as `skills/pr-converge/SKILL.md` § State across ticks). | **Step 1** increments `tick_count` in that line **only** when no `state.json` — must not double-count with any file-backed path |
52
-
53
- **`status` (file-backed `prs[...]` only):** `fresh | in_progress | awaiting_bugbot | awaiting_bugteam | converged | blocked`
34
+ Normative field list, phase enum, dual persistence, and reset semantics: [`../../skills/pr-converge/reference/state-schema.md`](../../skills/pr-converge/reference/state-schema.md). File-backed multi-PR `status` enum: [`../../skills/pr-converge/reference/multi-pr-orchestration.md`](../../skills/pr-converge/reference/multi-pr-orchestration.md).
54
35
 
55
36
  ### monitor-many
56
37
 
@@ -71,11 +52,11 @@ Adds per-PR JSON state file at `~/.claude/skills/monitor-many/state/<owner>-<rep
71
52
 
72
53
  - bugteam: cleared on each new `/bugteam` invocation
73
54
  - qbug: cleared on each new `/qbug` invocation
74
- - pr-converge: `bugbot_clean_at`, `copilot_clean_at`, and `merge_state_status` all reset to `null` on every push (a new commit invalidates every reviewer's prior clean and the prior mergeability snapshot by definition); `phase` cycles each tick. With `state.json`, orchestrator reads that file at tick start; without it, rely on the prior conversation state line — **never** mix both increment rules for `tick_count` on the same run
55
+ - pr-converge: see [`../../skills/pr-converge/reference/state-schema.md`](../../skills/pr-converge/reference/state-schema.md)
75
56
  - monitor-many: persists across orchestrator runs; only `last_seen_comment_id` advances monotonically
76
57
 
77
58
  ## Convergence checks
78
59
 
79
60
  - bugteam, qbug: `last_action == "audited"` AND `last_findings.total == 0` → `converged`
80
- - pr-converge: `bugbot_clean_at == current_head` AND most-recent bugteam exit is `converged` AND no push during the bugteam tick AND no outstanding Copilot findings on `current_head` AND `merge_state_status == "clean"` (per `skills/pr-converge/SKILL.md` § Convergence gates) → back-to-back clean → `update_pull_request(draft=false)` (read `current_head` / `bugbot_clean_at` / `copilot_clean_at` / `merge_state_status` from `state.json` when file-backed, else from the conversation state line and Step 1 `pull_request_read(method="get")` output)
61
+ - pr-converge: see [`../../skills/pr-converge/reference/convergence-gates.md`](../../skills/pr-converge/reference/convergence-gates.md)
81
62
  - monitor-many: no unresolved comments requiring code changes AND required checks green AND review policy satisfied → `gh pr ready`
package/bin/CLAUDE.md CHANGED
@@ -6,7 +6,8 @@ The installer and its companion modules. Running `npx claude-dev-env` (or `node
6
6
 
7
7
  | File | Purpose |
8
8
  |---|---|
9
- | `install.mjs` | Main installer: discovers install groups, copies content directories (`rules`, `docs`, `commands`, `agents`, `system-prompts`, `scripts`, `_shared`, `audit-rubrics`), merges hooks into `settings.json`, installs skills, runs `git_hooks_installer.mjs` and `install_mypy_ini.mjs` |
9
+ | `install.mjs` | Main installer: discovers install groups, copies content directories (`rules`, `docs`, `commands`, `agents`, `system-prompts`, `scripts`, `_shared`, `audit-rubrics`), merges hooks into `settings.json`, installs skills, prunes retired skills on a full install, runs `git_hooks_installer.mjs` and `install_mypy_ini.mjs` |
10
+ | `ever-shipped-skills.mjs` | Static `EVER_SHIPPED_SKILL_NAMES` set of every top-level skill directory name the package has shipped; the installer subtracts the current skill set from it to prune retired skills left under `~/.claude/skills` |
10
11
  | `expand_home_directory_tokens.mjs` | Expands residual `$HOME` / `${HOME}` / `~/` tokens in settings.json hook and statusLine commands to absolute home paths at install time (literal-safe for homes that contain `$`) |
11
12
  | `git_hooks_installer.mjs` | Installs or updates the `pre-commit`, `pre-push`, and `post-commit` Git hooks in the user's git config; writes hook scripts that delegate to the installed Python hooks |
12
13
  | `install_mypy_ini.mjs` | Writes `~/.mypy.ini` with settings that make mypy find the hooks package and enforce strict type checking |
@@ -14,6 +15,14 @@ The installer and its companion modules. Running `npx claude-dev-env` (or `node
14
15
  | `git_hooks_installer.test.mjs` | Tests for `git_hooks_installer.mjs` |
15
16
  | `install_mypy_ini.test.mjs` | Tests for `install_mypy_ini.mjs` |
16
17
 
18
+ ## Retired-skill prune
19
+
20
+ The full-install prune renames a retired skill directory into a timestamped backup rather than deleting it. Each pruned directory is renamed to `~/.claude/.claude-dev-env-pruned/<timestamp>/<skill-name>/`, a backup root outside `~/.claude/skills` so a backed-up directory is never re-discovered as a skill. Backups accumulate — nothing cleans them — so a user can recover a directory. A rename that fails leaves the directory in place with a logged warning and never falls back to deletion, so a prune failure costs at most a cosmetic leftover.
21
+
22
+ Matching is by directory name alone, so a user-authored directory whose name collides with a retired skill is backed up as if it were that skill. A directory is pruned when the prior install's manifest recorded it or the ever-shipped set names it, and the current install did not just write it. A name absent from all three of those sets, together with `~/.claude/skills/_shared`, is left in place.
23
+
24
+ The prune is skipped for the whole run — with a logged notice naming the unresolved group — when any declared dependency group fails to resolve. An unresolved dependency contributes no skills to the installed set, so a live skill that a dependency package supplies would look retired; holding the prune until every dependency resolves keeps such a skill from being backed up.
25
+
17
26
  ## Key exports from install.mjs
18
27
 
19
28
  | Export | Description |
@@ -26,4 +35,4 @@ The installer and its companion modules. Running `npx claude-dev-env` (or `node
26
35
 
27
36
  ## Install groups
28
37
 
29
- `install.mjs` defines install groups (`core`, `journal`, `research`) plus any dependency groups discovered from `package.json` `dependencies`. The `core` group installs skills, all hooks, and the content directories. `journal` and `research` install only their skill sets.
38
+ `install.mjs` defines install groups (`core`, `journal`) plus any dependency groups discovered from `package.json` `dependencies`. The `core` group installs skills, all hooks, and the content directories. `journal` installs only its skill set.
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The top-level skill directory names this package has ever shipped.
3
+ *
4
+ * The installer subtracts the skills the current package installs from this set
5
+ * to learn which shipped skills have retired, so a full reinstall can remove a
6
+ * retired skill left behind under ~/.claude/skills. Because the current set is
7
+ * subtracted at runtime, restoring a retired skill to the package protects it
8
+ * automatically — it re-enters the installed set and drops out of the retired
9
+ * set on the next install.
10
+ *
11
+ * The list is a committed literal rather than a git query, because a user
12
+ * installs from the npm tarball, which carries no source-repo history. Refresh
13
+ * it by running, from the repository root:
14
+ *
15
+ * git log --all --pretty=format: --name-only -- 'packages/claude-dev-env/skills/*\/SKILL.md' | sort -u
16
+ *
17
+ * and pasting each distinct top-level skill directory name below.
18
+ */
19
+ export const EVER_SHIPPED_SKILL_NAMES = new Set([
20
+ 'anthropic-plan',
21
+ 'auditing-claude-config',
22
+ 'autoconverge',
23
+ 'bdd-protocol',
24
+ 'bg-agent',
25
+ 'bugteam',
26
+ 'caveman',
27
+ 'code',
28
+ 'copilot-finding-triage',
29
+ 'copilot-review',
30
+ 'deep-research',
31
+ 'everything-search',
32
+ 'findbugs',
33
+ 'fixbugs',
34
+ 'fresh-branch',
35
+ 'gh-paginate',
36
+ 'gotcha',
37
+ 'grokify',
38
+ 'implement',
39
+ 'log-audit',
40
+ 'logifix',
41
+ 'monitor-open-prs',
42
+ 'orchestrator',
43
+ 'orchestrator-refresh',
44
+ 'post-audit-findings',
45
+ 'pr-consistency-audit',
46
+ 'pr-converge',
47
+ 'pr-fix-protocol',
48
+ 'pr-loop-cloud-transport',
49
+ 'pr-loop-lifecycle',
50
+ 'pr-review-responder',
51
+ 'pr-scope-resolve',
52
+ 'pre-compact',
53
+ 'privacy-hygiene',
54
+ 'qbug',
55
+ 'rebase',
56
+ 'recall',
57
+ 'refine',
58
+ 'remember',
59
+ 'research-mode',
60
+ 'reviewer-gates',
61
+ 'session-log',
62
+ 'session-tidy',
63
+ 'skill-builder',
64
+ 'structure-prompt',
65
+ 'task-build',
66
+ 'team-advisor',
67
+ 'update',
68
+ 'usage-pause',
69
+ 'verified-build',
70
+ ]);
package/bin/install.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync, copyFileSync, unlinkSync, rmSync, realpathSync } from 'node:fs';
4
- import { join, dirname, resolve, relative } from 'node:path';
3
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync, copyFileSync, unlinkSync, rmSync, renameSync, realpathSync } from 'node:fs';
4
+ import { join, dirname, resolve, relative, basename } from 'node:path';
5
5
  import { homedir } from 'node:os';
6
6
  import { execSync, execFileSync } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
@@ -9,6 +9,7 @@ import { createRequire } from 'node:module';
9
9
  import { installAllGitHooks } from './git_hooks_installer.mjs';
10
10
  import { installMypyIniForClaudeHooks } from './install_mypy_ini.mjs';
11
11
  import { expandHomeDirectoryTokensInSettings } from './expand_home_directory_tokens.mjs';
12
+ import { EVER_SHIPPED_SKILL_NAMES } from './ever-shipped-skills.mjs';
12
13
 
13
14
  const CLAUDE_HOME = join(homedir(), '.claude');
14
15
  const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
@@ -19,6 +20,10 @@ const packageRequire = createRequire(import.meta.url);
19
20
 
20
21
  export const CONTENT_DIRECTORIES = ['rules', 'docs', 'commands', 'agents', 'system-prompts', 'scripts', '_shared', 'audit-rubrics'];
21
22
 
23
+ const SKILL_MANIFEST_FILENAME = 'SKILL.md';
24
+ const NEVER_PRUNED_SKILL_DIRECTORIES = new Set(['_shared']);
25
+ const PRUNED_SKILLS_BACKUP_DIRECTORY_NAME = '.claude-dev-env-pruned';
26
+
22
27
  export const CORE_INCLUDE_DIRECTORIES = [
23
28
  'rules', 'docs', 'commands', 'agents', 'audit-rubrics', '_shared', 'scripts',
24
29
  ];
@@ -94,17 +99,33 @@ function resolveDependencyPackageRoot(dependencyPackageName) {
94
99
  return dirname(dependencyPackageJsonPath);
95
100
  }
96
101
 
102
+ /**
103
+ * Discovers the install groups contributed by resolvable dependency packages and
104
+ * the names of the declared dependencies that failed to resolve.
105
+ *
106
+ * A dependency that cannot be resolved contributes no group, so its skills never
107
+ * enter the installed set. The retired-skill prune subtracts the installed set
108
+ * from the ever-shipped set, so an unresolved dependency whose skills migrated
109
+ * out of the main package would leave those live skills looking retired. The
110
+ * returned unresolved-name list lets the caller skip the prune in that degraded
111
+ * mode rather than delete a live skill.
112
+ *
113
+ * @returns {{groups: object, unresolvedDependencyNames: string[]}} The resolvable
114
+ * dependency groups keyed by group name, and the names that failed to resolve.
115
+ */
97
116
  function discoverDependencyGroups() {
98
117
  const ownPackageJsonPath = join(PACKAGE_ROOT, 'package.json');
99
118
  const ownPackageJson = JSON.parse(readFileSync(ownPackageJsonPath, 'utf8'));
100
119
  const dependencies = ownPackageJson.dependencies || {};
101
120
  const discoveredGroups = {};
121
+ const unresolvedDependencyNames = [];
102
122
  for (const dependencyName of Object.keys(dependencies)) {
103
123
  let dependencyRoot;
104
124
  try {
105
125
  dependencyRoot = resolveDependencyPackageRoot(dependencyName);
106
126
  } catch {
107
127
  console.error(` WARNING: Could not resolve dependency ${dependencyName}, skipping`);
128
+ unresolvedDependencyNames.push(dependencyName);
108
129
  continue;
109
130
  }
110
131
  const dependencyPackageJson = JSON.parse(
@@ -145,18 +166,20 @@ function discoverDependencyGroups() {
145
166
  }
146
167
  discoveredGroups[groupName] = group;
147
168
  }
148
- return discoveredGroups;
169
+ return { groups: discoveredGroups, unresolvedDependencyNames };
149
170
  }
150
171
 
172
+ const dependencyDiscovery = discoverDependencyGroups();
173
+ const UNRESOLVED_DEPENDENCY_NAMES = dependencyDiscovery.unresolvedDependencyNames;
174
+
151
175
  const INSTALL_GROUPS = {
152
176
  core: {
153
177
  description: 'Development standards, hooks, agents, commands',
154
178
  skills: [
155
- 'orchestrator', 'orchestrator-refresh', 'team-advisor',
179
+ 'orchestrator', 'orchestrator-refresh', 'team-advisor', 'grokify',
156
180
  'anthropic-plan', 'everything-search',
157
- 'pr-review-responder',
158
181
  'privacy-hygiene',
159
- 'recall', 'remember', 'task-build', 'verified-build'
182
+ 'recall', 'remember', 'task-build'
160
183
  ],
161
184
  includeDirectories: CORE_INCLUDE_DIRECTORIES,
162
185
  includeAllHooks: true,
@@ -165,11 +188,7 @@ const INSTALL_GROUPS = {
165
188
  description: 'Session logging and memory',
166
189
  skills: ['session-log', 'session-tidy'],
167
190
  },
168
- research: {
169
- description: 'Deep research and citation tools',
170
- skills: ['deep-research', 'research-mode'],
171
- },
172
- ...discoverDependencyGroups(),
191
+ ...dependencyDiscovery.groups,
173
192
  };
174
193
 
175
194
  /**
@@ -611,11 +630,99 @@ function mergeHooks(hooksSourceRoot, pythonCommand) {
611
630
  return groupCount;
612
631
  }
613
632
 
614
- function writeManifest(installedFiles) {
633
+ function writeManifest(installedFiles, skillNames) {
615
634
  const manifest = { package: PACKAGE_NAME, version: PACKAGE_VERSION, installedAt: new Date().toISOString(), files: installedFiles };
635
+ if (skillNames) {
636
+ manifest.skills = skillNames;
637
+ }
616
638
  writeFileSync(MANIFEST_FILE, JSON.stringify(manifest, null, 2) + '\n');
617
639
  }
618
640
 
641
+ /**
642
+ * Read the skill directory names the previous install recorded.
643
+ *
644
+ * Returns null when no manifest exists or the manifest predates the skills key,
645
+ * so a caller can treat "unknown prior skills" the same in both cases and lean
646
+ * on the ever-shipped set to find retired skills.
647
+ *
648
+ * @returns {string[]|null} The prior manifest's skill names, or null when absent.
649
+ */
650
+ function readPriorManifestSkills() {
651
+ if (!existsSync(MANIFEST_FILE)) return null;
652
+ try {
653
+ const priorManifest = JSON.parse(readFileSync(MANIFEST_FILE, 'utf8'));
654
+ return Array.isArray(priorManifest.skills) ? priorManifest.skills : null;
655
+ } catch {
656
+ return null;
657
+ }
658
+ }
659
+
660
+ /**
661
+ * Move retired skill directories a prior install left under ~/.claude/skills into
662
+ * a timestamped backup directory rather than deleting them.
663
+ *
664
+ * A directory is pruned only when the package no longer ships it and either the
665
+ * prior manifest recorded it or the package once shipped it. Subtracting the
666
+ * just-installed set from the ever-shipped set at call time means restoring a
667
+ * skill to the package protects it — it re-enters the installed set and never
668
+ * counts as retired. Matching is by directory name alone, so a personal
669
+ * directory a user authored under a name that collides with a retired skill
670
+ * (for example `code`, `implement`, `refine`, `gotcha`, `caveman`) is treated as
671
+ * that retired skill and moved to backup; only a name in neither set, and
672
+ * ~/.claude/skills/_shared, are left in place.
673
+ *
674
+ * Each pruned directory is renamed to
675
+ * ~/.claude/.claude-dev-env-pruned/<timestamp>/<skill-name>/ — a backup root
676
+ * outside ~/.claude/skills, so a moved directory is never re-discovered as a
677
+ * skill — under one shared timestamp per run. A backup is never cleaned up, so a
678
+ * user can recover a wrongly-matched directory. One directory whose rename fails
679
+ * (for example a read-only file or a cross-device move) is logged and left in
680
+ * place, never deleted, so a prune failure costs at most a cosmetic leftover.
681
+ *
682
+ * @param {Set<string>} installedSkillNames Skill names this install just wrote.
683
+ * @param {string[]|null} priorManifestSkills The prior manifest's skill names, or null.
684
+ */
685
+ function pruneRetiredSkills(installedSkillNames, priorManifestSkills) {
686
+ const skillsDirectory = join(CLAUDE_HOME, 'skills');
687
+ if (!existsSync(skillsDirectory)) return;
688
+ const retiredSkillNames = new Set(
689
+ [...EVER_SHIPPED_SKILL_NAMES].filter(skillName => !installedSkillNames.has(skillName))
690
+ );
691
+ const priorSkillNames = new Set(priorManifestSkills || []);
692
+ const runTimestamp = new Date().toISOString().replace(/[:.]/g, '-');
693
+ const backupRoot = join(CLAUDE_HOME, PRUNED_SKILLS_BACKUP_DIRECTORY_NAME, runTimestamp);
694
+ const existingSkillDirs = readdirSync(skillsDirectory, { withFileTypes: true })
695
+ .filter(entry => entry.isDirectory());
696
+ for (const skillDir of existingSkillDirs) {
697
+ const skillName = skillDir.name;
698
+ if (NEVER_PRUNED_SKILL_DIRECTORIES.has(skillName)) continue;
699
+ if (installedSkillNames.has(skillName)) continue;
700
+ const isPruneCandidate = priorSkillNames.has(skillName) || retiredSkillNames.has(skillName);
701
+ if (!isPruneCandidate) continue;
702
+ moveRetiredSkillToBackup(skillsDirectory, backupRoot, skillName);
703
+ }
704
+ }
705
+
706
+ /**
707
+ * Move one retired skill directory into the run's backup root, leaving it in
708
+ * place when the move fails.
709
+ *
710
+ * @param {string} skillsDirectory The ~/.claude/skills directory holding the skill.
711
+ * @param {string} backupRoot The run's timestamped backup directory.
712
+ * @param {string} skillName The retired skill directory name to move.
713
+ */
714
+ function moveRetiredSkillToBackup(skillsDirectory, backupRoot, skillName) {
715
+ const skillPath = join(skillsDirectory, skillName);
716
+ const backupPath = join(backupRoot, skillName);
717
+ try {
718
+ mkdirSync(backupRoot, { recursive: true });
719
+ renameSync(skillPath, backupPath);
720
+ console.log(` ✗ ${join('skills', skillName)} (retired — moved to ${join(PRUNED_SKILLS_BACKUP_DIRECTORY_NAME, basename(backupRoot), skillName)})`);
721
+ } catch (moveError) {
722
+ console.warn(` Warning: could not move retired ${join('skills', skillName)} to backup, leaving in place (${moveError.message})`);
723
+ }
724
+ }
725
+
619
726
  function install(selectedGroups, options = {}) {
620
727
  const isUpdateRefresh = Boolean(options.isUpdateRefresh);
621
728
  if (isUpdateRefresh && !selectedGroups && existsSync(MANIFEST_FILE)) {
@@ -713,6 +820,7 @@ function install(selectedGroups, options = {}) {
713
820
  let skillsCreated = 0;
714
821
  let skillsUpdated = 0;
715
822
  const skillPaths = [];
823
+ const installedSkillNames = new Set();
716
824
  for (const sourceRoot of allSourceRoots) {
717
825
  const skillsSource = join(sourceRoot, 'skills');
718
826
  if (!existsSync(skillsSource)) continue;
@@ -723,6 +831,9 @@ function install(selectedGroups, options = {}) {
723
831
  skillsCreated += stats.created;
724
832
  skillsUpdated += stats.updated;
725
833
  skillPaths.push(...stats.paths);
834
+ if (existsSync(join(skillsSource, skillDir.name, SKILL_MANIFEST_FILENAME))) {
835
+ installedSkillNames.add(skillDir.name);
836
+ }
726
837
  }
727
838
  }
728
839
  summary.skills = { created: skillsCreated, updated: skillsUpdated, paths: skillPaths };
@@ -809,7 +920,21 @@ function install(selectedGroups, options = {}) {
809
920
  allInstalledFiles.push(claudeHubDest);
810
921
  console.log(` \u2713 ${relative(CLAUDE_HOME, claudeHubDest)} (hub)`);
811
922
  }
812
- writeManifest(allInstalledFiles);
923
+ const isFullInstall = !selectedGroups;
924
+ const priorManifestSkills = readPriorManifestSkills();
925
+ let manifestSkillNames = priorManifestSkills;
926
+ if (isFullInstall) {
927
+ if (UNRESOLVED_DEPENDENCY_NAMES.length > 0) {
928
+ console.log(
929
+ ` Skipping retired-skill prune — unresolved dependency group(s): ${UNRESOLVED_DEPENDENCY_NAMES.join(', ')}. `
930
+ + 'A skill that migrated to a dependency package would look retired and be moved to backup, so the prune is held until every dependency resolves.',
931
+ );
932
+ } else {
933
+ pruneRetiredSkills(installedSkillNames, priorManifestSkills);
934
+ }
935
+ manifestSkillNames = [...installedSkillNames].sort();
936
+ }
937
+ writeManifest(allInstalledFiles, manifestSkillNames);
813
938
  console.log(`\nInstalled ${PACKAGE_NAME}:`);
814
939
  for (const directory of CONTENT_DIRECTORIES) {
815
940
  if (summary[directory]) {