@xhulz/nina 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/bin/nina.mjs +222 -48
  2. package/package.json +1 -1
  3. package/releases/0.35.0/core/GAPS.md +125 -0
  4. package/releases/0.35.0/core/answered.json +29 -0
  5. package/releases/0.35.0/core/defaults/tree/.claude/agents/architect.md +1 -0
  6. package/releases/0.35.0/core/defaults/tree/.claude/agents/dba.md +3 -0
  7. package/releases/0.35.0/core/defaults/tree/.claude/agents/devops.md +1 -0
  8. package/releases/0.35.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
  9. package/releases/0.35.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
  10. package/releases/0.35.0/core/defaults/tree/.claude/agents/qa.md +2 -0
  11. package/releases/0.35.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
  12. package/releases/0.35.0/core/defaults/tree/.claude/agents/secops.md +3 -0
  13. package/releases/0.35.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
  14. package/releases/0.35.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
  15. package/releases/0.35.0/core/tree/.claude/agents/architect.md +127 -0
  16. package/releases/0.35.0/core/tree/.claude/agents/dba.md +110 -0
  17. package/releases/0.35.0/core/tree/.claude/agents/devops.md +114 -0
  18. package/releases/0.35.0/core/tree/.claude/agents/implementer.md +156 -0
  19. package/releases/0.35.0/core/tree/.claude/agents/integration-tester.md +168 -0
  20. package/releases/0.35.0/core/tree/.claude/agents/planner.md +132 -0
  21. package/releases/0.35.0/core/tree/.claude/agents/qa.md +153 -0
  22. package/releases/0.35.0/core/tree/.claude/agents/reviewer.md +183 -0
  23. package/releases/0.35.0/core/tree/.claude/agents/secops.md +121 -0
  24. package/releases/0.35.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
  25. package/releases/0.35.0/core/tree/.claude/agents/solidity-dev.md +123 -0
  26. package/releases/0.35.0/core/tree/.claude/agents-overview.md +64 -0
  27. package/releases/0.35.0/core/tree/.claude/frontend.md +10 -0
  28. package/releases/0.35.0/core/tree/.claude/graph.md +75 -0
  29. package/releases/0.35.0/core/tree/.claude/patterns.md +213 -0
  30. package/releases/0.35.0/core/tree/.claude/pills/README.md +146 -0
  31. package/releases/0.35.0/core/tree/.claude/pipeline.md +101 -0
  32. package/releases/0.35.0/core/tree/.claude/retrieval.md +103 -0
  33. package/releases/0.35.0/core/tree/.claude/router.md +198 -0
  34. package/releases/0.35.0/core/tree/.claude/templates/integration.md +45 -0
  35. package/releases/0.35.0/core/tree/CLAUDE.md +161 -0
  36. package/releases/0.35.0/core/tree/scripts/cost-watch.mjs +18 -0
  37. package/releases/0.35.0/core/tree/scripts/edit-guard.mjs +16 -0
  38. package/releases/0.35.0/core/tree/scripts/harness-check.mjs +71 -0
  39. package/releases/0.35.0/core/tree/scripts/loop-gate.mjs +19 -0
  40. package/releases/0.35.0/core/vocabulary.json +13 -0
  41. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
  42. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
  43. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
  44. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
  45. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
  46. package/releases/0.35.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
  47. package/releases/0.35.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
  48. package/releases/0.35.0/surfaces/blockchain/tree/.claude/router.md +6 -0
  49. package/releases/0.35.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
  50. package/releases/0.35.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
  51. package/releases/0.35.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
  52. package/releases/0.35.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
  53. package/releases/0.35.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
  54. package/releases/0.35.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
  55. package/releases/0.35.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
  56. package/releases/0.35.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
  57. package/releases/0.35.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
  58. package/releases/0.35.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
  59. package/releases/0.35.0/surfaces/db/tree/.claude/graph.md +8 -0
  60. package/releases/0.35.0/surfaces/db/tree/.claude/patterns.md +19 -0
  61. package/releases/0.35.0/surfaces/db/tree/.claude/pipeline.md +13 -0
  62. package/releases/0.35.0/surfaces/db/tree/.claude/retrieval.md +5 -0
  63. package/releases/0.35.0/surfaces/db/tree/.claude/router.md +4 -0
  64. package/releases/0.35.0/surfaces/db/tree/CLAUDE.md +17 -0
  65. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
  66. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
  67. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
  68. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
  69. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
  70. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
  71. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
  72. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
  73. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
  74. package/releases/0.35.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
  75. package/releases/0.35.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
  76. package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
  77. package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
  78. package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
  79. package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
  80. package/releases/0.35.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
  81. package/releases/0.35.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
  82. package/releases/0.35.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
  83. package/releases/0.35.0/surfaces/frontend/tree/.claude/router.md +14 -0
  84. package/releases/0.35.0/surfaces/frontend/tree/CLAUDE.md +5 -0
  85. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
  86. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
  87. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
  88. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
  89. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
  90. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
  91. package/releases/0.35.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
  92. package/releases/0.35.0/surfaces/integrations/tree/.claude/graph.md +10 -0
  93. package/releases/0.35.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
  94. package/releases/0.35.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
  95. package/releases/0.35.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
  96. package/releases/0.35.0/surfaces/integrations/tree/.claude/router.md +6 -0
  97. package/releases/0.35.0/surfaces/integrations/tree/CLAUDE.md +17 -0
  98. package/releases/0.35.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
  99. package/releases/0.35.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
  100. package/releases/0.35.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
  101. package/releases/0.35.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
  102. package/releases/0.35.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
  103. package/releases/0.35.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
  104. package/releases/0.35.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
  105. package/releases/0.35.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
  106. package/releases/0.35.0/surfaces/money/tree/.claude/graph.md +2 -0
  107. package/releases/0.35.0/surfaces/money/tree/.claude/patterns.md +49 -0
  108. package/releases/0.35.0/surfaces/money/tree/.claude/pipeline.md +2 -0
  109. package/releases/0.35.0/surfaces/money/tree/.claude/retrieval.md +2 -0
  110. package/releases/0.35.0/surfaces/money/tree/CLAUDE.md +11 -0
  111. package/releases/0.35.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
  112. package/releases/0.35.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
  113. package/releases/0.35.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
  114. package/releases/0.35.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
  115. package/releases/0.35.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
  116. package/releases/0.35.0/surfaces/pii/tree/CLAUDE.md +5 -0
  117. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
  118. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
  119. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
  120. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
  121. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
  122. package/releases/0.35.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
  123. package/releases/0.35.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
  124. package/releases/0.35.0/surfaces/prisma/tree/CLAUDE.md +5 -0
  125. package/releases/0.36.0/core/GAPS.md +125 -0
  126. package/releases/0.36.0/core/answered.json +29 -0
  127. package/releases/0.36.0/core/defaults/tree/.claude/agents/architect.md +1 -0
  128. package/releases/0.36.0/core/defaults/tree/.claude/agents/dba.md +3 -0
  129. package/releases/0.36.0/core/defaults/tree/.claude/agents/devops.md +1 -0
  130. package/releases/0.36.0/core/defaults/tree/.claude/agents/implementer.md +1 -0
  131. package/releases/0.36.0/core/defaults/tree/.claude/agents/integration-tester.md +3 -0
  132. package/releases/0.36.0/core/defaults/tree/.claude/agents/qa.md +2 -0
  133. package/releases/0.36.0/core/defaults/tree/.claude/agents/reviewer.md +3 -0
  134. package/releases/0.36.0/core/defaults/tree/.claude/agents/secops.md +3 -0
  135. package/releases/0.36.0/core/defaults/tree/.claude/agents/solidity-auditor.md +3 -0
  136. package/releases/0.36.0/core/defaults/tree/.claude/agents/solidity-dev.md +3 -0
  137. package/releases/0.36.0/core/tree/.claude/agents/architect.md +127 -0
  138. package/releases/0.36.0/core/tree/.claude/agents/dba.md +110 -0
  139. package/releases/0.36.0/core/tree/.claude/agents/devops.md +114 -0
  140. package/releases/0.36.0/core/tree/.claude/agents/implementer.md +156 -0
  141. package/releases/0.36.0/core/tree/.claude/agents/integration-tester.md +168 -0
  142. package/releases/0.36.0/core/tree/.claude/agents/planner.md +132 -0
  143. package/releases/0.36.0/core/tree/.claude/agents/qa.md +153 -0
  144. package/releases/0.36.0/core/tree/.claude/agents/reviewer.md +183 -0
  145. package/releases/0.36.0/core/tree/.claude/agents/secops.md +121 -0
  146. package/releases/0.36.0/core/tree/.claude/agents/solidity-auditor.md +126 -0
  147. package/releases/0.36.0/core/tree/.claude/agents/solidity-dev.md +123 -0
  148. package/releases/0.36.0/core/tree/.claude/agents-overview.md +64 -0
  149. package/releases/0.36.0/core/tree/.claude/frontend.md +10 -0
  150. package/releases/0.36.0/core/tree/.claude/graph.md +75 -0
  151. package/releases/0.36.0/core/tree/.claude/patterns.md +213 -0
  152. package/releases/0.36.0/core/tree/.claude/pills/README.md +146 -0
  153. package/releases/0.36.0/core/tree/.claude/pipeline.md +101 -0
  154. package/releases/0.36.0/core/tree/.claude/retrieval.md +103 -0
  155. package/releases/0.36.0/core/tree/.claude/router.md +198 -0
  156. package/releases/0.36.0/core/tree/.claude/templates/integration.md +45 -0
  157. package/releases/0.36.0/core/tree/CLAUDE.md +161 -0
  158. package/releases/0.36.0/core/tree/scripts/cost-watch.mjs +18 -0
  159. package/releases/0.36.0/core/tree/scripts/edit-guard.mjs +16 -0
  160. package/releases/0.36.0/core/tree/scripts/harness-check.mjs +71 -0
  161. package/releases/0.36.0/core/tree/scripts/loop-gate.mjs +19 -0
  162. package/releases/0.36.0/core/vocabulary.json +13 -0
  163. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/architect.md +5 -0
  164. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/devops.md +5 -0
  165. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/reviewer.md +5 -0
  166. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/solidity-auditor.md +18 -0
  167. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents/solidity-dev.md +16 -0
  168. package/releases/0.36.0/surfaces/blockchain/tree/.claude/agents-overview.md +6 -0
  169. package/releases/0.36.0/surfaces/blockchain/tree/.claude/graph.md +11 -0
  170. package/releases/0.36.0/surfaces/blockchain/tree/.claude/router.md +6 -0
  171. package/releases/0.36.0/surfaces/blockchain/tree/CLAUDE.md +12 -0
  172. package/releases/0.36.0/surfaces/db/tree/.claude/agents/architect.md +5 -0
  173. package/releases/0.36.0/surfaces/db/tree/.claude/agents/dba.md +50 -0
  174. package/releases/0.36.0/surfaces/db/tree/.claude/agents/devops.md +5 -0
  175. package/releases/0.36.0/surfaces/db/tree/.claude/agents/implementer.md +2 -0
  176. package/releases/0.36.0/surfaces/db/tree/.claude/agents/integration-tester.md +10 -0
  177. package/releases/0.36.0/surfaces/db/tree/.claude/agents/planner.md +2 -0
  178. package/releases/0.36.0/surfaces/db/tree/.claude/agents/reviewer.md +22 -0
  179. package/releases/0.36.0/surfaces/db/tree/.claude/agents/secops.md +2 -0
  180. package/releases/0.36.0/surfaces/db/tree/.claude/agents-overview.md +5 -0
  181. package/releases/0.36.0/surfaces/db/tree/.claude/graph.md +8 -0
  182. package/releases/0.36.0/surfaces/db/tree/.claude/patterns.md +19 -0
  183. package/releases/0.36.0/surfaces/db/tree/.claude/pipeline.md +13 -0
  184. package/releases/0.36.0/surfaces/db/tree/.claude/retrieval.md +5 -0
  185. package/releases/0.36.0/surfaces/db/tree/.claude/router.md +4 -0
  186. package/releases/0.36.0/surfaces/db/tree/CLAUDE.md +17 -0
  187. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/architect.md +14 -0
  188. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/dba.md +2 -0
  189. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/devops.md +32 -0
  190. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/implementer.md +14 -0
  191. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/integration-tester.md +11 -0
  192. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/qa.md +3 -0
  193. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/reviewer.md +8 -0
  194. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/agents/secops.md +8 -0
  195. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/patterns.md +17 -0
  196. package/releases/0.36.0/surfaces/edge-cf/tree/.claude/retrieval.md +8 -0
  197. package/releases/0.36.0/surfaces/edge-cf/tree/CLAUDE.md +27 -0
  198. package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/architect.md +20 -0
  199. package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/devops.md +28 -0
  200. package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/implementer.md +25 -0
  201. package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/qa.md +17 -0
  202. package/releases/0.36.0/surfaces/frontend/tree/.claude/agents/reviewer.md +56 -0
  203. package/releases/0.36.0/surfaces/frontend/tree/.claude/patterns.md +8 -0
  204. package/releases/0.36.0/surfaces/frontend/tree/.claude/retrieval.md +2 -0
  205. package/releases/0.36.0/surfaces/frontend/tree/.claude/router.md +14 -0
  206. package/releases/0.36.0/surfaces/frontend/tree/CLAUDE.md +5 -0
  207. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/architect.md +16 -0
  208. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/implementer.md +12 -0
  209. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/integration-tester.md +20 -0
  210. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/planner.md +2 -0
  211. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/reviewer.md +21 -0
  212. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents/secops.md +2 -0
  213. package/releases/0.36.0/surfaces/integrations/tree/.claude/agents-overview.md +8 -0
  214. package/releases/0.36.0/surfaces/integrations/tree/.claude/graph.md +10 -0
  215. package/releases/0.36.0/surfaces/integrations/tree/.claude/patterns.md +38 -0
  216. package/releases/0.36.0/surfaces/integrations/tree/.claude/pipeline.md +16 -0
  217. package/releases/0.36.0/surfaces/integrations/tree/.claude/retrieval.md +16 -0
  218. package/releases/0.36.0/surfaces/integrations/tree/.claude/router.md +6 -0
  219. package/releases/0.36.0/surfaces/integrations/tree/CLAUDE.md +17 -0
  220. package/releases/0.36.0/surfaces/money/tree/.claude/agents/architect.md +12 -0
  221. package/releases/0.36.0/surfaces/money/tree/.claude/agents/dba.md +14 -0
  222. package/releases/0.36.0/surfaces/money/tree/.claude/agents/implementer.md +11 -0
  223. package/releases/0.36.0/surfaces/money/tree/.claude/agents/integration-tester.md +3 -0
  224. package/releases/0.36.0/surfaces/money/tree/.claude/agents/reviewer.md +23 -0
  225. package/releases/0.36.0/surfaces/money/tree/.claude/agents/secops.md +5 -0
  226. package/releases/0.36.0/surfaces/money/tree/.claude/agents/solidity-auditor.md +4 -0
  227. package/releases/0.36.0/surfaces/money/tree/.claude/agents/solidity-dev.md +4 -0
  228. package/releases/0.36.0/surfaces/money/tree/.claude/graph.md +2 -0
  229. package/releases/0.36.0/surfaces/money/tree/.claude/patterns.md +49 -0
  230. package/releases/0.36.0/surfaces/money/tree/.claude/pipeline.md +2 -0
  231. package/releases/0.36.0/surfaces/money/tree/.claude/retrieval.md +2 -0
  232. package/releases/0.36.0/surfaces/money/tree/CLAUDE.md +11 -0
  233. package/releases/0.36.0/surfaces/pii/tree/.claude/agents/dba.md +2 -0
  234. package/releases/0.36.0/surfaces/pii/tree/.claude/agents/devops.md +8 -0
  235. package/releases/0.36.0/surfaces/pii/tree/.claude/agents/reviewer.md +8 -0
  236. package/releases/0.36.0/surfaces/pii/tree/.claude/agents/secops.md +2 -0
  237. package/releases/0.36.0/surfaces/pii/tree/.claude/agents/solidity-auditor.md +5 -0
  238. package/releases/0.36.0/surfaces/pii/tree/CLAUDE.md +5 -0
  239. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/architect.md +2 -0
  240. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/dba.md +39 -0
  241. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/devops.md +11 -0
  242. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/implementer.md +2 -0
  243. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/integration-tester.md +2 -0
  244. package/releases/0.36.0/surfaces/prisma/tree/.claude/agents/reviewer.md +2 -0
  245. package/releases/0.36.0/surfaces/prisma/tree/.claude/patterns.md +15 -0
  246. package/releases/0.36.0/surfaces/prisma/tree/CLAUDE.md +5 -0
  247. package/src/agentrun.mjs +89 -9
  248. package/src/commands/check.mjs +12 -8
  249. package/src/commands/compose.mjs +85 -9
  250. package/src/commands/export.mjs +8 -16
  251. package/src/commands/gate.mjs +19 -13
  252. package/src/commands/init.mjs +13 -4
  253. package/src/commands/learn.mjs +17 -18
  254. package/src/commands/pipeline.mjs +4 -4
  255. package/src/commands/release.mjs +21 -3
  256. package/src/commands/runs.mjs +14 -8
  257. package/src/commands/snapshot.mjs +63 -64
  258. package/src/commands/stats.mjs +98 -30
  259. package/src/commands/status.mjs +2 -2
  260. package/src/commands/upgrade.mjs +131 -25
  261. package/src/guard.mjs +7 -37
  262. package/src/paths.mjs +50 -1
  263. package/src/prices.mjs +7 -7
  264. package/src/store.mjs +158 -0
  265. package/src/transcripts.mjs +15 -4
  266. package/src/vocabulary.mjs +12 -1
  267. package/src/wiring.mjs +106 -41
