@wipcomputer/wip-ai-devops-toolbox 1.9.59 → 1.9.60

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 (739) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/SKILL.md +1 -1
  3. package/package.json +1 -1
  4. package/tools/deploy-public/package.json +1 -1
  5. package/tools/post-merge-rename/package.json +1 -1
  6. package/tools/wip-branch-guard/package.json +1 -1
  7. package/tools/wip-file-guard/package.json +1 -1
  8. package/tools/wip-license-guard/package.json +1 -1
  9. package/tools/wip-license-hook/package.json +1 -1
  10. package/tools/wip-readme-format/package.json +1 -1
  11. package/tools/wip-release/package.json +1 -1
  12. package/tools/wip-repo-init/package.json +1 -1
  13. package/tools/wip-repo-permissions-hook/package.json +1 -1
  14. package/tools/wip-repos/package.json +1 -1
  15. package/tools/wip-universal-installer/package.json +1 -1
  16. package/.worktrees/toolbox--guard-plan/.license-guard.json +0 -7
  17. package/.worktrees/toolbox--guard-plan/.publish-skill.json +0 -4
  18. package/.worktrees/toolbox--guard-plan/CHANGELOG.md +0 -1965
  19. package/.worktrees/toolbox--guard-plan/CLA.md +0 -19
  20. package/.worktrees/toolbox--guard-plan/DEV-GUIDE-GENERAL-PUBLIC.md +0 -949
  21. package/.worktrees/toolbox--guard-plan/LICENSE +0 -52
  22. package/.worktrees/toolbox--guard-plan/README.md +0 -238
  23. package/.worktrees/toolbox--guard-plan/RELEASE-NOTES-v1-9-59.md +0 -28
  24. package/.worktrees/toolbox--guard-plan/SKILL.md +0 -821
  25. package/.worktrees/toolbox--guard-plan/TECHNICAL.md +0 -416
  26. package/.worktrees/toolbox--guard-plan/UNIVERSAL-INTERFACE.md +0 -180
  27. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-8-0.md +0 -29
  28. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-8-1.md +0 -7
  29. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-8-2.md +0 -7
  30. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-0.md +0 -37
  31. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-1.md +0 -38
  32. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-10.md +0 -40
  33. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-2.md +0 -40
  34. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-31.md +0 -26
  35. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-32.md +0 -18
  36. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-41.md +0 -28
  37. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-45.md +0 -25
  38. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-46.md +0 -38
  39. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-47.md +0 -42
  40. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-48.md +0 -22
  41. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-49.md +0 -31
  42. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-50.md +0 -24
  43. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-51.md +0 -11
  44. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-52.md +0 -25
  45. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-53.md +0 -22
  46. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-54.md +0 -13
  47. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-55.md +0 -11
  48. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-56.md +0 -42
  49. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-57.md +0 -18
  50. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-58.md +0 -21
  51. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-6.md +0 -72
  52. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-7.md +0 -23
  53. package/.worktrees/toolbox--guard-plan/_trash/RELEASE-NOTES-v1-9-9.md +0 -75
  54. package/.worktrees/toolbox--guard-plan/_trash/guide 2/DEV-GUIDE.md +0 -487
  55. package/.worktrees/toolbox--guard-plan/_trash/guide 2/scripts/deploy-public.sh +0 -152
  56. package/.worktrees/toolbox--guard-plan/package.json +0 -27
  57. package/.worktrees/toolbox--guard-plan/scripts/SKILL-deploy-public.md +0 -61
  58. package/.worktrees/toolbox--guard-plan/scripts/SKILL-post-merge-rename.md +0 -47
  59. package/.worktrees/toolbox--guard-plan/scripts/deploy-public.sh +0 -350
  60. package/.worktrees/toolbox--guard-plan/scripts/post-merge-rename.sh +0 -210
  61. package/.worktrees/toolbox--guard-plan/scripts/publish-skill.sh +0 -134
  62. package/.worktrees/toolbox--guard-plan/templates/global-claude-md.md +0 -73
  63. package/.worktrees/toolbox--guard-plan/templates/repo-claude-md.template +0 -24
  64. package/.worktrees/toolbox--guard-plan/tools/deploy-public/LICENSE +0 -52
  65. package/.worktrees/toolbox--guard-plan/tools/deploy-public/README.md +0 -31
  66. package/.worktrees/toolbox--guard-plan/tools/deploy-public/SKILL.md +0 -71
  67. package/.worktrees/toolbox--guard-plan/tools/deploy-public/deploy-public.sh +0 -264
  68. package/.worktrees/toolbox--guard-plan/tools/deploy-public/package.json +0 -9
  69. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/LICENSE +0 -52
  70. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/README.md +0 -46
  71. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/backup.sh +0 -16
  72. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/branch-protect.sh +0 -39
  73. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/crystal-capture.sh +0 -19
  74. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/setup-shell.sh +0 -27
  75. package/.worktrees/toolbox--guard-plan/tools/ldm-jobs/visibility-audit.sh +0 -27
  76. package/.worktrees/toolbox--guard-plan/tools/post-merge-rename/LICENSE +0 -52
  77. package/.worktrees/toolbox--guard-plan/tools/post-merge-rename/README.md +0 -29
  78. package/.worktrees/toolbox--guard-plan/tools/post-merge-rename/SKILL.md +0 -57
  79. package/.worktrees/toolbox--guard-plan/tools/post-merge-rename/package.json +0 -9
  80. package/.worktrees/toolbox--guard-plan/tools/post-merge-rename/post-merge-rename.sh +0 -122
  81. package/.worktrees/toolbox--guard-plan/tools/wip-branch-guard/INSTALL.md +0 -41
  82. package/.worktrees/toolbox--guard-plan/tools/wip-branch-guard/guard.mjs +0 -477
  83. package/.worktrees/toolbox--guard-plan/tools/wip-branch-guard/package.json +0 -18
  84. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/CHANGELOG.md +0 -6
  85. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/LICENSE +0 -52
  86. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/README.md +0 -113
  87. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/REFERENCE.md +0 -86
  88. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/SKILL.md +0 -105
  89. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/guard.mjs +0 -161
  90. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/openclaw.plugin.json +0 -8
  91. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/package.json +0 -27
  92. package/.worktrees/toolbox--guard-plan/tools/wip-file-guard/test.sh +0 -119
  93. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/LICENSE +0 -52
  94. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/README.md +0 -69
  95. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/SKILL.md +0 -65
  96. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/cli.mjs +0 -472
  97. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/core.mjs +0 -310
  98. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/guard.mjs +0 -146
  99. package/.worktrees/toolbox--guard-plan/tools/wip-license-guard/package.json +0 -22
  100. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/CHANGELOG.md +0 -17
  101. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/LICENSE +0 -52
  102. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/README.md +0 -200
  103. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/SKILL.md +0 -111
  104. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/cli/index.d.ts +0 -15
  105. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/cli/index.js +0 -170
  106. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/cli/index.js.map +0 -1
  107. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/detector.d.ts +0 -12
  108. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/detector.js +0 -104
  109. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/detector.js.map +0 -1
  110. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/index.d.ts +0 -4
  111. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/index.js +0 -5
  112. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/index.js.map +0 -1
  113. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/ledger.d.ts +0 -49
  114. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/ledger.js +0 -72
  115. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/ledger.js.map +0 -1
  116. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/reporter.d.ts +0 -14
  117. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/reporter.js +0 -227
  118. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/reporter.js.map +0 -1
  119. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/scanner.d.ts +0 -39
  120. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/scanner.js +0 -325
  121. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/dist/core/scanner.js.map +0 -1
  122. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/hooks/pre-pull.sh +0 -55
  123. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/hooks/pre-push.sh +0 -51
  124. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/mcp-server.mjs +0 -119
  125. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/package-lock.json +0 -54
  126. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/package.json +0 -43
  127. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/cli/index.ts +0 -189
  128. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/core/detector.ts +0 -130
  129. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/core/index.ts +0 -4
  130. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/core/ledger.ts +0 -116
  131. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/core/reporter.ts +0 -255
  132. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/src/core/scanner.ts +0 -367
  133. package/.worktrees/toolbox--guard-plan/tools/wip-license-hook/tsconfig.json +0 -16
  134. package/.worktrees/toolbox--guard-plan/tools/wip-readme-format/README.md +0 -49
  135. package/.worktrees/toolbox--guard-plan/tools/wip-readme-format/SKILL.md +0 -84
  136. package/.worktrees/toolbox--guard-plan/tools/wip-readme-format/format.mjs +0 -597
  137. package/.worktrees/toolbox--guard-plan/tools/wip-readme-format/package.json +0 -15
  138. package/.worktrees/toolbox--guard-plan/tools/wip-release/CHANGELOG.md +0 -42
  139. package/.worktrees/toolbox--guard-plan/tools/wip-release/LICENSE +0 -52
  140. package/.worktrees/toolbox--guard-plan/tools/wip-release/README.md +0 -45
  141. package/.worktrees/toolbox--guard-plan/tools/wip-release/REFERENCE.md +0 -100
  142. package/.worktrees/toolbox--guard-plan/tools/wip-release/SKILL.md +0 -139
  143. package/.worktrees/toolbox--guard-plan/tools/wip-release/cli.js +0 -175
  144. package/.worktrees/toolbox--guard-plan/tools/wip-release/core.mjs +0 -1664
  145. package/.worktrees/toolbox--guard-plan/tools/wip-release/mcp-server.mjs +0 -113
  146. package/.worktrees/toolbox--guard-plan/tools/wip-release/package.json +0 -36
  147. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/README.md +0 -38
  148. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/SKILL.md +0 -77
  149. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/init.mjs +0 -148
  150. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/package.json +0 -11
  151. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/_sort/README.md +0 -15
  152. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/_trash/README.md +0 -16
  153. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/dev-updates/README.md +0 -50
  154. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/product/notes/README.md +0 -26
  155. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/product/plans-prds/roadmap.md +0 -77
  156. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/product/plans-prds/todos/README.md +0 -63
  157. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/product/product-ideas/README.md +0 -24
  158. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/product/readme-first-product.md +0 -128
  159. package/.worktrees/toolbox--guard-plan/tools/wip-repo-init/templates/read-me-first.md +0 -80
  160. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/LICENSE +0 -52
  161. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/README.md +0 -86
  162. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/SKILL.md +0 -73
  163. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/cli.js +0 -93
  164. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/core.mjs +0 -122
  165. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/guard.mjs +0 -64
  166. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/mcp-server.mjs +0 -92
  167. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/openclaw.plugin.json +0 -8
  168. package/.worktrees/toolbox--guard-plan/tools/wip-repo-permissions-hook/package.json +0 -31
  169. package/.worktrees/toolbox--guard-plan/tools/wip-repos/LICENSE +0 -52
  170. package/.worktrees/toolbox--guard-plan/tools/wip-repos/README.md +0 -77
  171. package/.worktrees/toolbox--guard-plan/tools/wip-repos/SKILL.md +0 -80
  172. package/.worktrees/toolbox--guard-plan/tools/wip-repos/claude.mjs +0 -248
  173. package/.worktrees/toolbox--guard-plan/tools/wip-repos/cli.mjs +0 -191
  174. package/.worktrees/toolbox--guard-plan/tools/wip-repos/core.mjs +0 -290
  175. package/.worktrees/toolbox--guard-plan/tools/wip-repos/mcp-server.mjs +0 -157
  176. package/.worktrees/toolbox--guard-plan/tools/wip-repos/package.json +0 -34
  177. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/CHANGELOG.md +0 -57
  178. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/LICENSE +0 -52
  179. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/README.md +0 -81
  180. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/REFERENCE.md +0 -122
  181. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/SKILL.md +0 -87
  182. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/SPEC.md +0 -206
  183. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/detect.mjs +0 -130
  184. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/README.md +0 -20
  185. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/SKILL.md +0 -28
  186. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/cli.mjs +0 -4
  187. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/core.mjs +0 -8
  188. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/mcp-server.mjs +0 -27
  189. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/examples/minimal/package.json +0 -12
  190. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/install.js +0 -930
  191. package/.worktrees/toolbox--guard-plan/tools/wip-universal-installer/package.json +0 -32
  192. package/.worktrees/toolbox--release-notes/.license-guard.json +0 -7
  193. package/.worktrees/toolbox--release-notes/.publish-skill.json +0 -4
  194. package/.worktrees/toolbox--release-notes/CHANGELOG.md +0 -1875
  195. package/.worktrees/toolbox--release-notes/CLA.md +0 -19
  196. package/.worktrees/toolbox--release-notes/DEV-GUIDE-GENERAL-PUBLIC.md +0 -949
  197. package/.worktrees/toolbox--release-notes/LICENSE +0 -52
  198. package/.worktrees/toolbox--release-notes/README.md +0 -238
  199. package/.worktrees/toolbox--release-notes/RELEASE-NOTES-v1-9-56.md +0 -42
  200. package/.worktrees/toolbox--release-notes/SKILL.md +0 -821
  201. package/.worktrees/toolbox--release-notes/TECHNICAL.md +0 -416
  202. package/.worktrees/toolbox--release-notes/UNIVERSAL-INTERFACE.md +0 -180
  203. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-8-0.md +0 -29
  204. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-8-1.md +0 -7
  205. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-8-2.md +0 -7
  206. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-0.md +0 -37
  207. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-1.md +0 -38
  208. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-10.md +0 -40
  209. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-2.md +0 -40
  210. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-31.md +0 -26
  211. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-32.md +0 -18
  212. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-41.md +0 -28
  213. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-45.md +0 -25
  214. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-46.md +0 -38
  215. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-47.md +0 -42
  216. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-48.md +0 -22
  217. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-49.md +0 -31
  218. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-50.md +0 -24
  219. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-51.md +0 -11
  220. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-52.md +0 -25
  221. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-53.md +0 -22
  222. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-54.md +0 -13
  223. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-55.md +0 -11
  224. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-6.md +0 -72
  225. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-7.md +0 -23
  226. package/.worktrees/toolbox--release-notes/_trash/RELEASE-NOTES-v1-9-9.md +0 -75
  227. package/.worktrees/toolbox--release-notes/_trash/guide 2/DEV-GUIDE.md +0 -487
  228. package/.worktrees/toolbox--release-notes/_trash/guide 2/scripts/deploy-public.sh +0 -152
  229. package/.worktrees/toolbox--release-notes/package.json +0 -27
  230. package/.worktrees/toolbox--release-notes/scripts/SKILL-deploy-public.md +0 -61
  231. package/.worktrees/toolbox--release-notes/scripts/SKILL-post-merge-rename.md +0 -47
  232. package/.worktrees/toolbox--release-notes/scripts/deploy-public.sh +0 -345
  233. package/.worktrees/toolbox--release-notes/scripts/post-merge-rename.sh +0 -210
  234. package/.worktrees/toolbox--release-notes/scripts/publish-skill.sh +0 -134
  235. package/.worktrees/toolbox--release-notes/templates/global-claude-md.md +0 -73
  236. package/.worktrees/toolbox--release-notes/templates/repo-claude-md.template +0 -24
  237. package/.worktrees/toolbox--release-notes/tools/deploy-public/LICENSE +0 -52
  238. package/.worktrees/toolbox--release-notes/tools/deploy-public/README.md +0 -31
  239. package/.worktrees/toolbox--release-notes/tools/deploy-public/SKILL.md +0 -71
  240. package/.worktrees/toolbox--release-notes/tools/deploy-public/deploy-public.sh +0 -264
  241. package/.worktrees/toolbox--release-notes/tools/deploy-public/package.json +0 -9
  242. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/LICENSE +0 -52
  243. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/README.md +0 -46
  244. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/backup.sh +0 -16
  245. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/branch-protect.sh +0 -39
  246. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/crystal-capture.sh +0 -19
  247. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/setup-shell.sh +0 -27
  248. package/.worktrees/toolbox--release-notes/tools/ldm-jobs/visibility-audit.sh +0 -27
  249. package/.worktrees/toolbox--release-notes/tools/post-merge-rename/LICENSE +0 -52
  250. package/.worktrees/toolbox--release-notes/tools/post-merge-rename/README.md +0 -29
  251. package/.worktrees/toolbox--release-notes/tools/post-merge-rename/SKILL.md +0 -57
  252. package/.worktrees/toolbox--release-notes/tools/post-merge-rename/package.json +0 -9
  253. package/.worktrees/toolbox--release-notes/tools/post-merge-rename/post-merge-rename.sh +0 -122
  254. package/.worktrees/toolbox--release-notes/tools/wip-branch-guard/INSTALL.md +0 -41
  255. package/.worktrees/toolbox--release-notes/tools/wip-branch-guard/guard.mjs +0 -459
  256. package/.worktrees/toolbox--release-notes/tools/wip-branch-guard/package.json +0 -18
  257. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/CHANGELOG.md +0 -6
  258. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/LICENSE +0 -52
  259. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/README.md +0 -113
  260. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/REFERENCE.md +0 -86
  261. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/SKILL.md +0 -105
  262. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/guard.mjs +0 -161
  263. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/openclaw.plugin.json +0 -8
  264. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/package.json +0 -27
  265. package/.worktrees/toolbox--release-notes/tools/wip-file-guard/test.sh +0 -119
  266. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/LICENSE +0 -52
  267. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/README.md +0 -69
  268. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/SKILL.md +0 -65
  269. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/cli.mjs +0 -472
  270. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/core.mjs +0 -310
  271. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/guard.mjs +0 -146
  272. package/.worktrees/toolbox--release-notes/tools/wip-license-guard/package.json +0 -22
  273. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/CHANGELOG.md +0 -17
  274. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/LICENSE +0 -52
  275. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/README.md +0 -200
  276. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/SKILL.md +0 -111
  277. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/cli/index.d.ts +0 -15
  278. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/cli/index.js +0 -170
  279. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/cli/index.js.map +0 -1
  280. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/detector.d.ts +0 -12
  281. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/detector.js +0 -104
  282. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/detector.js.map +0 -1
  283. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/index.d.ts +0 -4
  284. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/index.js +0 -5
  285. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/index.js.map +0 -1
  286. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/ledger.d.ts +0 -49
  287. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/ledger.js +0 -72
  288. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/ledger.js.map +0 -1
  289. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/reporter.d.ts +0 -14
  290. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/reporter.js +0 -227
  291. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/reporter.js.map +0 -1
  292. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/scanner.d.ts +0 -39
  293. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/scanner.js +0 -325
  294. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/dist/core/scanner.js.map +0 -1
  295. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/hooks/pre-pull.sh +0 -55
  296. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/hooks/pre-push.sh +0 -51
  297. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/mcp-server.mjs +0 -119
  298. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/package-lock.json +0 -54
  299. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/package.json +0 -43
  300. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/cli/index.ts +0 -189
  301. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/core/detector.ts +0 -130
  302. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/core/index.ts +0 -4
  303. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/core/ledger.ts +0 -116
  304. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/core/reporter.ts +0 -255
  305. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/src/core/scanner.ts +0 -367
  306. package/.worktrees/toolbox--release-notes/tools/wip-license-hook/tsconfig.json +0 -16
  307. package/.worktrees/toolbox--release-notes/tools/wip-readme-format/README.md +0 -49
  308. package/.worktrees/toolbox--release-notes/tools/wip-readme-format/SKILL.md +0 -84
  309. package/.worktrees/toolbox--release-notes/tools/wip-readme-format/format.mjs +0 -597
  310. package/.worktrees/toolbox--release-notes/tools/wip-readme-format/package.json +0 -15
  311. package/.worktrees/toolbox--release-notes/tools/wip-release/CHANGELOG.md +0 -42
  312. package/.worktrees/toolbox--release-notes/tools/wip-release/LICENSE +0 -52
  313. package/.worktrees/toolbox--release-notes/tools/wip-release/README.md +0 -45
  314. package/.worktrees/toolbox--release-notes/tools/wip-release/REFERENCE.md +0 -100
  315. package/.worktrees/toolbox--release-notes/tools/wip-release/SKILL.md +0 -139
  316. package/.worktrees/toolbox--release-notes/tools/wip-release/cli.js +0 -175
  317. package/.worktrees/toolbox--release-notes/tools/wip-release/core.mjs +0 -1664
  318. package/.worktrees/toolbox--release-notes/tools/wip-release/mcp-server.mjs +0 -113
  319. package/.worktrees/toolbox--release-notes/tools/wip-release/package.json +0 -36
  320. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/README.md +0 -38
  321. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/SKILL.md +0 -77
  322. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/init.mjs +0 -148
  323. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/package.json +0 -11
  324. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/_sort/README.md +0 -15
  325. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/_trash/README.md +0 -16
  326. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/dev-updates/README.md +0 -50
  327. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/product/notes/README.md +0 -26
  328. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/product/plans-prds/roadmap.md +0 -77
  329. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/product/plans-prds/todos/README.md +0 -63
  330. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/product/product-ideas/README.md +0 -24
  331. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/product/readme-first-product.md +0 -128
  332. package/.worktrees/toolbox--release-notes/tools/wip-repo-init/templates/read-me-first.md +0 -80
  333. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/LICENSE +0 -52
  334. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/README.md +0 -86
  335. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/SKILL.md +0 -73
  336. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/cli.js +0 -93
  337. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/core.mjs +0 -122
  338. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/guard.mjs +0 -64
  339. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/mcp-server.mjs +0 -92
  340. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/openclaw.plugin.json +0 -8
  341. package/.worktrees/toolbox--release-notes/tools/wip-repo-permissions-hook/package.json +0 -31
  342. package/.worktrees/toolbox--release-notes/tools/wip-repos/LICENSE +0 -52
  343. package/.worktrees/toolbox--release-notes/tools/wip-repos/README.md +0 -77
  344. package/.worktrees/toolbox--release-notes/tools/wip-repos/SKILL.md +0 -80
  345. package/.worktrees/toolbox--release-notes/tools/wip-repos/claude.mjs +0 -248
  346. package/.worktrees/toolbox--release-notes/tools/wip-repos/cli.mjs +0 -191
  347. package/.worktrees/toolbox--release-notes/tools/wip-repos/core.mjs +0 -290
  348. package/.worktrees/toolbox--release-notes/tools/wip-repos/mcp-server.mjs +0 -157
  349. package/.worktrees/toolbox--release-notes/tools/wip-repos/package.json +0 -34
  350. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/CHANGELOG.md +0 -57
  351. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/LICENSE +0 -52
  352. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/README.md +0 -81
  353. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/REFERENCE.md +0 -122
  354. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/SKILL.md +0 -87
  355. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/SPEC.md +0 -206
  356. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/detect.mjs +0 -130
  357. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/README.md +0 -20
  358. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/SKILL.md +0 -28
  359. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/cli.mjs +0 -4
  360. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/core.mjs +0 -8
  361. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/mcp-server.mjs +0 -27
  362. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/examples/minimal/package.json +0 -12
  363. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/install.js +0 -930
  364. package/.worktrees/toolbox--release-notes/tools/wip-universal-installer/package.json +0 -32
  365. package/.worktrees/toolbox--save-stale/.license-guard.json +0 -7
  366. package/.worktrees/toolbox--save-stale/.publish-skill.json +0 -4
  367. package/.worktrees/toolbox--save-stale/CHANGELOG.md +0 -1875
  368. package/.worktrees/toolbox--save-stale/CLA.md +0 -19
  369. package/.worktrees/toolbox--save-stale/DEV-GUIDE-GENERAL-PUBLIC.md +0 -949
  370. package/.worktrees/toolbox--save-stale/LICENSE +0 -52
  371. package/.worktrees/toolbox--save-stale/README.md +0 -238
  372. package/.worktrees/toolbox--save-stale/SKILL.md +0 -821
  373. package/.worktrees/toolbox--save-stale/TECHNICAL.md +0 -416
  374. package/.worktrees/toolbox--save-stale/UNIVERSAL-INTERFACE.md +0 -180
  375. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-8-0.md +0 -29
  376. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-8-1.md +0 -7
  377. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-8-2.md +0 -7
  378. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-0.md +0 -37
  379. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-1.md +0 -38
  380. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-10.md +0 -40
  381. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-2.md +0 -40
  382. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-31.md +0 -26
  383. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-32.md +0 -18
  384. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-41.md +0 -28
  385. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-45.md +0 -25
  386. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-46.md +0 -38
  387. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-47.md +0 -42
  388. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-48.md +0 -22
  389. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-49.md +0 -31
  390. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-50.md +0 -24
  391. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-51.md +0 -11
  392. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-52.md +0 -25
  393. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-53.md +0 -22
  394. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-54.md +0 -13
  395. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-55.md +0 -11
  396. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-6.md +0 -72
  397. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-7.md +0 -23
  398. package/.worktrees/toolbox--save-stale/_trash/RELEASE-NOTES-v1-9-9.md +0 -75
  399. package/.worktrees/toolbox--save-stale/_trash/guide 2/DEV-GUIDE.md +0 -487
  400. package/.worktrees/toolbox--save-stale/_trash/guide 2/scripts/deploy-public.sh +0 -152
  401. package/.worktrees/toolbox--save-stale/package.json +0 -27
  402. package/.worktrees/toolbox--save-stale/scripts/SKILL-deploy-public.md +0 -61
  403. package/.worktrees/toolbox--save-stale/scripts/SKILL-post-merge-rename.md +0 -47
  404. package/.worktrees/toolbox--save-stale/scripts/deploy-public.sh +0 -345
  405. package/.worktrees/toolbox--save-stale/scripts/post-merge-rename.sh +0 -210
  406. package/.worktrees/toolbox--save-stale/scripts/publish-skill.sh +0 -134
  407. package/.worktrees/toolbox--save-stale/templates/global-claude-md.md +0 -73
  408. package/.worktrees/toolbox--save-stale/templates/repo-claude-md.template +0 -24
  409. package/.worktrees/toolbox--save-stale/tools/deploy-public/LICENSE +0 -52
  410. package/.worktrees/toolbox--save-stale/tools/deploy-public/README.md +0 -31
  411. package/.worktrees/toolbox--save-stale/tools/deploy-public/SKILL.md +0 -71
  412. package/.worktrees/toolbox--save-stale/tools/deploy-public/deploy-public.sh +0 -264
  413. package/.worktrees/toolbox--save-stale/tools/deploy-public/package.json +0 -9
  414. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/LICENSE +0 -52
  415. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/README.md +0 -46
  416. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/backup.sh +0 -16
  417. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/branch-protect.sh +0 -39
  418. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/crystal-capture.sh +0 -19
  419. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/setup-shell.sh +0 -27
  420. package/.worktrees/toolbox--save-stale/tools/ldm-jobs/visibility-audit.sh +0 -27
  421. package/.worktrees/toolbox--save-stale/tools/post-merge-rename/LICENSE +0 -52
  422. package/.worktrees/toolbox--save-stale/tools/post-merge-rename/README.md +0 -29
  423. package/.worktrees/toolbox--save-stale/tools/post-merge-rename/SKILL.md +0 -57
  424. package/.worktrees/toolbox--save-stale/tools/post-merge-rename/package.json +0 -9
  425. package/.worktrees/toolbox--save-stale/tools/post-merge-rename/post-merge-rename.sh +0 -122
  426. package/.worktrees/toolbox--save-stale/tools/wip-branch-guard/INSTALL.md +0 -41
  427. package/.worktrees/toolbox--save-stale/tools/wip-branch-guard/guard.mjs +0 -459
  428. package/.worktrees/toolbox--save-stale/tools/wip-branch-guard/package.json +0 -18
  429. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/CHANGELOG.md +0 -6
  430. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/LICENSE +0 -52
  431. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/README.md +0 -113
  432. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/REFERENCE.md +0 -86
  433. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/SKILL.md +0 -105
  434. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/guard.mjs +0 -161
  435. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/openclaw.plugin.json +0 -8
  436. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/package.json +0 -27
  437. package/.worktrees/toolbox--save-stale/tools/wip-file-guard/test.sh +0 -119
  438. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/LICENSE +0 -52
  439. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/README.md +0 -69
  440. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/SKILL.md +0 -65
  441. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/cli.mjs +0 -472
  442. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/core.mjs +0 -310
  443. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/guard.mjs +0 -146
  444. package/.worktrees/toolbox--save-stale/tools/wip-license-guard/package.json +0 -22
  445. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/CHANGELOG.md +0 -17
  446. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/LICENSE +0 -52
  447. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/README.md +0 -200
  448. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/SKILL.md +0 -111
  449. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/cli/index.d.ts +0 -15
  450. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/cli/index.js +0 -170
  451. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/cli/index.js.map +0 -1
  452. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/detector.d.ts +0 -12
  453. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/detector.js +0 -104
  454. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/detector.js.map +0 -1
  455. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/index.d.ts +0 -4
  456. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/index.js +0 -5
  457. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/index.js.map +0 -1
  458. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/ledger.d.ts +0 -49
  459. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/ledger.js +0 -72
  460. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/ledger.js.map +0 -1
  461. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/reporter.d.ts +0 -14
  462. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/reporter.js +0 -227
  463. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/reporter.js.map +0 -1
  464. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/scanner.d.ts +0 -39
  465. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/scanner.js +0 -325
  466. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/dist/core/scanner.js.map +0 -1
  467. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/hooks/pre-pull.sh +0 -55
  468. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/hooks/pre-push.sh +0 -51
  469. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/mcp-server.mjs +0 -119
  470. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/package-lock.json +0 -54
  471. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/package.json +0 -43
  472. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/cli/index.ts +0 -189
  473. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/core/detector.ts +0 -130
  474. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/core/index.ts +0 -4
  475. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/core/ledger.ts +0 -116
  476. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/core/reporter.ts +0 -255
  477. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/src/core/scanner.ts +0 -367
  478. package/.worktrees/toolbox--save-stale/tools/wip-license-hook/tsconfig.json +0 -16
  479. package/.worktrees/toolbox--save-stale/tools/wip-readme-format/README.md +0 -49
  480. package/.worktrees/toolbox--save-stale/tools/wip-readme-format/SKILL.md +0 -84
  481. package/.worktrees/toolbox--save-stale/tools/wip-readme-format/format.mjs +0 -597
  482. package/.worktrees/toolbox--save-stale/tools/wip-readme-format/package.json +0 -15
  483. package/.worktrees/toolbox--save-stale/tools/wip-release/CHANGELOG.md +0 -42
  484. package/.worktrees/toolbox--save-stale/tools/wip-release/LICENSE +0 -52
  485. package/.worktrees/toolbox--save-stale/tools/wip-release/README.md +0 -45
  486. package/.worktrees/toolbox--save-stale/tools/wip-release/REFERENCE.md +0 -100
  487. package/.worktrees/toolbox--save-stale/tools/wip-release/SKILL.md +0 -139
  488. package/.worktrees/toolbox--save-stale/tools/wip-release/cli.js +0 -175
  489. package/.worktrees/toolbox--save-stale/tools/wip-release/core.mjs +0 -1664
  490. package/.worktrees/toolbox--save-stale/tools/wip-release/mcp-server.mjs +0 -113
  491. package/.worktrees/toolbox--save-stale/tools/wip-release/package.json +0 -36
  492. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/README.md +0 -38
  493. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/SKILL.md +0 -77
  494. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/init.mjs +0 -148
  495. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/package.json +0 -11
  496. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/_sort/README.md +0 -15
  497. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/_trash/README.md +0 -16
  498. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/dev-updates/README.md +0 -50
  499. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/product/notes/README.md +0 -26
  500. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/product/plans-prds/roadmap.md +0 -77
  501. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/product/plans-prds/todos/README.md +0 -63
  502. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/product/product-ideas/README.md +0 -24
  503. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/product/readme-first-product.md +0 -128
  504. package/.worktrees/toolbox--save-stale/tools/wip-repo-init/templates/read-me-first.md +0 -80
  505. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/LICENSE +0 -52
  506. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/README.md +0 -86
  507. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/SKILL.md +0 -73
  508. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/cli.js +0 -93
  509. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/core.mjs +0 -122
  510. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/guard.mjs +0 -64
  511. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/mcp-server.mjs +0 -92
  512. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/openclaw.plugin.json +0 -8
  513. package/.worktrees/toolbox--save-stale/tools/wip-repo-permissions-hook/package.json +0 -31
  514. package/.worktrees/toolbox--save-stale/tools/wip-repos/LICENSE +0 -52
  515. package/.worktrees/toolbox--save-stale/tools/wip-repos/README.md +0 -77
  516. package/.worktrees/toolbox--save-stale/tools/wip-repos/SKILL.md +0 -80
  517. package/.worktrees/toolbox--save-stale/tools/wip-repos/claude.mjs +0 -248
  518. package/.worktrees/toolbox--save-stale/tools/wip-repos/cli.mjs +0 -191
  519. package/.worktrees/toolbox--save-stale/tools/wip-repos/core.mjs +0 -290
  520. package/.worktrees/toolbox--save-stale/tools/wip-repos/mcp-server.mjs +0 -157
  521. package/.worktrees/toolbox--save-stale/tools/wip-repos/package.json +0 -34
  522. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/CHANGELOG.md +0 -57
  523. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/LICENSE +0 -52
  524. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/README.md +0 -81
  525. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/REFERENCE.md +0 -122
  526. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/SKILL.md +0 -87
  527. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/SPEC.md +0 -206
  528. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/detect.mjs +0 -130
  529. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/README.md +0 -20
  530. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/SKILL.md +0 -28
  531. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/cli.mjs +0 -4
  532. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/core.mjs +0 -8
  533. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/mcp-server.mjs +0 -27
  534. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/examples/minimal/package.json +0 -12
  535. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/install.js +0 -930
  536. package/.worktrees/toolbox--save-stale/tools/wip-universal-installer/package.json +0 -32
  537. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/.license-guard.json +0 -7
  538. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/.publish-skill.json +0 -4
  539. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/CHANGELOG.md +0 -1875
  540. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/CLA.md +0 -19
  541. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/DEV-GUIDE-GENERAL-PUBLIC.md +0 -949
  542. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/LICENSE +0 -52
  543. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/README.md +0 -238
  544. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/SKILL.md +0 -821
  545. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/TECHNICAL.md +0 -416
  546. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/UNIVERSAL-INTERFACE.md +0 -180
  547. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-8-0.md +0 -29
  548. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-8-1.md +0 -7
  549. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-8-2.md +0 -7
  550. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-0.md +0 -37
  551. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-1.md +0 -38
  552. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-10.md +0 -40
  553. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-2.md +0 -40
  554. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-31.md +0 -26
  555. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-32.md +0 -18
  556. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-41.md +0 -28
  557. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-45.md +0 -25
  558. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-46.md +0 -38
  559. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-47.md +0 -42
  560. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-48.md +0 -22
  561. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-49.md +0 -31
  562. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-50.md +0 -24
  563. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-51.md +0 -11
  564. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-52.md +0 -25
  565. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-53.md +0 -22
  566. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-54.md +0 -13
  567. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-55.md +0 -11
  568. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-6.md +0 -72
  569. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-7.md +0 -23
  570. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/RELEASE-NOTES-v1-9-9.md +0 -75
  571. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/guide 2/DEV-GUIDE.md +0 -487
  572. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/_trash/guide 2/scripts/deploy-public.sh +0 -152
  573. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/package.json +0 -27
  574. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/scripts/SKILL-deploy-public.md +0 -61
  575. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/scripts/SKILL-post-merge-rename.md +0 -47
  576. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/scripts/deploy-public.sh +0 -345
  577. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/scripts/post-merge-rename.sh +0 -210
  578. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/scripts/publish-skill.sh +0 -134
  579. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/templates/global-claude-md.md +0 -73
  580. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/templates/repo-claude-md.template +0 -24
  581. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/deploy-public/LICENSE +0 -52
  582. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/deploy-public/README.md +0 -31
  583. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/deploy-public/SKILL.md +0 -71
  584. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/deploy-public/deploy-public.sh +0 -264
  585. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/deploy-public/package.json +0 -9
  586. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/LICENSE +0 -52
  587. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/README.md +0 -46
  588. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/backup.sh +0 -16
  589. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/branch-protect.sh +0 -39
  590. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/crystal-capture.sh +0 -19
  591. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/setup-shell.sh +0 -27
  592. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/ldm-jobs/visibility-audit.sh +0 -27
  593. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/post-merge-rename/LICENSE +0 -52
  594. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/post-merge-rename/README.md +0 -29
  595. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/post-merge-rename/SKILL.md +0 -57
  596. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/post-merge-rename/package.json +0 -9
  597. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/post-merge-rename/post-merge-rename.sh +0 -122
  598. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-branch-guard/INSTALL.md +0 -41
  599. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-branch-guard/guard.mjs +0 -418
  600. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-branch-guard/package.json +0 -18
  601. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/CHANGELOG.md +0 -6
  602. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/LICENSE +0 -52
  603. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/README.md +0 -113
  604. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/REFERENCE.md +0 -86
  605. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/SKILL.md +0 -105
  606. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/guard.mjs +0 -161
  607. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/openclaw.plugin.json +0 -8
  608. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/package.json +0 -27
  609. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-file-guard/test.sh +0 -119
  610. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/LICENSE +0 -52
  611. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/README.md +0 -69
  612. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/SKILL.md +0 -65
  613. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/cli.mjs +0 -472
  614. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/core.mjs +0 -310
  615. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/guard.mjs +0 -146
  616. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-guard/package.json +0 -22
  617. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/CHANGELOG.md +0 -17
  618. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/LICENSE +0 -52
  619. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/README.md +0 -200
  620. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/SKILL.md +0 -111
  621. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/cli/index.d.ts +0 -15
  622. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/cli/index.js +0 -170
  623. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/cli/index.js.map +0 -1
  624. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/detector.d.ts +0 -12
  625. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/detector.js +0 -104
  626. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/detector.js.map +0 -1
  627. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/index.d.ts +0 -4
  628. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/index.js +0 -5
  629. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/index.js.map +0 -1
  630. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/ledger.d.ts +0 -49
  631. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/ledger.js +0 -72
  632. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/ledger.js.map +0 -1
  633. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/reporter.d.ts +0 -14
  634. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/reporter.js +0 -227
  635. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/reporter.js.map +0 -1
  636. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/scanner.d.ts +0 -39
  637. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/scanner.js +0 -325
  638. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/dist/core/scanner.js.map +0 -1
  639. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/hooks/pre-pull.sh +0 -55
  640. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/hooks/pre-push.sh +0 -51
  641. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/mcp-server.mjs +0 -119
  642. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/package-lock.json +0 -54
  643. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/package.json +0 -43
  644. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/cli/index.ts +0 -189
  645. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/core/detector.ts +0 -130
  646. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/core/index.ts +0 -4
  647. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/core/ledger.ts +0 -116
  648. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/core/reporter.ts +0 -255
  649. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/src/core/scanner.ts +0 -367
  650. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-license-hook/tsconfig.json +0 -16
  651. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-readme-format/README.md +0 -49
  652. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-readme-format/SKILL.md +0 -84
  653. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-readme-format/format.mjs +0 -597
  654. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-readme-format/package.json +0 -15
  655. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/CHANGELOG.md +0 -42
  656. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/LICENSE +0 -52
  657. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/README.md +0 -45
  658. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/REFERENCE.md +0 -100
  659. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/SKILL.md +0 -139
  660. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/cli.js +0 -175
  661. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/core.mjs +0 -1664
  662. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/mcp-server.mjs +0 -113
  663. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-release/package.json +0 -36
  664. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/README.md +0 -38
  665. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/SKILL.md +0 -77
  666. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/init.mjs +0 -148
  667. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/package.json +0 -11
  668. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/_sort/README.md +0 -15
  669. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/_trash/README.md +0 -16
  670. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/dev-updates/README.md +0 -50
  671. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/product/notes/README.md +0 -26
  672. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/product/plans-prds/roadmap.md +0 -77
  673. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/product/plans-prds/todos/README.md +0 -63
  674. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/product/product-ideas/README.md +0 -24
  675. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/product/readme-first-product.md +0 -128
  676. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-init/templates/read-me-first.md +0 -80
  677. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/LICENSE +0 -52
  678. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/README.md +0 -86
  679. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/SKILL.md +0 -73
  680. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/cli.js +0 -93
  681. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/core.mjs +0 -122
  682. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/guard.mjs +0 -64
  683. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/mcp-server.mjs +0 -92
  684. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/openclaw.plugin.json +0 -8
  685. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repo-permissions-hook/package.json +0 -31
  686. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/LICENSE +0 -52
  687. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/README.md +0 -77
  688. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/SKILL.md +0 -80
  689. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/claude.mjs +0 -248
  690. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/cli.mjs +0 -191
  691. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/core.mjs +0 -290
  692. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/mcp-server.mjs +0 -157
  693. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-repos/package.json +0 -34
  694. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/CHANGELOG.md +0 -57
  695. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/LICENSE +0 -52
  696. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/README.md +0 -81
  697. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/REFERENCE.md +0 -122
  698. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/SKILL.md +0 -87
  699. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/SPEC.md +0 -206
  700. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/detect.mjs +0 -130
  701. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/README.md +0 -20
  702. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/SKILL.md +0 -28
  703. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/cli.mjs +0 -4
  704. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/core.mjs +0 -8
  705. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/mcp-server.mjs +0 -27
  706. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/examples/minimal/package.json +0 -12
  707. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/install.js +0 -930
  708. package/.worktrees/wip-ai-devops-toolbox-private--cc-mini--dot-worktrees/tools/wip-universal-installer/package.json +0 -32
  709. package/_trash/RELEASE-NOTES-v1-8-0.md +0 -29
  710. package/_trash/RELEASE-NOTES-v1-8-1.md +0 -7
  711. package/_trash/RELEASE-NOTES-v1-8-2.md +0 -7
  712. package/_trash/RELEASE-NOTES-v1-9-0.md +0 -37
  713. package/_trash/RELEASE-NOTES-v1-9-1.md +0 -38
  714. package/_trash/RELEASE-NOTES-v1-9-10.md +0 -40
  715. package/_trash/RELEASE-NOTES-v1-9-2.md +0 -40
  716. package/_trash/RELEASE-NOTES-v1-9-31.md +0 -26
  717. package/_trash/RELEASE-NOTES-v1-9-32.md +0 -18
  718. package/_trash/RELEASE-NOTES-v1-9-41.md +0 -28
  719. package/_trash/RELEASE-NOTES-v1-9-45.md +0 -25
  720. package/_trash/RELEASE-NOTES-v1-9-46.md +0 -38
  721. package/_trash/RELEASE-NOTES-v1-9-47.md +0 -42
  722. package/_trash/RELEASE-NOTES-v1-9-48.md +0 -22
  723. package/_trash/RELEASE-NOTES-v1-9-49.md +0 -31
  724. package/_trash/RELEASE-NOTES-v1-9-50.md +0 -24
  725. package/_trash/RELEASE-NOTES-v1-9-51.md +0 -11
  726. package/_trash/RELEASE-NOTES-v1-9-52.md +0 -25
  727. package/_trash/RELEASE-NOTES-v1-9-53.md +0 -22
  728. package/_trash/RELEASE-NOTES-v1-9-54.md +0 -13
  729. package/_trash/RELEASE-NOTES-v1-9-55.md +0 -11
  730. package/_trash/RELEASE-NOTES-v1-9-56.md +0 -42
  731. package/_trash/RELEASE-NOTES-v1-9-57.md +0 -18
  732. package/_trash/RELEASE-NOTES-v1-9-58.md +0 -21
  733. package/_trash/RELEASE-NOTES-v1-9-59.md +0 -28
  734. package/_trash/RELEASE-NOTES-v1-9-6.md +0 -72
  735. package/_trash/RELEASE-NOTES-v1-9-7.md +0 -23
  736. package/_trash/RELEASE-NOTES-v1-9-9.md +0 -75
  737. package/_trash/guide 2/DEV-GUIDE.md +0 -487
  738. package/_trash/guide 2/scripts/deploy-public.sh +0 -152
  739. package/tools/wip-repo-init/templates/_trash/README.md +0 -16