package/src/wiring.mjs CHANGED
@@ -205,21 +205,77 @@ function groupsFor(hooks, event) {
205
205
  return Array.isArray(hooks[event]) ? hooks[event] : null;
206
206
  }
207
207
 
208
+ /** Whether one hook command runs a hook's script, recognised by what it runs, not by its exact text. */
209
+ function runsCommand(x, h) {
210
+ const cmd = String(x?.command ?? '');
211
+ return cmd.includes(h.script) && (!h.mode || cmd.includes(h.mode));
212
+ }
213
+
214
+ /** Whether a settings group runs a hook's script. */
215
+ function runs(g, h) {
216
+ return Boolean(g) && typeof g === 'object' && Array.isArray(g.hooks) && g.hooks.some((x) => runsCommand(x, h));
217
+ }
218
+
219
+ /** A matcher that reaches every tool: none, empty, or `*`. */
220
+ const everyTool = (m) => m === undefined || m === null || m === '' || m === '*';
221
+
222
+ /** A matcher this can read and rewrite: every tool, or a list of exact names. A regular expression is its owner's. */
223
+ const plainMatcher = (m) => everyTool(m) || (typeof m === 'string' && /^[A-Za-z0-9_|]+$/.test(m));
224
+
225
+ /** Whether two matchers reach a tool in common — unknown for a regular expression, taken as no. */
226
+ function overlaps(a, b) {
227
+ if (everyTool(a) || everyTool(b)) return true;
228
+ if (!plainMatcher(a) || !plainMatcher(b)) return false;
229
+ const names = new Set(a.split('|'));
230
+ return b.split('|').some((n) => names.has(n));
231
+ }
232
+
233
+ /** Whether two of these groups run on a tool they share, so the hook runs once per group there. */
234
+ const doubled = (groups) => groups.some((g, i) => groups.slice(i + 1).some((other) => overlaps(g.matcher, other.matcher)));
235
+
208
236
  /**
209
237
  * Whether settings already run a hook. Recognised by what the command runs, not by its exact text —
210
238
  * a project may have written its own — and by a matcher that reaches every tool the hook needs.
211
239
  */