@@ -1,1664 +0,0 @@
1
- /**
2
- * wip-release/core.mjs
3
- * Local release tool. Bumps version, updates changelog + SKILL.md,
4
- * commits, tags, publishes to npm + GitHub Packages, creates GitHub release.
5
- * Zero dependencies.
6
- */
7
-
8
- import { execSync, execFileSync } from 'node:child_process';
9
- import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync, renameSync } from 'node:fs';
10
- import { join, basename } from 'node:path';
11
-
12
- // ── Version ─────────────────────────────────────────────────────────
13
-
14
- /**
15
- * Read current version from package.json.
16
- */
17
- export function detectCurrentVersion(repoPath) {
18
- const pkgPath = join(repoPath, 'package.json');
19
- if (!existsSync(pkgPath)) throw new Error(`No package.json found at ${repoPath}`);
20
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
21
- return pkg.version;
22
- }
23
-
24
- /**
25
- * Bump a semver string by level.
26
- */
27
- export function bumpSemver(version, level) {
28
- const [major, minor, patch] = version.split('.').map(Number);
29
- switch (level) {
30
- case 'major': return `${major + 1}.0.0`;
31
- case 'minor': return `${major}.${minor + 1}.0`;
32
- case 'patch': return `${major}.${minor}.${patch + 1}`;
33
- default: throw new Error(`Invalid level: ${level}. Use major, minor, or patch.`);
34
- }
35
- }
36
-
37
- /**
38
- * Write new version to package.json.
39
- */
40
- function writePackageVersion(repoPath, newVersion) {
41
- const pkgPath = join(repoPath, 'package.json');
42
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
43
- pkg.version = newVersion;
44
- writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
45
- }
46
-
47
- // ── SKILL.md ────────────────────────────────────────────────────────
48
-
49
- /**
50
- * Update version in SKILL.md YAML frontmatter.
51
- */
52
- export function syncSkillVersion(repoPath, newVersion) {
53
- const skillPath = join(repoPath, 'SKILL.md');
54
- if (!existsSync(skillPath)) return false;
55
-
56
- let content = readFileSync(skillPath, 'utf8');
57
-
58
- // Check for staleness: if SKILL.md version is more than a patch behind,
59
- // warn that content may need updating (not just the version number)
60
- const skillVersionMatch = content.match(/^---[\s\S]*?version:\s*"?(\d+\.\d+\.\d+)"?[\s\S]*?---/);
61
- if (skillVersionMatch) {
62
- const skillVersion = skillVersionMatch[1];
63
- const [sMaj, sMin] = skillVersion.split('.').map(Number);
64
- const [nMaj, nMin] = newVersion.split('.').map(Number);
65
- if (nMaj > sMaj || nMin > sMin + 1) {
66
- console.warn(` ! SKILL.md is at ${skillVersion}, releasing ${newVersion}`);
67
- console.warn(` SKILL.md content may be stale. Review tool list and interfaces.`);
68
- }
69
- }
70
-
71
- // Match version line in YAML frontmatter (between --- markers).
72
- // Uses "[^\n]* for quoted values (including corrupted multi-quote strings
73
- // like "1.9.5".9.4".9.3") or \S+ for unquoted values. This replaces the
74
- // ENTIRE value on the line, preventing the accumulation bug (#71).
75
- const updated = content.replace(
76
- /^(---[\s\S]*?version:\s*)(?:"[^\n]*|\S+)([\s\S]*?---)/,
77
- `$1"${newVersion}"$2`
78
- );
79
-
80
- if (updated === content) return false;
81
- writeFileSync(skillPath, updated);
82
- return true;
83
- }
84
-
85
- // ── CHANGELOG.md ────────────────────────────────────────────────────
86
-
87
- /**
88
- * Prepend a new version entry to CHANGELOG.md.
89
- */
90
- export function updateChangelog(repoPath, newVersion, notes) {
91
- const changelogPath = join(repoPath, 'CHANGELOG.md');
92
- const d = new Date();
93
- const date = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
94
-
95
- // Bug fix #121: never silently default to "Release." when notes are empty.
96
- // If notes are empty at this point, warn loudly.
97
- if (!notes || !notes.trim()) {
98
- console.warn(` ! WARNING: No release notes provided for v${newVersion}. CHANGELOG entry will be minimal.`);
99
- notes = 'No release notes provided.';
100
- }
101
-
102
- const entry = `## ${newVersion} (${date})\n\n${notes}\n`;
103
-
104
- if (!existsSync(changelogPath)) {
105
- writeFileSync(changelogPath, `# Changelog\n\n${entry}`);
106
- return;
107
- }
108
-
109
- let content = readFileSync(changelogPath, 'utf8');
110
- // Insert after the # Changelog header (single newline, no accumulation)
111
- const headerMatch = content.match(/^# Changelog\s*\n+/);
112
- if (headerMatch) {
113
- const insertPoint = headerMatch[0].length;
114
- content = content.slice(0, insertPoint) + entry + '\n' + content.slice(insertPoint);
115
- } else {
116
- content = `# Changelog\n\n${entry}\n${content}`;
117
- }
118
-
119
- writeFileSync(changelogPath, content);
120
- }
121
-
122
- // ── Git ─────────────────────────────────────────────────────────────
123
-
124
- /**
125
- * Move all RELEASE-NOTES-v*.md files to _trash/.
126
- * Returns the number of files moved.
127
- */
128
- function trashReleaseNotes(repoPath) {
129
- const files = readdirSync(repoPath).filter(f => /^RELEASE-NOTES-v.*\.md$/i.test(f));
130
- if (files.length === 0) return 0;
131
-
132
- const trashDir = join(repoPath, '_trash');
133
- if (!existsSync(trashDir)) mkdirSync(trashDir);
134
-
135
- for (const f of files) {
136
- renameSync(join(repoPath, f), join(trashDir, f));
137
- execFileSync('git', ['add', join('_trash', f)], { cwd: repoPath, stdio: 'pipe' });
138
- // Only git rm if the file was tracked (committed or staged).
139
- // Untracked scaffolded files from failed releases just need the rename.
140
- try {
141
- execFileSync('git', ['ls-files', '--error-unmatch', f], { cwd: repoPath, stdio: 'pipe' });
142
- execFileSync('git', ['rm', '--cached', f], { cwd: repoPath, stdio: 'pipe' });
143
- } catch {
144
- // File wasn't tracked. Rename already moved it.
145
- }
146
- }
147
- return files.length;
148
- }
149
-
150
- function gitCommitAndTag(repoPath, newVersion, notes) {
151
- const msg = `v${newVersion}: ${notes || 'Release'}`;
152
- // Stage known files (ignore missing ones)
153
- for (const f of ['package.json', 'CHANGELOG.md', 'SKILL.md']) {
154
- if (existsSync(join(repoPath, f))) {
155
- execFileSync('git', ['add', f], { cwd: repoPath, stdio: 'pipe' });
156
- }
157
- }
158
- // Use execFileSync to avoid shell injection via notes.
159
- // --no-verify: wip-release legitimately commits on main (version bump + changelog).
160
- // The pre-commit hook blocks all commits on main, but wip-release is the one exception.
161
- execFileSync('git', ['commit', '--no-verify', '-m', msg], { cwd: repoPath, stdio: 'pipe' });
162
- execFileSync('git', ['tag', `v${newVersion}`], { cwd: repoPath, stdio: 'pipe' });
163
- }
164
-
165
- // ── Publish ─────────────────────────────────────────────────────────
166
-
167
- /**
168
- * Publish to npm via 1Password for auth.
169
- */
170
- export function publishNpm(repoPath) {
171
- const token = getNpmToken();
172
- execFileSync('npm', [
173
- 'publish', '--access', 'public',
174
- `--//registry.npmjs.org/:_authToken=${token}`
175
- ], { cwd: repoPath, stdio: 'inherit' });
176
- }
177
-
178
- /**
179
- * Publish to GitHub Packages.
180
- */
181
- export function publishGitHubPackages(repoPath) {
182
- const ghToken = execSync('gh auth token', { encoding: 'utf8' }).trim();
183
- execFileSync('npm', [
184
- 'publish',
185
- '--registry', 'https://npm.pkg.github.com',
186
- `--//npm.pkg.github.com/:_authToken=${ghToken}`
187
- ], { cwd: repoPath, stdio: 'inherit' });
188
- }
189
-
190
- /**
191
- * Categorize a commit message into a section.
192
- * Returns: 'changes', 'fixes', 'docs', 'internal'
193
- */
194
- function categorizeCommit(subject) {
195
- const lower = subject.toLowerCase();
196
-
197
- // Fixes
198
- if (lower.startsWith('fix') || lower.startsWith('hotfix') || lower.startsWith('bugfix') ||
199
- lower.includes('fix:') || lower.includes('bug:')) {
200
- return 'fixes';
201
- }
202
-
203
- // Docs
204
- if (lower.startsWith('doc') || lower.startsWith('readme') ||
205
- lower.includes('docs:') || lower.includes('doc:') ||
206
- lower.startsWith('update readme') || lower.startsWith('rewrite readme') ||
207
- lower.startsWith('update technical') || lower.startsWith('rewrite relay') ||
208
- lower.startsWith('update relay')) {
209
- return 'docs';
210
- }
211
-
212
- // Internal (skip in release notes)
213
- if (lower.startsWith('chore') || lower.startsWith('auto-commit') ||
214
- lower.startsWith('merge pull request') || lower.startsWith('merge branch') ||
215
- lower.match(/^v\d+\.\d+\.\d+/) || lower.startsWith('mark ') ||
216
- lower.startsWith('clean up todo') || lower.startsWith('keep ')) {
217
- return 'internal';
218
- }
219
-
220
- // Everything else is a change
221
- return 'changes';
222
- }
223
-
224
- /**
225
- * Check release notes quality. Returns { ok, issues[] }.
226
- *
227
- * notesSource: 'file' (RELEASE-NOTES-v*.md or --notes-file),
228
- * 'dev-update' (ai/dev-updates/ fallback),
229
- * 'flag' (bare --notes="string"),
230
- * 'none' (nothing provided).
231
- *
232
- * For minor/major: BLOCKS if notes came from bare --notes flag or are missing.
233
- * Agents must write a RELEASE-NOTES-v{version}.md file and commit it.
234
- * For patch: WARNS only.
235
- */
236
- function checkReleaseNotes(notes, notesSource, level) {
237
- const issues = [];
238
-
239
- if (!notes) {
240
- issues.push('No release notes found. A file is REQUIRED.');
241
- issues.push('Write RELEASE-NOTES-v{version}.md or ai/dev-updates/YYYY-MM-DD--description.md');
242
- issues.push('Commit it on your branch so it is reviewable in the PR.');
243
- return { ok: false, issues, block: true };
244
- }
245
-
246
- // HARD RULE: release notes must come from a file on disk.
247
- // --notes flag is NOT accepted. Write a file. Commit it. Review it.
248
- if (notesSource === 'flag') {
249
- issues.push('Release notes must come from a file, not the --notes flag.');
250
- issues.push('Write RELEASE-NOTES-v{version}.md or ai/dev-updates/YYYY-MM-DD--description.md');
251
- issues.push('Commit it on your branch so it is reviewable in the PR before merge.');
252
- return { ok: false, issues, block: true };
253
- }
254
-
255
- // Notes too short.
256
- if (notes.length < 50) {
257
- issues.push('Release notes are too short (under 50 chars). Explain what changed and why.');
258
- }
259
-
260
- // Check for changelog-style one-liners
261
- const looksLikeChangelog = /^(fix|add|update|remove|bump|chore|refactor|docs?)[\s:]/i.test(notes);
262
- if (looksLikeChangelog && notes.length < 100) {
263
- issues.push('Notes look like a changelog entry, not a narrative. Explain the impact.');
264
- }
265
-
266
- // Narrative quality: must have at least one paragraph (not just bullets/headers)
267
- // A paragraph is 2+ consecutive lines of prose (not starting with -, *, #, |, or ```)
268
- const lines = notes.split('\n').filter(l => l.trim().length > 0);
269
- const proseLines = lines.filter(l => {
270
- const t = l.trim();
271
- return !t.startsWith('#') && !t.startsWith('-') && !t.startsWith('*') &&
272
- !t.startsWith('|') && !t.startsWith('```') && !t.startsWith('>') &&
273
- t.length > 30;
274
- });
275
- if (proseLines.length < 2) {
276
- issues.push('Release notes need narrative, not just bullets. Write at least one paragraph explaining what changed and why it matters. Tell the story.');
277
- }
278
-
279
- // Must be substantial (not just a header + bullets)
280
- if (notes.length < 200) {
281
- issues.push('Release notes are too short (under 200 chars). Every release deserves a story: what was broken or missing, what we built, why the user should care.');
282
- }
283
-
284
- // Release notes should reference at least one issue
285
- const hasIssueRef = /#\d+/.test(notes);
286
- if (!hasIssueRef) {
287
- issues.push('No issue reference found (#XX). Every release should close or reference an issue.');
288
- }
289
-
290
- return { ok: issues.length === 0, issues, block: issues.length > 0 };
291
- }
292
-
293
- /**
294
- * Scaffold a RELEASE-NOTES-v{version}.md template if one doesn't exist.
295
- * Called when the release notes gate blocks. Gives the agent a file to fill in.
296
- */
297
- export function scaffoldReleaseNotes(repoPath, version) {
298
- const dashed = version.replace(/\./g, '-');
299
- const notesPath = join(repoPath, `RELEASE-NOTES-v${dashed}.md`);
300
- if (existsSync(notesPath)) return notesPath;
301
-
302
- const pkg = JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8'));
303
- const name = pkg.name?.replace(/^@[^/]+\//, '') || basename(repoPath);
304
-
305
- // Auto-detect issue references from commits since last tag
306
- let issueRefs = '';
307
- try {
308
- const lastTag = execFileSync('git', ['describe', '--tags', '--abbrev=0'],
309
- { cwd: repoPath, encoding: 'utf8' }).trim();
310
- const log = execFileSync('git', ['log', `${lastTag}..HEAD`, '--oneline'],
311
- { cwd: repoPath, encoding: 'utf8' });
312
- const issues = [...new Set(log.match(/#\d+/g) || [])];
313
- if (issues.length > 0) {
314
- issueRefs = issues.map(i => `- ${i}`).join('\n');
315
- }
316
- } catch {}
317
-
318
- const template = `# Release Notes: ${name} v${version}
319
-
320
- **One-line summary of what this release does**
321
-
322
- Tell the story. What was broken or missing? What did we build? Why does the user care?
323
- Write at least one real paragraph of prose. Not just bullets. The release notes gate
324
- will block if there is no narrative. Bullets are fine for details, but the story comes first.
325
-
326
- ## The story
327
-
328
- (Write a paragraph here. What was the problem? What does this release fix? Why does it matter?
329
- This is what users read. Make it worth reading.)
330
-
331
- ## Issues closed
332
-
333
- ${issueRefs || '- #XX (replace with actual issue numbers)'}
334
-
335
- ## How to verify
336
-
337
- \`\`\`bash
338
- # Commands to test the changes
339
- \`\`\`
340
- `;
341
-
342
- writeFileSync(notesPath, template);
343
- return notesPath;
344
- }
345
-
346
- /**
347
- * Check if a file was modified in commits since the last git tag.
348
- */
349
- function fileModifiedSinceLastTag(repoPath, relativePath) {
350
- try {
351
- const lastTag = execFileSync('git', ['describe', '--tags', '--abbrev=0'],
352
- { cwd: repoPath, encoding: 'utf8' }).trim();
353
- const diff = execFileSync('git', ['diff', '--name-only', lastTag, 'HEAD'],
354
- { cwd: repoPath, encoding: 'utf8' });
355
- return diff.split('\n').some(f => f.trim() === relativePath);
356
- } catch {
357
- // No tags yet or git error ... skip check
358
- return true;
359
- }
360
- }
361
-
362
- /**
363
- * Check that product docs were updated for this release.
364
- * Returns { missing: string[], ok: boolean, skipped: boolean }.
365
- * Only runs if ai/ directory structure exists.
366
- */
367
- function checkProductDocs(repoPath) {
368
- const missing = [];
369
-
370
- // Skip repos without ai/ structure
371
- const aiDir = join(repoPath, 'ai');
372
- if (!existsSync(aiDir)) return { missing: [], ok: true, skipped: true };
373
-
374
- // 1. Dev update: must have a file modified since last release tag.
375
- // Old check ("any file from last 3 days") let the same stale file pass
376
- // across 11 releases in one session. Now uses the same git-based check
377
- // as roadmap and readme-first: was the file actually changed since the tag?
378
- const devUpdatesDir = join(aiDir, 'dev-updates');
379
- if (existsSync(devUpdatesDir)) {
380
- const files = readdirSync(devUpdatesDir).filter(f => f.endsWith('.md'));
381
- if (files.length === 0) {
382
- missing.push('ai/dev-updates/ (no dev update files)');
383
- } else {
384
- const anyModified = files.some(f =>
385
- fileModifiedSinceLastTag(repoPath, `ai/dev-updates/${f}`)
386
- );
387
- if (!anyModified) {
388
- missing.push('ai/dev-updates/ (no dev update modified since last release)');
389
- }
390
- }
391
- }
392
-
393
- // 2. Roadmap: modified since last tag
394
- const roadmapPath = 'ai/product/plans-prds/roadmap.md';
395
- if (existsSync(join(repoPath, roadmapPath))) {
396
- if (!fileModifiedSinceLastTag(repoPath, roadmapPath)) {
397
- missing.push('ai/product/plans-prds/roadmap.md (not updated since last release)');
398
- }
399
- }
400
-
401
- // 3. Readme-first: modified since last tag
402
- const readmeFirstPath = 'ai/product/readme-first-product.md';
403
- if (existsSync(join(repoPath, readmeFirstPath))) {
404
- if (!fileModifiedSinceLastTag(repoPath, readmeFirstPath)) {
405
- missing.push('ai/product/readme-first-product.md (not updated since last release)');
406
- }
407
- }
408
-
409
- // 4. Product update doc: modified since last tag
410
- const productUpdateDir = join(aiDir, 'dev-updates', 'product-update');
411
- if (existsSync(productUpdateDir)) {
412
- const puFiles = readdirSync(productUpdateDir).filter(f => f.endsWith('.md'));
413
- if (puFiles.length > 0) {
414
- const anyModified = puFiles.some(f =>
415
- fileModifiedSinceLastTag(repoPath, `ai/dev-updates/product-update/${f}`)
416
- );
417
- if (!anyModified) {
418
- missing.push('ai/dev-updates/product-update/ (product update doc not updated since last release)');
419
- }
420
- }
421
- }
422
-
423
- return { missing, ok: missing.length === 0, skipped: false };
424
- }
425
-
426
- /**
427
- * Check that technical docs (SKILL.md, TECHNICAL.md) were updated
428
- * when source code changed since last release tag.
429
- * Returns { missing: string[], ok: boolean, skipped: boolean }.
430
- */
431
- function checkTechnicalDocs(repoPath) {
432
- try {
433
- let lastTag;
434
- try {
435
- lastTag = execFileSync('git', ['describe', '--tags', '--abbrev=0'],
436
- { cwd: repoPath, encoding: 'utf8' }).trim();
437
- } catch {
438
- return { missing: [], ok: true, skipped: true }; // No tags yet
439
- }
440
-
441
- const diff = execFileSync('git', ['diff', '--name-only', lastTag, 'HEAD'],
442
- { cwd: repoPath, encoding: 'utf8' });
443
- const changedFiles = diff.split('\n').map(f => f.trim()).filter(Boolean);
444
-
445
- // Find source code changes (*.mjs, *.js, *.ts) excluding non-source dirs
446
- const excludePattern = /\/(node_modules|dist|_trash|examples)\//;
447
- const sourcePattern = /\.(mjs|js|ts)$/;
448
- const sourceChanges = changedFiles.filter(f =>
449
- sourcePattern.test(f) && !excludePattern.test(f) && !f.startsWith('ai/')
450
- );
451
-
452
- if (sourceChanges.length === 0) {
453
- return { missing: [], ok: true, skipped: false }; // No source changes
454
- }
455
-
456
- // Check if any doc files were also modified
457
- const docChanges = changedFiles.filter(f =>
458
- f === 'SKILL.md' || f === 'TECHNICAL.md' ||
459
- /^tools\/[^/]+\/SKILL\.md$/.test(f) ||
460
- /^tools\/[^/]+\/TECHNICAL\.md$/.test(f)
461
- );
462
-
463
- if (docChanges.length > 0) {
464
- return { missing: [], ok: true, skipped: false }; // Docs updated
465
- }
466
-
467
- // Source changed but no doc updates
468
- const missing = [];
469
- const preview = sourceChanges.slice(0, 5).join(', ');
470
- const more = sourceChanges.length > 5 ? ` (and ${sourceChanges.length - 5} more)` : '';
471
- missing.push('Source files changed since last tag but no SKILL.md or TECHNICAL.md was updated');
472
- missing.push(`Changed: ${preview}${more}`);
473
- missing.push('Update SKILL.md or TECHNICAL.md to document these changes');
474
-
475
- return { missing, ok: false, skipped: false };
476
- } catch {
477
- return { missing: [], ok: true, skipped: true }; // Graceful fallback
478
- }
479
- }
480
-
481
- /**
482
- * Parse the interface coverage table from a markdown file.
483
- * Returns array of { name, cli, module, mcp, openclaw, skill, ccHook } or null.
484
- */
485
- function parseInterfaceCoverageTable(filePath) {
486
- if (!existsSync(filePath)) return null;
487
- const content = readFileSync(filePath, 'utf8');
488
- const lines = content.split('\n');
489
-
490
- const headerIdx = lines.findIndex(l => /^\|\s*#\s*\|\s*Tool\s*\|/i.test(l));
491
- if (headerIdx === -1) return null;
492
-
493
- const rows = [];
494
- for (let i = headerIdx + 2; i < lines.length; i++) {
495
- const line = lines[i].trim();
496
- if (!line.startsWith('|')) break;
497
- const cells = line.split('|').map(c => c.trim()).filter(c => c !== '');
498
- if (cells.length < 8) continue;
499
- // Skip category header rows (# cell is empty, non-numeric, or bold)
500
- const num = cells[0].trim();
501
- if (!num || /^\*\*/.test(num) || isNaN(parseInt(num))) continue;
502
- rows.push({
503
- name: cells[1].trim(),
504
- cli: /^Y$/i.test(cells[2]),
505
- module: /^Y$/i.test(cells[3]),
506
- mcp: /^Y$/i.test(cells[4]),
507
- openclaw: /^Y$/i.test(cells[5]),
508
- skill: /^Y$/i.test(cells[6]),
509
- ccHook: /^Y$/i.test(cells[7]),
510
- });
511
- }
512
- return rows.length > 0 ? rows : null;
513
- }
514
-
515
- /**
516
- * Read display name from a tool's SKILL.md frontmatter.
517
- * Tries display-name, then name field. Falls back to null.
518
- */
519
- function getToolDisplayName(toolPath) {
520
- const skillPath = join(toolPath, 'SKILL.md');
521
- if (!existsSync(skillPath)) return null;
522
- try {
523
- const content = readFileSync(skillPath, 'utf8');
524
- const displayMatch = content.match(/^\s*display-name:\s*"?([^"\n]+)"?/m);
525
- if (displayMatch) return displayMatch[1].trim();
526
- const nameMatch = content.match(/^name:\s*"?([^"\n]+)"?/m);
527
- if (nameMatch) return nameMatch[1].trim();
528
- } catch {}
529
- return null;
530
- }
531
-
532
- /**
533
- * Check that the interface coverage table in README.md and SKILL.md
534
- * matches the actual interfaces detected in tools/* subdirectories.
535
- * Returns { missing: string[], ok: boolean, skipped: boolean }.
536
- */
537
- function checkInterfaceCoverage(repoPath) {
538
- try {
539
- // Only applies to toolbox repos
540
- const toolsDir = join(repoPath, 'tools');
541
- if (!existsSync(toolsDir)) return { missing: [], ok: true, skipped: true };
542
-
543
- const entries = readdirSync(toolsDir, { withFileTypes: true });
544
- const tools = entries
545
- .filter(e => e.isDirectory() && existsSync(join(toolsDir, e.name, 'package.json')))
546
- .map(e => ({ name: e.name, path: join(toolsDir, e.name) }));
547
-
548
- if (tools.length === 0) return { missing: [], ok: true, skipped: true };
549
-
550
- // Detect actual interfaces for each tool
551
- const actualMap = {};
552
- for (const tool of tools) {
553
- const pkg = JSON.parse(readFileSync(join(tool.path, 'package.json'), 'utf8'));
554
- actualMap[tool.name] = {
555
- displayName: getToolDisplayName(tool.path) || tool.name,
556
- cli: !!(pkg.bin),
557
- module: !!(pkg.main || pkg.exports),
558
- mcp: ['mcp-server.mjs', 'mcp-server.js', 'dist/mcp-server.js'].some(f => existsSync(join(tool.path, f))),
559
- openclaw: existsSync(join(tool.path, 'openclaw.plugin.json')),
560
- skill: existsSync(join(tool.path, 'SKILL.md')),
561
- ccHook: !!(pkg.claudeCode?.hook) || existsSync(join(tool.path, 'guard.mjs')),
562
- };
563
- }
564
-
565
- const missing = [];
566
-
567
- // Check both README.md and SKILL.md tables
568
- for (const [label, filePath] of [['README.md', join(repoPath, 'README.md')], ['SKILL.md', join(repoPath, 'SKILL.md')]]) {
569
- const tableRows = parseInterfaceCoverageTable(filePath);
570
- if (!tableRows) continue;
571
-
572
- // Tool count
573
- if (tools.length !== tableRows.length) {
574
- missing.push(`${label}: tool count mismatch (${tools.length} in tools/, ${tableRows.length} in table)`);
575
- }
576
-
577
- // Check each actual tool against the table
578
- for (const tool of tools) {
579
- const actual = actualMap[tool.name];
580
- const displayName = actual.displayName;
581
- const tableRow = tableRows.find(r =>
582
- r.name === displayName ||
583
- r.name.toLowerCase() === displayName.toLowerCase() ||
584
- r.name.toLowerCase().includes(tool.name.replace(/^wip-/, '').replace(/-/g, ' '))
585
- );
586
-
587
- if (!tableRow) {
588
- missing.push(`${label}: ${tool.name} (${displayName}) missing from coverage table`);
589
- continue;
590
- }
591
-
592
- const ifaceMap = [
593
- ['cli', 'CLI'], ['module', 'Module'], ['mcp', 'MCP'],
594
- ['openclaw', 'OC Plugin'], ['skill', 'Skill'], ['ccHook', 'CC Hook']
595
- ];
596
-
597
- for (const [key, name] of ifaceMap) {
598
- if (actual[key] && !tableRow[key]) {
599
- missing.push(`${label}: ${displayName} has ${name} but table says no`);
600
- }
601
- if (tableRow[key] && !actual[key]) {
602
- missing.push(`${label}: ${displayName} marked ${name} in table but not detected`);
603
- }
604
- }
605
- }
606
- }
607
-
608
- return { missing, ok: missing.length === 0, skipped: false };
609
- } catch {
610
- return { missing: [], ok: true, skipped: true }; // Graceful fallback
611
- }
612
- }
613
-
614
- /**
615
- * Auto-update version/date lines in product docs before the release commit.
616
- * Updates roadmap.md "Current version" and "Last updated",
617
- * and readme-first-product.md "Last updated" and "What's Built (as of vX.Y.Z)".
618
- * Returns number of files updated.
619
- */
620
- function syncProductDocs(repoPath, newVersion) {
621
- let updated = 0;
622
- const td = new Date();
623
- const today = `${td.getFullYear()}-${String(td.getMonth()+1).padStart(2,'0')}-${String(td.getDate()).padStart(2,'0')}`;
624
-
625
- // 1. roadmap.md
626
- const roadmapPath = join(repoPath, 'ai', 'product', 'plans-prds', 'roadmap.md');
627
- if (existsSync(roadmapPath)) {
628
- let content = readFileSync(roadmapPath, 'utf8');
629
- let changed = false;
630
-
631
- // Update "Current version: vX.Y.Z"
632
- const versionRe = /(\*\*Current version:\*\*\s*)v[\d.]+/;
633
- if (versionRe.test(content)) {
634
- content = content.replace(versionRe, `$1v${newVersion}`);
635
- changed = true;
636
- }
637
-
638
- // Update "Last updated: YYYY-MM-DD"
639
- const dateRe = /(\*\*Last updated:\*\*\s*)[\d-]+/;
640
- if (dateRe.test(content)) {
641
- content = content.replace(dateRe, `$1${today}`);
642
- changed = true;
643
- }
644
-
645
- if (changed) {
646
- writeFileSync(roadmapPath, content);
647
- updated++;
648
- }
649
- }
650
-
651
- // 2. readme-first-product.md
652
- const rfpPath = join(repoPath, 'ai', 'product', 'readme-first-product.md');
653
- if (existsSync(rfpPath)) {
654
- let content = readFileSync(rfpPath, 'utf8');
655
- let changed = false;
656
-
657
- // Update "Last updated: YYYY-MM-DD"
658
- const dateRe = /(\*\*Last updated:\*\*\s*)[\d-]+/;
659
- if (dateRe.test(content)) {
660
- content = content.replace(dateRe, `$1${today}`);
661
- changed = true;
662
- }
663
-
664
- // Update "What's Built (as of vX.Y.Z)"
665
- const builtRe = /(What's Built \(as of\s*)v[\d.]+(\))/;
666
- if (builtRe.test(content)) {
667
- content = content.replace(builtRe, `$1v${newVersion}$2`);
668
- changed = true;
669
- }
670
-
671
- if (changed) {
672
- writeFileSync(rfpPath, content);
673
- updated++;
674
- }
675
- }
676
-
677
- return updated;
678
- }
679
-
680
- /**
681
- * Build release notes with narrative first, commit details second.
682
- *
683
- * Release notes should tell the story: what was built, why, and why it matters.
684
- * Commit history is included as supporting detail, not the main content.
685
- * ai/ files are excluded from the files-changed stats.
686
- */
687
- export function buildReleaseNotes(repoPath, currentVersion, newVersion, notes) {
688
- const slug = detectRepoSlug(repoPath);
689
- const pkg = JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8'));
690
- const lines = [];
691
-
692
- // Narrative summary (the main content of the release notes)
693
- if (notes) {
694
- lines.push(notes);
695
- lines.push('');
696
- }
697
-
698
- // Gather commits since last tag
699
- const prevTag = `v${currentVersion}`;
700
- let rawCommits = [];
701
- try {
702
- const raw = execFileSync('git', [
703
- 'log', `${prevTag}..HEAD`, '--pretty=format:%h\t%s'
704
- ], { cwd: repoPath, encoding: 'utf8' }).trim();
705
- if (raw) rawCommits = raw.split('\n').map(line => {
706
- const [hash, ...rest] = line.split('\t');
707
- return { hash, subject: rest.join('\t') };
708
- });
709
- } catch {
710
- try {
711
- const raw = execFileSync('git', [
712
- 'log', '--pretty=format:%h\t%s', '-30'
713
- ], { cwd: repoPath, encoding: 'utf8' }).trim();
714
- if (raw) rawCommits = raw.split('\n').map(line => {
715
- const [hash, ...rest] = line.split('\t');
716
- return { hash, subject: rest.join('\t') };
717
- });
718
- } catch {}
719
- }
720
-
721
- // Categorize commits
722
- const categories = { changes: [], fixes: [], docs: [], internal: [] };
723
- for (const commit of rawCommits) {
724
- const cat = categorizeCommit(commit.subject);
725
- categories[cat].push(commit);
726
- }
727
-
728
- // Commit details section (supporting detail, not the headline)
729
- const hasCommits = categories.changes.length + categories.fixes.length + categories.docs.length > 0;
730
- if (hasCommits) {
731
- lines.push('<details>');
732
- lines.push('<summary>What changed (commits)</summary>');
733
- lines.push('');
734
-
735
- if (categories.changes.length > 0) {
736
- lines.push('**Changes**');
737
- for (const c of categories.changes) {
738
- lines.push(`- ${c.subject} (${c.hash})`);
739
- }
740
- lines.push('');
741
- }
742
-
743
- if (categories.fixes.length > 0) {
744
- lines.push('**Fixes**');
745
- for (const c of categories.fixes) {
746
- lines.push(`- ${c.subject} (${c.hash})`);
747
- }
748
- lines.push('');
749
- }
750
-
751
- if (categories.docs.length > 0) {
752
- lines.push('**Docs**');
753
- for (const c of categories.docs) {
754
- lines.push(`- ${c.subject} (${c.hash})`);
755
- }
756
- lines.push('');
757
- }
758
-
759
- lines.push('</details>');
760
- lines.push('');
761
- }
762
-
763
- // Install section
764
- lines.push('### Install');
765
- lines.push('```bash');
766
- lines.push(`npm install -g ${pkg.name}@${newVersion}`);
767
- lines.push('```');
768
- lines.push('');
769
- lines.push('Or update your local clone:');
770
- lines.push('```bash');
771
- lines.push('git pull origin main');
772
- lines.push('```');
773
- lines.push('');
774
-
775
- // Attribution
776
- lines.push('---');
777
- lines.push('');
778
- lines.push('Built by Parker Todd Brooks, Lēsa (OpenClaw, Claude Opus 4.6), Claude Code (Claude Opus 4.6).');
779
-
780
- // Compare URL
781
- if (slug) {
782
- lines.push('');
783
- lines.push(`Full changelog: https://github.com/${slug}/compare/v${currentVersion}...v${newVersion}`);
784
- }
785
-
786
- return lines.join('\n');
787
- }
788
-
789
- /**
790
- * Create a GitHub release with detailed notes.
791
- */
792
- export function createGitHubRelease(repoPath, newVersion, notes, currentVersion) {
793
- const repoSlug = detectRepoSlug(repoPath);
794
- const body = buildReleaseNotes(repoPath, currentVersion, newVersion, notes);
795
-
796
- // Write notes to a temp file to avoid shell escaping issues
797
- const tmpFile = join(repoPath, '.release-notes-tmp.md');
798
- writeFileSync(tmpFile, body);
799
-
800
- try {
801
- execFileSync('gh', [
802
- 'release', 'create', `v${newVersion}`,
803
- '--title', `v${newVersion}`,
804
- '--notes-file', '.release-notes-tmp.md',
805
- '--repo', repoSlug
806
- ], { cwd: repoPath, stdio: 'inherit' });
807
-
808
- // Bug fix #121: verify the release was actually created
809
- try {
810
- const verify = execFileSync('gh', [
811
- 'release', 'view', `v${newVersion}`,
812
- '--repo', repoSlug, '--json', 'body', '--jq', '.body | length'
813
- ], { cwd: repoPath, encoding: 'utf8' }).trim();
814
- const bodyLen = parseInt(verify, 10);
815
- if (bodyLen < 50) {
816
- console.warn(` ! GitHub release body is only ${bodyLen} chars. Notes may be truncated.`);
817
- }
818
- } catch {}
819
-
820
- // Auto-close referenced issues
821
- const issueNums = [...new Set((body.match(/#(\d+)/g) || []).map(m => m.slice(1)))];
822
- for (const num of issueNums) {
823
- try {
824
- // Only close if issue exists and is open on the public repo
825
- const publicSlug = repoSlug.replace(/-private$/, '');
826
- execFileSync('gh', [
827
- 'issue', 'close', num,
828
- '--repo', publicSlug,
829
- '--comment', `Closed by v${newVersion}. See release notes.`
830
- ], { cwd: repoPath, stdio: 'pipe' });
831
- console.log(` ✓ Closed #${num} on ${publicSlug}`);
832
- } catch {
833
- // Issue doesn't exist on public repo or already closed. Fine.
834
- }
835
- }
836
- } finally {
837
- try { execFileSync('rm', ['-f', tmpFile]); } catch {}
838
- }
839
- }
840
-
841
- /**
842
- * Publish skill to ClawHub.
843
- */
844
- export function publishClawHub(repoPath, newVersion, notes) {
845
- const skillPath = join(repoPath, 'SKILL.md');
846
- if (!existsSync(skillPath)) return false;
847
-
848
- const slug = detectSkillSlug(repoPath);
849
- const changelog = notes || 'Release.';
850
-
851
- execFileSync('clawhub', [
852
- 'publish', repoPath,
853
- '--slug', slug,
854
- '--version', newVersion,
855
- '--changelog', changelog
856
- ], { cwd: repoPath, stdio: 'inherit' });
857
- return true;
858
- }
859
-
860
- // ── Skill Publish ────────────────────────────────────────────────────
861
-
862
- /**
863
- * Publish SKILL.md to website as plain text.
864
- *
865
- * Auto-detects: if SKILL.md exists and WIP_WEBSITE_REPO is set,
866
- * publishes automatically. No config file needed.
867
- *
868
- * Name resolution (first match wins):
869
- * 1. .publish-skill.json { "name": "memory-crystal" }
870
- * 2. SKILL.md frontmatter name: field
871
- * 3. Directory name (basename of repoPath)
872
- *
873
- * Copies SKILL.md to {website}/wip.computer/install/{name}.txt
874
- * Then runs deploy.sh to push to VPS.
875
- *
876
- * Non-blocking: returns result, never throws.
877
- */
878
- export function publishSkillToWebsite(repoPath) {
879
- // Resolve website repo: .publish-skill.json > env var
880
- let websiteRepo;
881
- let targetName;
882
- const configPath = join(repoPath, '.publish-skill.json');
883
- let publishConfig = {};
884
- if (existsSync(configPath)) {
885
- try { publishConfig = JSON.parse(readFileSync(configPath, 'utf8')); } catch {}
886
- }
887
-
888
- websiteRepo = publishConfig.websiteRepo || process.env.WIP_WEBSITE_REPO;
889
- if (!websiteRepo) return { skipped: true, reason: 'no websiteRepo in .publish-skill.json and WIP_WEBSITE_REPO not set' };
890
-
891
- // Find SKILL.md: check root, then skills/*/SKILL.md
892
- let skillFile = join(repoPath, 'SKILL.md');
893
- if (!existsSync(skillFile)) {
894
- const skillsDir = join(repoPath, 'skills');
895
- if (existsSync(skillsDir)) {
896
- for (const sub of readdirSync(skillsDir)) {
897
- const candidate = join(skillsDir, sub, 'SKILL.md');
898
- if (existsSync(candidate)) { skillFile = candidate; break; }
899
- }
900
- }
901
- }
902
- if (!existsSync(skillFile)) return { skipped: true, reason: 'no SKILL.md found' };
903
-
904
- // Resolve target name: config > package.json > directory name
905
- // SKILL.md frontmatter name is skipped because it's a short slug
906
- // (e.g., "memory") not the full install name (e.g., "memory-crystal").
907
-
908
- // 1. Explicit config (optional, overrides auto-detect)
909
- if (publishConfig.name) targetName = publishConfig.name;
910
-
911
- // 2. package.json name (strip @scope/ prefix, most reliable)
912
- if (!targetName) {
913
- const pkgPath = join(repoPath, 'package.json');
914
- if (existsSync(pkgPath)) {
915
- try {
916
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
917
- if (pkg.name) targetName = pkg.name.replace(/^@[^/]+\//, '');
918
- } catch {}
919
- }
920
- }
921
-
922
- // 3. Directory name fallback (strip -private suffix)
923
- if (!targetName) {
924
- targetName = basename(repoPath).replace(/-private$/, '').toLowerCase();
925
- }
926
-
927
- // Copy to website install dir
928
- const installDir = join(websiteRepo, 'wip.computer', 'install');
929
- if (!existsSync(installDir)) {
930
- try { mkdirSync(installDir, { recursive: true }); } catch {}
931
- }
932
-
933
- const targetFile = join(installDir, `${targetName}.txt`);
934
- try {
935
- const content = readFileSync(skillFile, 'utf8');
936
- writeFileSync(targetFile, content);
937
- } catch (e) {
938
- return { ok: false, error: `copy failed: ${e.message}` };
939
- }
940
-
941
- // Deploy to VPS (non-blocking ... warn on failure)
942
- const deployScript = join(websiteRepo, 'deploy.sh');
943
- if (existsSync(deployScript)) {
944
- try {
945
- execSync(`bash deploy.sh`, { cwd: websiteRepo, stdio: 'pipe', timeout: 30000 });
946
- } catch (e) {
947
- return { ok: true, deployed: false, target: targetName, error: `deploy failed: ${e.message}` };
948
- }
949
- } else {
950
- return { ok: true, deployed: false, target: targetName, error: 'no deploy.sh found' };
951
- }
952
-
953
- return { ok: true, deployed: true, target: targetName };
954
- }
955
-
956
- // ── Helpers ──────────────────────────────────────────────────────────
957
-
958
- function getNpmToken() {
959
- try {
960
- return execSync(
961
- `OP_SERVICE_ACCOUNT_TOKEN=$(cat ~/.openclaw/secrets/op-sa-token) op item get "npm Token" --vault "Agent Secrets" --fields label=password --reveal 2>/dev/null`,
962
- { encoding: 'utf8' }
963
- ).trim();
964
- } catch {
965
- throw new Error('Could not fetch npm token from 1Password. Check op CLI and SA token.');
966
- }
967
- }
968
-
969
- function detectSkillSlug(repoPath) {
970
- // Read the name field from SKILL.md frontmatter (agentskills.io spec: lowercase-hyphen slug).
971
- // Falls back to directory name.
972
- const skillPath = join(repoPath, 'SKILL.md');
973
- if (existsSync(skillPath)) {
974
- const content = readFileSync(skillPath, 'utf8');
975
- const nameMatch = content.match(/^---[\s\S]*?\nname:\s*(.+?)\n/);
976
- if (nameMatch) {
977
- const name = nameMatch[1].trim().replace(/^["']|["']$/g, '');
978
- // Only use if it looks like a slug (lowercase, hyphens)
979
- if (/^[a-z][a-z0-9-]*$/.test(name)) return name;
980
- }
981
- }
982
- return basename(repoPath).toLowerCase();
983
- }
984
-
985
- function detectRepoSlug(repoPath) {
986
- try {
987
- const url = execSync('git remote get-url origin', { cwd: repoPath, encoding: 'utf8' }).trim();
988
- // git@github.com:wipcomputer/wip-grok.git or https://github.com/wipcomputer/wip-grok.git
989
- const match = url.match(/github\.com[:/](.+?)(?:\.git)?$/);
990
- return match ? match[1] : null;
991
- } catch {
992
- return null;
993
- }
994
- }
995
-
996
- // ── Stale Branch Check ──────────────────────────────────────────────
997
-
998
- /**
999
- * Check for remote branches that are already merged into origin/main.
1000
- * These should be cleaned up before releasing.
1001
- *
1002
- * For patch: WARN (non-blocking, just print stale branches).
1003
- * For minor/major: BLOCK (return { failed: true }).
1004
- *
1005
- * Filters out origin/main, origin/HEAD, and already-renamed --merged- branches.
1006
- */
1007
- export function checkStaleBranches(repoPath, level) {
1008
- try {
1009
- // Fetch latest remote state so --merged check is accurate
1010
- try {
1011
- execFileSync('git', ['fetch', '--prune'], { cwd: repoPath, stdio: 'pipe' });
1012
- } catch {
1013
- // Non-fatal: proceed with local state if fetch fails
1014
- }
1015
-
1016
- const raw = execFileSync('git', ['branch', '-r', '--merged', 'origin/main'], {
1017
- cwd: repoPath, encoding: 'utf8'
1018
- }).trim();
1019
-
1020
- if (!raw) return { stale: [], ok: true };
1021
-
1022
- const stale = raw.split('\n')
1023
- .map(b => b.trim())
1024
- .filter(b =>
1025
- b &&
1026
- !b.includes('origin/main') &&
1027
- !b.includes('origin/HEAD') &&
1028
- !b.includes('--merged-')
1029
- );
1030
-
1031
- if (stale.length === 0) return { stale: [], ok: true };
1032
-
1033
- const isMinorOrMajor = level === 'minor' || level === 'major';
1034
- return {
1035
- stale,
1036
- ok: !isMinorOrMajor,
1037
- blocked: isMinorOrMajor,
1038
- };
1039
- } catch {
1040
- // Git command failed... skip check gracefully
1041
- return { stale: [], ok: true, skipped: true };
1042
- }
1043
- }
1044
-
1045
- // ── Main ────────────────────────────────────────────────────────────
1046
-
1047
- /**
1048
- * Run the full release pipeline.
1049
- */
1050
- export async function release({ repoPath, level, notes, notesSource, dryRun, noPublish, skipProductCheck, skipStaleCheck, skipWorktreeCheck, skipTechDocsCheck, skipCoverageCheck }) {
1051
- repoPath = repoPath || process.cwd();
1052
- const currentVersion = detectCurrentVersion(repoPath);
1053
- const newVersion = bumpSemver(currentVersion, level);
1054
- const repoName = basename(repoPath);
1055
-
1056
- console.log('');
1057
- console.log(` ${repoName}: ${currentVersion} -> ${newVersion} (${level})`);
1058
- console.log(` ${'─'.repeat(40)}`);
1059
-
1060
- // -1. Worktree guard: block releases from linked worktrees
1061
- if (!skipWorktreeCheck) {
1062
- try {
1063
- const gitDir = execFileSync('git', ['rev-parse', '--git-dir'], {
1064
- cwd: repoPath, encoding: 'utf8'
1065
- }).trim();
1066
-
1067
- // Linked worktrees have "/worktrees/" in their git-dir path
1068
- if (gitDir.includes('/worktrees/')) {
1069
- // Get the main working tree path from `git worktree list`
1070
- const worktreeList = execFileSync('git', ['worktree', 'list', '--porcelain'], {
1071
- cwd: repoPath, encoding: 'utf8'
1072
- });
1073
- const mainWorktree = worktreeList.split('\n')
1074
- .find(line => line.startsWith('worktree '));
1075
- const mainPath = mainWorktree ? mainWorktree.replace('worktree ', '') : '(unknown)';
1076
-
1077
- console.log(` \u2717 wip-release must run from the main working tree, not a worktree.`);
1078
- console.log(` Current: ${repoPath}`);
1079
- console.log(` Main working tree: ${mainPath}`);
1080
- console.log(` Switch to the main working tree and run again.`);
1081
- console.log('');
1082
- return { currentVersion, newVersion, dryRun: false, failed: true };
1083
- }
1084
- console.log(' \u2713 Running from main working tree');
1085
- } catch {
1086
- // Git command failed... skip check gracefully
1087
- }
1088
- }
1089
-
1090
- // 0. License compliance gate
1091
- const configPath = join(repoPath, '.license-guard.json');
1092
- if (existsSync(configPath)) {
1093
- const config = JSON.parse(readFileSync(configPath, 'utf8'));
1094
- const licenseIssues = [];
1095
-
1096
- const licensePath = join(repoPath, 'LICENSE');
1097
- if (!existsSync(licensePath)) {
1098
- licenseIssues.push('LICENSE file is missing');
1099
- } else {
1100
- const licenseText = readFileSync(licensePath, 'utf8');
1101
- if (!licenseText.includes(config.copyright)) {
1102
- licenseIssues.push(`LICENSE copyright does not match "${config.copyright}"`);
1103
- }
1104
- if (config.license === 'MIT+AGPL' && !licenseText.includes('AGPL') && !licenseText.includes('GNU Affero')) {
1105
- licenseIssues.push('LICENSE is MIT-only but config requires MIT+AGPL');
1106
- }
1107
- }
1108
-
1109
- if (!existsSync(join(repoPath, 'CLA.md'))) {
1110
- licenseIssues.push('CLA.md is missing');
1111
- }
1112
-
1113
- const readmePath = join(repoPath, 'README.md');
1114
- if (existsSync(readmePath)) {
1115
- const readme = readFileSync(readmePath, 'utf8');
1116
- if (!readme.includes('## License')) licenseIssues.push('README.md missing ## License section');
1117
- if (config.license === 'MIT+AGPL' && !readme.includes('AGPL')) licenseIssues.push('README.md License section missing AGPL reference');
1118
- }
1119
-
1120
- if (licenseIssues.length > 0) {
1121
- console.log(` ✗ License compliance failed:`);
1122
- for (const issue of licenseIssues) console.log(` - ${issue}`);
1123
- console.log(`\n Run \`wip-license-guard check --fix\` to auto-repair, then try again.`);
1124
- console.log('');
1125
- return { currentVersion, newVersion, dryRun: false, failed: true };
1126
- }
1127
- console.log(` ✓ License compliance passed`);
1128
- }
1129
-
1130
- // 0.5. Product docs check
1131
- if (!skipProductCheck) {
1132
- const productCheck = checkProductDocs(repoPath);
1133
- if (!productCheck.skipped) {
1134
- if (productCheck.ok) {
1135
- console.log(' ✓ Product docs up to date');
1136
- } else {
1137
- const isMinorOrMajor = level === 'minor' || level === 'major';
1138
- const prefix = isMinorOrMajor ? '✗' : '!';
1139
- console.log(` ${prefix} Product docs need attention:`);
1140
- for (const m of productCheck.missing) console.log(` - ${m}`);
1141
- if (isMinorOrMajor) {
1142
- console.log('');
1143
- console.log(' Update product docs before a minor/major release.');
1144
- console.log(' Use --skip-product-check to override.');
1145
- console.log('');
1146
- return { currentVersion, newVersion, dryRun: false, failed: true };
1147
- }
1148
- }
1149
- }
1150
- }
1151
-
1152
- // 0.75. Release notes quality gate
1153
- {
1154
- const notesCheck = checkReleaseNotes(notes, notesSource || 'flag', level);
1155
- if (notesCheck.ok) {
1156
- const sourceLabel = notesSource === 'file' ? 'from file' : notesSource === 'dev-update' ? 'from dev update' : 'from --notes';
1157
- console.log(` ✓ Release notes OK (${sourceLabel})`);
1158
- } else {
1159
- console.log(` ✗ Release notes blocked:`);
1160
- for (const issue of notesCheck.issues) console.log(` - ${issue}`);
1161
- console.log('');
1162
- // Scaffold a template so the agent has something to fill in
1163
- const templatePath = scaffoldReleaseNotes(repoPath, newVersion);
1164
- console.log(` Scaffolded template: ${basename(templatePath)}`);
1165
- console.log(' Fill it in, commit, then run wip-release again.');
1166
- console.log('');
1167
- return { currentVersion, newVersion, dryRun: false, failed: true };
1168
- }
1169
- }
1170
-
1171
- // 0.8. Stale remote branch check
1172
- if (!skipStaleCheck) {
1173
- const staleCheck = checkStaleBranches(repoPath, level);
1174
- if (staleCheck.skipped) {
1175
- // Silently skip if git command failed
1176
- } else if (staleCheck.stale.length === 0) {
1177
- console.log(' ✓ No stale remote branches');
1178
- } else {
1179
- const isMinorOrMajor = level === 'minor' || level === 'major';
1180
- const prefix = isMinorOrMajor ? '✗' : '!';
1181
- console.log(` ${prefix} Stale remote branches merged into main:`);
1182
- for (const b of staleCheck.stale) console.log(` - ${b}`);
1183
- if (isMinorOrMajor) {
1184
- console.log('');
1185
- console.log(' Clean up stale branches before a minor/major release.');
1186
- console.log(' Delete them with: git push origin --delete <branch>');
1187
- console.log(' Use --skip-stale-check to override.');
1188
- console.log('');
1189
- return { currentVersion, newVersion, dryRun: false, failed: true };
1190
- }
1191
- }
1192
- }
1193
-
1194
- // 0.85. Technical docs check
1195
- if (!skipTechDocsCheck) {
1196
- const techDocsCheck = checkTechnicalDocs(repoPath);
1197
- if (!techDocsCheck.skipped) {
1198
- if (techDocsCheck.ok) {
1199
- console.log(' ✓ Technical docs up to date');
1200
- } else {
1201
- const isMinorOrMajor = level === 'minor' || level === 'major';
1202
- const prefix = isMinorOrMajor ? '✗' : '!';
1203
- console.log(` ${prefix} Technical docs need attention:`);
1204
- for (const m of techDocsCheck.missing) console.log(` - ${m}`);
1205
- if (isMinorOrMajor) {
1206
- console.log('');
1207
- console.log(' Update SKILL.md or TECHNICAL.md before a minor/major release.');
1208
- console.log(' Use --skip-tech-docs-check to override.');
1209
- console.log('');
1210
- return { currentVersion, newVersion, dryRun: false, failed: true };
1211
- }
1212
- }
1213
- }
1214
- }
1215
-
1216
- // 0.9. Interface coverage check
1217
- if (!skipCoverageCheck) {
1218
- const coverageCheck = checkInterfaceCoverage(repoPath);
1219
- if (!coverageCheck.skipped) {
1220
- if (coverageCheck.ok) {
1221
- console.log(' ✓ Interface coverage table matches');
1222
- } else {
1223
- const isMinorOrMajor = level === 'minor' || level === 'major';
1224
- const prefix = isMinorOrMajor ? '✗' : '!';
1225
- console.log(` ${prefix} Interface coverage table has mismatches:`);
1226
- for (const m of coverageCheck.missing) console.log(` - ${m}`);
1227
- if (isMinorOrMajor) {
1228
- console.log('');
1229
- console.log(' Update the coverage table in README.md and SKILL.md.');
1230
- console.log(' Use --skip-coverage-check to override.');
1231
- console.log('');
1232
- return { currentVersion, newVersion, dryRun: false, failed: true };
1233
- }
1234
- }
1235
- }
1236
- }
1237
-
1238
- if (dryRun) {
1239
- // Product docs check (dry-run)
1240
- if (!skipProductCheck) {
1241
- const productCheck = checkProductDocs(repoPath);
1242
- if (!productCheck.skipped) {
1243
- if (productCheck.ok) {
1244
- console.log(' [dry run] ✓ Product docs up to date');
1245
- } else {
1246
- const isMinorOrMajor = level === 'minor' || level === 'major';
1247
- console.log(` [dry run] ${isMinorOrMajor ? '✗ Would BLOCK' : '! Would WARN'}: product docs need updates`);
1248
- for (const m of productCheck.missing) console.log(` - ${m}`);
1249
- }
1250
- }
1251
- }
1252
- // Release notes check (dry-run)
1253
- {
1254
- const notesCheck = checkReleaseNotes(notes, notesSource || 'flag', level);
1255
- if (notesCheck.ok) {
1256
- const sourceLabel = notesSource === 'file' ? 'from file' : notesSource === 'dev-update' ? 'from dev update' : 'from --notes';
1257
- console.log(` [dry run] ✓ Release notes OK (${sourceLabel})`);
1258
- } else {
1259
- const isMinorOrMajor = level === 'minor' || level === 'major';
1260
- console.log(` [dry run] ${isMinorOrMajor ? '✗ Would BLOCK' : '! Would WARN'}: release notes need attention`);
1261
- for (const issue of notesCheck.issues) console.log(` - ${issue}`);
1262
- }
1263
- }
1264
- // Stale branch check (dry-run)
1265
- if (!skipStaleCheck) {
1266
- const staleCheck = checkStaleBranches(repoPath, level);
1267
- if (!staleCheck.skipped && staleCheck.stale.length > 0) {
1268
- const isMinorOrMajor = level === 'minor' || level === 'major';
1269
- console.log(` [dry run] ${isMinorOrMajor ? '✗ Would BLOCK' : '! Would WARN'}: stale remote branches`);
1270
- for (const b of staleCheck.stale) console.log(` - ${b}`);
1271
- } else if (!staleCheck.skipped) {
1272
- console.log(' [dry run] ✓ No stale remote branches');
1273
- }
1274
- }
1275
- // Technical docs check (dry-run)
1276
- if (!skipTechDocsCheck) {
1277
- const techDocsCheck = checkTechnicalDocs(repoPath);
1278
- if (!techDocsCheck.skipped) {
1279
- if (techDocsCheck.ok) {
1280
- console.log(' [dry run] ✓ Technical docs up to date');
1281
- } else {
1282
- const isMinorOrMajor = level === 'minor' || level === 'major';
1283
- console.log(` [dry run] ${isMinorOrMajor ? '✗ Would BLOCK' : '! Would WARN'}: technical docs need updates`);
1284
- for (const m of techDocsCheck.missing) console.log(` - ${m}`);
1285
- }
1286
- }
1287
- }
1288
- // Interface coverage check (dry-run)
1289
- if (!skipCoverageCheck) {
1290
- const coverageCheck = checkInterfaceCoverage(repoPath);
1291
- if (!coverageCheck.skipped) {
1292
- if (coverageCheck.ok) {
1293
- console.log(' [dry run] ✓ Interface coverage table matches');
1294
- } else {
1295
- const isMinorOrMajor = level === 'minor' || level === 'major';
1296
- console.log(` [dry run] ${isMinorOrMajor ? '✗ Would BLOCK' : '! Would WARN'}: interface coverage mismatches`);
1297
- for (const m of coverageCheck.missing) console.log(` - ${m}`);
1298
- }
1299
- }
1300
- }
1301
- const hasSkill = existsSync(join(repoPath, 'SKILL.md'));
1302
- console.log(` [dry run] Would bump package.json to ${newVersion}`);
1303
- if (hasSkill) console.log(` [dry run] Would update SKILL.md version`);
1304
- console.log(` [dry run] Would update CHANGELOG.md`);
1305
- console.log(` [dry run] Would commit and tag v${newVersion}`);
1306
- if (!noPublish) {
1307
- console.log(` [dry run] Would publish to npm (@wipcomputer scope)`);
1308
- console.log(` [dry run] GitHub Packages: handled by deploy-public.sh`);
1309
- console.log(` [dry run] Would create GitHub release v${newVersion}`);
1310
- if (hasSkill) console.log(` [dry run] Would publish to ClawHub`);
1311
- // Skill-to-website dry run (auto-detects SKILL.md, no config needed)
1312
- if (hasSkill) {
1313
- const envSet = !!process.env.WIP_WEBSITE_REPO;
1314
- if (envSet) {
1315
- // Resolve name same way as publishSkillToWebsite
1316
- let dryName;
1317
- const publishConfig = join(repoPath, '.publish-skill.json');
1318
- if (existsSync(publishConfig)) {
1319
- try { dryName = JSON.parse(readFileSync(publishConfig, 'utf8')).name; } catch {}
1320
- }
1321
- if (!dryName) {
1322
- const pkgPath = join(repoPath, 'package.json');
1323
- if (existsSync(pkgPath)) {
1324
- try { dryName = JSON.parse(readFileSync(pkgPath, 'utf8')).name?.replace(/^@[^/]+\//, ''); } catch {}
1325
- }
1326
- }
1327
- if (!dryName) dryName = basename(repoPath).replace(/-private$/, '').toLowerCase();
1328
- console.log(` [dry run] Would publish SKILL.md to website: install/${dryName}.txt`);
1329
- } else {
1330
- console.log(` [dry run] Would publish SKILL.md to website but WIP_WEBSITE_REPO not set`);
1331
- }
1332
- }
1333
- }
1334
- console.log('');
1335
- console.log(` Dry run complete. No changes made.`);
1336
- console.log('');
1337
- return { currentVersion, newVersion, dryRun: true };
1338
- }
1339
-
1340
- // 1. Bump package.json
1341
- writePackageVersion(repoPath, newVersion);
1342
- console.log(` ✓ package.json -> ${newVersion}`);
1343
-
1344
- // 1.5. Bump sub-tool versions in toolbox repos (tools/*/)
1345
- const toolsDir = join(repoPath, 'tools');
1346
- if (existsSync(toolsDir)) {
1347
- let subBumped = 0;
1348
- try {
1349
- const entries = readdirSync(toolsDir, { withFileTypes: true });
1350
- for (const entry of entries) {
1351
- if (!entry.isDirectory()) continue;
1352
- const subPkgPath = join(toolsDir, entry.name, 'package.json');
1353
- if (existsSync(subPkgPath)) {
1354
- try {
1355
- const subPkg = JSON.parse(readFileSync(subPkgPath, 'utf8'));
1356
- subPkg.version = newVersion;
1357
- writeFileSync(subPkgPath, JSON.stringify(subPkg, null, 2) + '\n');
1358
- subBumped++;
1359
- } catch {}
1360
- }
1361
- }
1362
- } catch {}
1363
- if (subBumped > 0) {
1364
- console.log(` ✓ ${subBumped} sub-tool(s) -> ${newVersion}`);
1365
- }
1366
- }
1367
-
1368
- // 2. Sync SKILL.md
1369
- if (syncSkillVersion(repoPath, newVersion)) {
1370
- console.log(` ✓ SKILL.md -> ${newVersion}`);
1371
- }
1372
-
1373
- // 3. Update CHANGELOG.md
1374
- updateChangelog(repoPath, newVersion, notes);
1375
- console.log(` ✓ CHANGELOG.md updated`);
1376
-
1377
- // 3.5. Move RELEASE-NOTES-v*.md to _trash/
1378
- const trashed = trashReleaseNotes(repoPath);
1379
- if (trashed > 0) {
1380
- console.log(` ✓ Moved ${trashed} RELEASE-NOTES file(s) to _trash/`);
1381
- }
1382
-
1383
- // 3.75. Auto-update product docs version/date
1384
- const docsUpdated = syncProductDocs(repoPath, newVersion);
1385
- if (docsUpdated > 0) {
1386
- console.log(` ✓ Product docs synced to v${newVersion} (${docsUpdated} file(s))`);
1387
- }
1388
-
1389
- // 4. Git commit + tag
1390
- gitCommitAndTag(repoPath, newVersion, notes);
1391
- console.log(` ✓ Committed and tagged v${newVersion}`);
1392
-
1393
- // 5. Push commit + tag
1394
- try {
1395
- execSync('git push && git push --tags', { cwd: repoPath, stdio: 'pipe' });
1396
- console.log(` ✓ Pushed to remote`);
1397
- } catch {
1398
- console.log(` ! Push failed (maybe branch protection). Push manually.`);
1399
- }
1400
-
1401
- // Distribution results collector (#104)
1402
- const distResults = [];
1403
-
1404
- if (!noPublish) {
1405
- // 6. npm publish
1406
- try {
1407
- publishNpm(repoPath);
1408
- const pkg = JSON.parse(readFileSync(join(repoPath, 'package.json'), 'utf8'));
1409
- distResults.push({ target: 'npm', status: 'ok', detail: `${pkg.name}@${newVersion}` });
1410
- console.log(` ✓ Published to npm`);
1411
- } catch (e) {
1412
- distResults.push({ target: 'npm', status: 'failed', detail: e.message });
1413
- console.log(` ✗ npm publish failed: ${e.message}`);
1414
- }
1415
-
1416
- // 7. GitHub Packages ... SKIPPED from private repos.
1417
- // deploy-public.sh publishes to GitHub Packages from the public repo clone.
1418
- // Publishing from private ties the package to the private repo, making it
1419
- // invisible on the public repo's Packages tab. (#53)
1420
- console.log(` - GitHub Packages: handled by deploy-public.sh (from public repo)`);
1421
-
1422
- // 8. GitHub release
1423
- try {
1424
- createGitHubRelease(repoPath, newVersion, notes, currentVersion);
1425
- distResults.push({ target: 'GitHub', status: 'ok', detail: `v${newVersion}` });
1426
- console.log(` ✓ GitHub release v${newVersion} created`);
1427
- } catch (e) {
1428
- distResults.push({ target: 'GitHub', status: 'failed', detail: e.message });
1429
- console.log(` ✗ GitHub release failed: ${e.message}`);
1430
- }
1431
-
1432
- // 9. ClawHub skill publish (root + sub-tools)
1433
- const rootSkill = join(repoPath, 'SKILL.md');
1434
- const toolsDir = join(repoPath, 'tools');
1435
-
1436
- // Publish root SKILL.md
1437
- if (existsSync(rootSkill)) {
1438
- try {
1439
- publishClawHub(repoPath, newVersion, notes);
1440
- const slug = detectSkillSlug(repoPath);
1441
- distResults.push({ target: `ClawHub`, status: 'ok', detail: `${slug}@${newVersion}` });
1442
- console.log(` ✓ Published to ClawHub: ${slug}`);
1443
- } catch (e) {
1444
- distResults.push({ target: 'ClawHub (root)', status: 'failed', detail: e.message });
1445
- console.log(` ✗ ClawHub publish failed: ${e.message}`);
1446
- }
1447
- }
1448
-
1449
- // Publish each sub-tool SKILL.md (#97)
1450
- if (existsSync(toolsDir)) {
1451
- for (const tool of readdirSync(toolsDir)) {
1452
- const toolPath = join(toolsDir, tool);
1453
- const toolSkill = join(toolPath, 'SKILL.md');
1454
- if (existsSync(toolSkill)) {
1455
- try {
1456
- publishClawHub(toolPath, newVersion, notes);
1457
- const slug = detectSkillSlug(toolPath);
1458
- distResults.push({ target: `ClawHub`, status: 'ok', detail: `${slug}@${newVersion}` });
1459
- console.log(` ✓ Published to ClawHub: ${slug}`);
1460
- } catch (e) {
1461
- const slug = detectSkillSlug(toolPath);
1462
- distResults.push({ target: `ClawHub (${slug})`, status: 'failed', detail: e.message });
1463
- console.log(` ✗ ClawHub publish failed for ${slug}: ${e.message}`);
1464
- }
1465
- }
1466
- }
1467
- }
1468
-
1469
- // 9.5. Publish SKILL.md to website as plain text
1470
- const skillWebResult = publishSkillToWebsite(repoPath);
1471
- if (skillWebResult.skipped) {
1472
- // Silent skip ... no config or env var
1473
- } else if (skillWebResult.ok) {
1474
- const deployNote = skillWebResult.deployed ? '' : ' (copied, deploy skipped)';
1475
- distResults.push({ target: 'Website', status: 'ok', detail: `install/${skillWebResult.target}.txt${deployNote}` });
1476
- console.log(` ✓ Published to website: install/${skillWebResult.target}.txt${deployNote}`);
1477
- if (!skillWebResult.deployed && skillWebResult.error) {
1478
- console.log(` ! ${skillWebResult.error}`);
1479
- }
1480
- } else {
1481
- distResults.push({ target: 'Website', status: 'failed', detail: skillWebResult.error });
1482
- console.log(` ✗ Website publish failed: ${skillWebResult.error}`);
1483
- }
1484
- }
1485
-
1486
- // Distribution summary (#104)
1487
- if (distResults.length > 0) {
1488
- console.log('');
1489
- console.log(' Distribution:');
1490
- for (const r of distResults) {
1491
- const icon = r.status === 'ok' ? '✓' : '✗';
1492
- console.log(` ${icon} ${r.target}: ${r.detail}`);
1493
- }
1494
- const failed = distResults.filter(r => r.status !== 'ok');
1495
- if (failed.length > 0) {
1496
- console.log(`\n ! ${failed.length} of ${distResults.length} target(s) failed.`);
1497
- }
1498
- }
1499
-
1500
- // 10. Post-merge branch cleanup: rename merged branches with --merged-YYYY-MM-DD
1501
- try {
1502
- const merged = execSync(
1503
- 'git branch --merged main', { cwd: repoPath, encoding: 'utf8' }
1504
- ).split('\n')
1505
- .map(b => b.trim())
1506
- .filter(b => b && b !== 'main' && b !== 'master' && !b.startsWith('*') && !b.includes('--merged-'));
1507
-
1508
- if (merged.length > 0) {
1509
- console.log(` Scanning ${merged.length} merged branch(es) for rename...`);
1510
- for (const branch of merged) {
1511
- const current = execSync('git branch --show-current', { cwd: repoPath, encoding: 'utf8' }).trim();
1512
- if (branch === current) continue;
1513
-
1514
- let mergeDate;
1515
- try {
1516
- const mergeBase = execSync(`git merge-base main ${branch}`, { cwd: repoPath, encoding: 'utf8' }).trim();
1517
- mergeDate = execSync(
1518
- `git log main --format="%ai" --ancestry-path ${mergeBase}..main`,
1519
- { cwd: repoPath, encoding: 'utf8' }
1520
- ).trim().split('\n').pop().split(' ')[0];
1521
- } catch {}
1522
- if (!mergeDate) {
1523
- try {
1524
- mergeDate = execSync(`git log ${branch} -1 --format="%ai"`, { cwd: repoPath, encoding: 'utf8' }).trim().split(' ')[0];
1525
- } catch {}
1526
- }
1527
- if (!mergeDate) continue;
1528
-
1529
- const newName = `${branch}--merged-${mergeDate}`;
1530
- try {
1531
- execSync(`git branch -m "${branch}" "${newName}"`, { cwd: repoPath, stdio: 'pipe' });
1532
- execSync(`git push origin "${newName}"`, { cwd: repoPath, stdio: 'pipe' });
1533
- execSync(`git push origin --delete "${branch}"`, { cwd: repoPath, stdio: 'pipe' });
1534
- console.log(` ✓ Renamed: ${branch} -> ${newName}`);
1535
- } catch (e) {
1536
- console.log(` ! Could not rename ${branch}: ${e.message}`);
1537
- }
1538
- }
1539
- }
1540
- } catch (e) {
1541
- // Non-fatal: branch cleanup is a convenience, not a blocker
1542
- console.log(` ! Branch cleanup skipped: ${e.message}`);
1543
- }
1544
-
1545
- // 11. Prune old merged branches (keep last 3 per developer prefix)
1546
- try {
1547
- const KEEP_COUNT = 3;
1548
- const remoteBranches = execSync(
1549
- 'git branch -r', { cwd: repoPath, encoding: 'utf8' }
1550
- ).split('\n')
1551
- .map(b => b.trim())
1552
- .filter(b => b && !b.includes('HEAD') && b.includes('--merged-'))
1553
- .map(b => b.replace('origin/', ''));
1554
-
1555
- if (remoteBranches.length > 0) {
1556
- // Group by developer prefix (everything before first /)
1557
- const byPrefix = {};
1558
- for (const branch of remoteBranches) {
1559
- const prefix = branch.split('/')[0];
1560
- if (!byPrefix[prefix]) byPrefix[prefix] = [];
1561
- byPrefix[prefix].push(branch);
1562
- }
1563
-
1564
- let pruned = 0;
1565
- for (const [prefix, branches] of Object.entries(byPrefix)) {
1566
- // Sort by date descending (date is at the end: --merged-YYYY-MM-DD)
1567
- branches.sort((a, b) => {
1568
- const dateA = a.match(/--merged-(\d{4}-\d{2}-\d{2})/)?.[1] || '';
1569
- const dateB = b.match(/--merged-(\d{4}-\d{2}-\d{2})/)?.[1] || '';
1570
- return dateB.localeCompare(dateA);
1571
- });
1572
-
1573
- for (let i = KEEP_COUNT; i < branches.length; i++) {
1574
- try {
1575
- execSync(`git push origin --delete "${branches[i]}"`, { cwd: repoPath, stdio: 'pipe' });
1576
- execSync(`git branch -d "${branches[i]}" 2>/dev/null || true`, { cwd: repoPath, stdio: 'pipe', shell: true });
1577
- pruned++;
1578
- } catch {}
1579
- }
1580
- }
1581
-
1582
- if (pruned > 0) {
1583
- console.log(` ✓ Pruned ${pruned} old merged branch(es)`);
1584
- }
1585
- }
1586
-
1587
- // Clean stale branches (merged into main but never renamed)
1588
- const current = execSync('git branch --show-current', { cwd: repoPath, encoding: 'utf8' }).trim();
1589
- const allRemote = execSync(
1590
- 'git branch -r', { cwd: repoPath, encoding: 'utf8' }
1591
- ).split('\n')
1592
- .map(b => b.trim())
1593
- .filter(b => b && !b.includes('HEAD') && !b.includes('origin/main') && !b.includes('--merged-'))
1594
- .map(b => b.replace('origin/', ''));
1595
-
1596
- let staleCleaned = 0;
1597
- for (const branch of allRemote) {
1598
- if (branch === current) continue;
1599
- try {
1600
- execSync(`git merge-base --is-ancestor origin/${branch} origin/main`, { cwd: repoPath, stdio: 'pipe' });
1601
- // If we get here, branch is fully merged
1602
- execSync(`git push origin --delete "${branch}"`, { cwd: repoPath, stdio: 'pipe' });
1603
- execSync(`git branch -d "${branch}" 2>/dev/null || true`, { cwd: repoPath, stdio: 'pipe', shell: true });
1604
- staleCleaned++;
1605
- } catch {}
1606
- }
1607
- if (staleCleaned > 0) {
1608
- console.log(` ✓ Cleaned ${staleCleaned} stale branch(es)`);
1609
- }
1610
- } catch (e) {
1611
- console.log(` ! Branch prune skipped: ${e.message}`);
1612
- }
1613
-
1614
- // 12. Prune stale worktrees (#212)
1615
- try {
1616
- execSync('git worktree prune', { cwd: repoPath, stdio: 'pipe' });
1617
- // Also check .worktrees/ for dirs whose branches are now merged
1618
- const worktreesDir = join(dirname(repoPath), '.worktrees');
1619
- if (existsSync(worktreesDir)) {
1620
- const repoBase = basename(repoPath);
1621
- const wtDirs = readdirSync(worktreesDir, { withFileTypes: true })
1622
- .filter(d => d.isDirectory() && d.name.startsWith(repoBase + '--'));
1623
- let wtPruned = 0;
1624
- for (const d of wtDirs) {
1625
- const wtPath = join(worktreesDir, d.name);
1626
- try {
1627
- // Check if branch is merged into main
1628
- const branch = execSync('git branch --show-current', {
1629
- cwd: wtPath, encoding: 'utf8', timeout: 3000
1630
- }).trim();
1631
- if (branch) {
1632
- execSync(`git merge-base --is-ancestor "${branch}" main`, {
1633
- cwd: repoPath, stdio: 'pipe', timeout: 5000
1634
- });
1635
- // Branch is merged. Remove worktree.
1636
- execSync(`git worktree remove "${wtPath}"`, { cwd: repoPath, stdio: 'pipe' });
1637
- wtPruned++;
1638
- }
1639
- } catch {} // Branch not merged or other issue, leave it
1640
- }
1641
- if (wtPruned > 0) {
1642
- console.log(` ✓ Pruned ${wtPruned} merged worktree(s) from .worktrees/`);
1643
- }
1644
- }
1645
- } catch {}
1646
-
1647
- // Write release marker so branch guard blocks immediate install (#73)
1648
- try {
1649
- const markerDir = join(process.env.HOME || '', '.ldm', 'state');
1650
- const { mkdirSync, writeFileSync } = await import('node:fs');
1651
- mkdirSync(markerDir, { recursive: true });
1652
- writeFileSync(join(markerDir, '.last-release'), JSON.stringify({
1653
- repo: repoName,
1654
- version: newVersion,
1655
- timestamp: new Date().toISOString(),
1656
- }) + '\n');
1657
- } catch {}
1658
-
1659
- console.log('');
1660
- console.log(` Done. ${repoName} v${newVersion} released.`);
1661
- console.log('');
1662
-
1663
- return { currentVersion, newVersion, dryRun: false };
1664
- }