212
240
  function covered(hooks, h) {
213
- const groups = groupsFor(hooks, h.event) ?? [];
214
241
  const need = h.matcher ? h.matcher.split('|') : [];
215
- return groups.some((g) => {
216
- if (!g || typeof g !== 'object') return false;
217
- if (!need.every((tool) => matcherReaches(g.matcher, tool))) return false;
218
- return Array.isArray(g.hooks) && g.hooks.some((x) => {
219
- const cmd = String(x?.command ?? '');
220
- return cmd.includes(h.script) && (!h.mode || cmd.includes(h.mode));
221
- });
222
- });
242
+ return (groupsFor(hooks, h.event) ?? []).some((g) => runs(g, h) && need.every((tool) => matcherReaches(g.matcher, tool)));
243
+ }
244
+
245
+ /**
246
+ * The hooks a project runs, from both settings files merged by event — Claude Code runs both, so a hook
247
+ * kept in the local file counts. Every reader asks this one: `wire` used to read the shared file alone,
248
+ * and appended a second copy of each hook a project kept in its local file, which then ran twice.
249
+ *
250
+ * @param {string} target - The project directory.
251
+ * @param {(event: string) => boolean} [wanted] - Events whose malformed lists are worth a problem.
252
+ * @returns {Promise<{merged: Record<string, object[]>, problems: string[]}>} Each merged group says `from` which file.
253
+ */
254
+ async function projectHooks(target, wanted = () => false) {
255
+ const merged = {};
256
+ const problems = [];
257
+ for (const rel of SETTINGS_FILES) {
258
+ const path = join(target, rel);
259
+ if (!existsSync(path)) continue;
260
+ let settings;
261
+ try {
262
+ settings = JSON.parse(await readFile(path, 'utf8'));
263
+ } catch (error) {
264
+ problems.push(`${rel} is not valid JSON — ${error.message}`);
265
+ continue;
266
+ }
267
+ const shape = settings?.hooks;
268
+ if (shape === undefined || shape === null) continue;
269
+ if (typeof shape !== 'object' || Array.isArray(shape)) {
270
+ problems.push(`${rel} has a "hooks" that is not an object of event lists — no hook in it can run`);
271
+ continue;
272
+ }
273
+ for (const [event, groups] of Object.entries(shape)) {
274
+ if (Array.isArray(groups)) (merged[event] ??= []).push(...groups.map((g) => (g && typeof g === 'object' ? { ...g, from: rel } : g)));
275
+ else if (wanted(event)) problems.push(`${rel}'s hooks.${event} is not a list — no hook in it can run`);
276
+ }
277
+ }
278
+ return { merged, problems };
223
279
  }
224
280
 
225
281
  /** The command settings run for a hook, when they run one — the selftest runs it the same way. */
@@ -299,29 +355,16 @@ export async function missingWiring(target, shipped) {
299
355
  }
300
356
  const wanted = HOOKS.filter((h) => shipped.has(h.script));
301
357
  if (wanted.length === 0) return out;
302
- const merged = {};
303
- for (const rel of SETTINGS_FILES) {
304
- const path = join(target, rel);
305
- if (!existsSync(path)) continue;
306
- let settings;
307
- try {
308
- settings = JSON.parse(await readFile(path, 'utf8'));
309
- } catch (error) {
310
- out.push(`${rel} is not valid JSON — ${error.message}`);
311
- continue;
312
- }
313
- const shape = settings?.hooks;
314
- if (shape === undefined || shape === null) continue;
315
- if (typeof shape !== 'object' || Array.isArray(shape)) {
316
- out.push(`${rel} has a "hooks" that is not an object of event lists — no hook in it can run`);
317
- continue;
318
- }
319
- for (const [event, groups] of Object.entries(shape)) {
320
- if (Array.isArray(groups)) (merged[event] ??= []).push(...groups);
321
- else if (wanted.some((h) => h.event === event)) out.push(`${rel}'s hooks.${event} is not a list — no hook in it can run`);
322
- }
323
- }
358
+ const { merged, problems } = await projectHooks(target, (event) => wanted.some((h) => h.event === event));
359
+ out.push(...problems);
324
360
  for (const h of wanted) {
361
+ const running = (merged[h.event] ?? []).filter((g) => runs(g, h));
362
+ if (doubled(running)) {
363
+ out.push(
364
+ `${running.length} ${h.event} groups run \`${h.script}${h.mode ? ` ${h.mode}` : ''}\` for tools they share, so it runs once per group there — ` +
365
+ '`nina wire --apply` makes them one',
366
+ );
367
+ }
325
368
  if (covered(merged, h)) continue;
326
369
  out.push(
327
370
  `.claude/settings.json has no ${h.event} hook${h.matcher ? ` for ${h.matcher}` : ''} running \`${h.script}${h.mode ? ` ${h.mode}` : ''}\` — without it ${h.why}`,
@@ -359,13 +402,9 @@ export async function staleHooks(target, shipped) {
359
402
  * @returns {Promise<string|null>} Null when nothing is missing.
360
403
  */
361
404
  export async function missingFragment(target, shipped) {
362
- let settings = null;
363
- try {
364
- settings = JSON.parse(await readFile(join(target, '.claude', 'settings.json'), 'utf8'));
365
- } catch {
366
- // Absent or unreadable: everything is missing, and `missingWiring` says which.
367
- }
368
- const lacking = HOOKS.filter((h) => shipped.has(h.script) && !covered(settings?.hooks, h));
405
+ // Absent or unreadable files hold nothing: everything they would have held is missing, and `missingWiring` says why.
406
+ const { merged } = await projectHooks(target);
407
+ const lacking = HOOKS.filter((h) => shipped.has(h.script) && !covered(merged, h));
369
408
  return lacking.length === 0 ? null : JSON.stringify({ hooks: settingsHooks(lacking) }, null, 2);
370
409
  }
371
410
 
@@ -405,10 +444,36 @@ export async function applyWiring(target, shipped, { settings: editSettings = tr
405
444
  if (readable) {
406
445
  const hooks = settings.hooks ?? {};
407
446
  const added = [];
447
+ const { merged } = await projectHooks(target);
408
448
  for (const h of HOOKS.filter((h) => shipped.has(h.script))) {
409
- if (covered(hooks, h)) continue;
410
- (hooks[h.event] ??= []).push(group(h));
411
- added.push(`${h.event}${h.matcher ? ` (${h.matcher})` : ''} → ${h.script}${h.mode ? ` ${h.mode}` : ''}`);
449
+ const running = (merged[h.event] ?? []).filter((g) => runs(g, h));
450
+ if (covered(merged, h) && !doubled(running)) continue;
451
+ const named = `${h.event}${h.matcher ? ` (${h.matcher})` : ''} → ${h.script}${h.mode ? ` ${h.mode}` : ''}`;
452
+ if (running.length === 0) {
453
+ (hooks[h.event] ??= []).push(group(h));
454
+ added.push(named);
455
+ continue;
456
+ }
457
+ // The groups that already run the script become one that reaches every tool it needs. A second group
458
+ // beside a narrower one — or two left as they were — runs it on the tools they share once per group, and
459
+ // the gate counts each of those events twice. A group in the local file, or one matched by a regular
460
+ // expression, is its owner's to change: said, and not doubled.
461
+ const foreign = running.find((g) => g.from !== '.claude/settings.json' || !plainMatcher(g.matcher));
462
+ if (foreign) {
463
+ problems.push(
464
+ `${foreign.from} runs ${h.script} for "${foreign.matcher ?? ''}" — make every group that runs it there one, reaching ${h.matcher ?? 'every tool'}; ` +
465
+ 'another group beside it would run it twice',
466
+ );
467
+ continue;
468
+ }
469
+ const mine = (hooks[h.event] ?? []).filter((g) => runs(g, h));
470
+ const keep = mine.find((g) => everyTool(g.matcher)) ?? mine[0];
471
+ if (!everyTool(keep.matcher)) {
472
+ keep.matcher = [...new Set([...mine.flatMap((g) => g.matcher.split('|')), ...(h.matcher ? h.matcher.split('|') : [])])].join('|');
473
+ }
474
+ for (const g of mine) if (g !== keep) g.hooks = g.hooks.filter((x) => !runsCommand(x, h));
475
+ hooks[h.event] = hooks[h.event].filter((g) => !Array.isArray(g?.hooks) || g.hooks.length > 0);
476
+ added.push(`${named} (${mine.length > 1 ? `${mine.length} groups made one, ` : ''}reaching ${everyTool(keep.matcher) ? 'every tool' : keep.matcher})`);
412
477
  }
413
478
  // An old command, exactly as it was written, learns to say when its script cannot start, and how to
414
479
  // install NINA as it is installed now.