spidersan 0.20.1 → 0.20.2

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 (310) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/bin/command-registry.d.ts +25 -0
  3. package/dist/bin/command-registry.d.ts.map +1 -0
  4. package/dist/bin/command-registry.js +29 -0
  5. package/dist/bin/command-registry.js.map +1 -0
  6. package/dist/bin/spidersan.d.ts +16 -0
  7. package/dist/bin/spidersan.d.ts.map +1 -0
  8. package/dist/bin/spidersan.js +98 -0
  9. package/dist/bin/spidersan.js.map +1 -0
  10. package/dist/commands/abandon.d.ts +8 -0
  11. package/dist/commands/abandon.d.ts.map +1 -0
  12. package/dist/commands/abandon.js +43 -0
  13. package/dist/commands/abandon.js.map +1 -0
  14. package/dist/commands/cleanup.d.ts +8 -0
  15. package/dist/commands/cleanup.d.ts.map +1 -0
  16. package/dist/commands/cleanup.js +50 -0
  17. package/dist/commands/cleanup.js.map +1 -0
  18. package/dist/commands/config.d.ts +15 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +309 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/conflicts.d.ts +34 -0
  23. package/dist/commands/conflicts.d.ts.map +1 -0
  24. package/dist/commands/conflicts.js +773 -0
  25. package/dist/commands/conflicts.js.map +1 -0
  26. package/dist/commands/context.d.ts +8 -0
  27. package/dist/commands/context.d.ts.map +1 -0
  28. package/dist/commands/context.js +104 -0
  29. package/dist/commands/context.js.map +1 -0
  30. package/dist/commands/cross-conflicts.d.ts +17 -0
  31. package/dist/commands/cross-conflicts.d.ts.map +1 -0
  32. package/dist/commands/cross-conflicts.js +273 -0
  33. package/dist/commands/cross-conflicts.js.map +1 -0
  34. package/dist/commands/depends.d.ts +11 -0
  35. package/dist/commands/depends.d.ts.map +1 -0
  36. package/dist/commands/depends.js +63 -0
  37. package/dist/commands/depends.js.map +1 -0
  38. package/dist/commands/doctor.d.ts +30 -0
  39. package/dist/commands/doctor.d.ts.map +1 -0
  40. package/dist/commands/doctor.js +558 -0
  41. package/dist/commands/doctor.js.map +1 -0
  42. package/dist/commands/git-watch.d.ts +24 -0
  43. package/dist/commands/git-watch.d.ts.map +1 -0
  44. package/dist/commands/git-watch.js +84 -0
  45. package/dist/commands/git-watch.js.map +1 -0
  46. package/dist/commands/github-sync.d.ts +42 -0
  47. package/dist/commands/github-sync.d.ts.map +1 -0
  48. package/dist/commands/github-sync.js +191 -0
  49. package/dist/commands/github-sync.js.map +1 -0
  50. package/dist/commands/index.d.ts +25 -0
  51. package/dist/commands/index.d.ts.map +1 -0
  52. package/dist/commands/index.js +29 -0
  53. package/dist/commands/index.js.map +1 -0
  54. package/dist/commands/init.d.ts +8 -0
  55. package/dist/commands/init.d.ts.map +1 -0
  56. package/dist/commands/init.js +23 -0
  57. package/dist/commands/init.js.map +1 -0
  58. package/dist/commands/list.d.ts +3 -0
  59. package/dist/commands/list.d.ts.map +1 -0
  60. package/dist/commands/list.js +45 -0
  61. package/dist/commands/list.js.map +1 -0
  62. package/dist/commands/log.d.ts +7 -0
  63. package/dist/commands/log.d.ts.map +1 -0
  64. package/dist/commands/log.js +110 -0
  65. package/dist/commands/log.js.map +1 -0
  66. package/dist/commands/merge-order.d.ts +9 -0
  67. package/dist/commands/merge-order.d.ts.map +1 -0
  68. package/dist/commands/merge-order.js +100 -0
  69. package/dist/commands/merge-order.js.map +1 -0
  70. package/dist/commands/merged.d.ts +8 -0
  71. package/dist/commands/merged.d.ts.map +1 -0
  72. package/dist/commands/merged.js +37 -0
  73. package/dist/commands/merged.js.map +1 -0
  74. package/dist/commands/pr-check.d.ts +24 -0
  75. package/dist/commands/pr-check.d.ts.map +1 -0
  76. package/dist/commands/pr-check.js +85 -0
  77. package/dist/commands/pr-check.js.map +1 -0
  78. package/dist/commands/ready-check.d.ts +11 -0
  79. package/dist/commands/ready-check.d.ts.map +1 -0
  80. package/dist/commands/ready-check.js +150 -0
  81. package/dist/commands/ready-check.js.map +1 -0
  82. package/dist/commands/rebase-helper.d.ts +3 -0
  83. package/dist/commands/rebase-helper.d.ts.map +1 -0
  84. package/dist/commands/rebase-helper.js +52 -0
  85. package/dist/commands/rebase-helper.js.map +1 -0
  86. package/dist/commands/register.d.ts +10 -0
  87. package/dist/commands/register.d.ts.map +1 -0
  88. package/dist/commands/register.js +176 -0
  89. package/dist/commands/register.js.map +1 -0
  90. package/dist/commands/registry-sync.d.ts +9 -0
  91. package/dist/commands/registry-sync.d.ts.map +1 -0
  92. package/dist/commands/registry-sync.js +129 -0
  93. package/dist/commands/registry-sync.js.map +1 -0
  94. package/dist/commands/stale.d.ts +17 -0
  95. package/dist/commands/stale.d.ts.map +1 -0
  96. package/dist/commands/stale.js +136 -0
  97. package/dist/commands/stale.js.map +1 -0
  98. package/dist/commands/sync.d.ts +21 -0
  99. package/dist/commands/sync.d.ts.map +1 -0
  100. package/dist/commands/sync.js +78 -0
  101. package/dist/commands/sync.js.map +1 -0
  102. package/dist/commands/verify-trunk.d.ts +18 -0
  103. package/dist/commands/verify-trunk.d.ts.map +1 -0
  104. package/dist/commands/verify-trunk.js +77 -0
  105. package/dist/commands/verify-trunk.js.map +1 -0
  106. package/dist/commands/watch.d.ts +8 -0
  107. package/dist/commands/watch.d.ts.map +1 -0
  108. package/dist/commands/watch.js +509 -0
  109. package/dist/commands/watch.js.map +1 -0
  110. package/dist/index.d.ts +8 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +8 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/lib/activity.d.ts +53 -0
  115. package/dist/lib/activity.d.ts.map +1 -0
  116. package/dist/lib/activity.js +271 -0
  117. package/dist/lib/activity.js.map +1 -0
  118. package/dist/lib/agent-errors.d.ts +41 -0
  119. package/dist/lib/agent-errors.d.ts.map +1 -0
  120. package/dist/lib/agent-errors.js +145 -0
  121. package/dist/lib/agent-errors.js.map +1 -0
  122. package/dist/lib/ai/context-builder.d.ts +16 -0
  123. package/dist/lib/ai/context-builder.d.ts.map +1 -0
  124. package/dist/lib/ai/context-builder.js +229 -0
  125. package/dist/lib/ai/context-builder.js.map +1 -0
  126. package/dist/lib/ai/event-handler.d.ts +21 -0
  127. package/dist/lib/ai/event-handler.d.ts.map +1 -0
  128. package/dist/lib/ai/event-handler.js +111 -0
  129. package/dist/lib/ai/event-handler.js.map +1 -0
  130. package/dist/lib/ai/index.d.ts +13 -0
  131. package/dist/lib/ai/index.d.ts.map +1 -0
  132. package/dist/lib/ai/index.js +11 -0
  133. package/dist/lib/ai/index.js.map +1 -0
  134. package/dist/lib/ai/llm-client.d.ts +37 -0
  135. package/dist/lib/ai/llm-client.d.ts.map +1 -0
  136. package/dist/lib/ai/llm-client.js +225 -0
  137. package/dist/lib/ai/llm-client.js.map +1 -0
  138. package/dist/lib/ai/reasoner.d.ts +11 -0
  139. package/dist/lib/ai/reasoner.d.ts.map +1 -0
  140. package/dist/lib/ai/reasoner.js +227 -0
  141. package/dist/lib/ai/reasoner.js.map +1 -0
  142. package/dist/lib/ai/setup.d.ts +40 -0
  143. package/dist/lib/ai/setup.d.ts.map +1 -0
  144. package/dist/lib/ai/setup.js +154 -0
  145. package/dist/lib/ai/setup.js.map +1 -0
  146. package/dist/lib/ai/types.d.ts +135 -0
  147. package/dist/lib/ai/types.d.ts.map +1 -0
  148. package/dist/lib/ai/types.js +42 -0
  149. package/dist/lib/ai/types.js.map +1 -0
  150. package/dist/lib/ast.d.ts +44 -0
  151. package/dist/lib/ast.d.ts.map +1 -0
  152. package/dist/lib/ast.js +160 -0
  153. package/dist/lib/ast.js.map +1 -0
  154. package/dist/lib/carries.d.ts +22 -0
  155. package/dist/lib/carries.d.ts.map +1 -0
  156. package/dist/lib/carries.js +56 -0
  157. package/dist/lib/carries.js.map +1 -0
  158. package/dist/lib/colony-subscriber.d.ts +56 -0
  159. package/dist/lib/colony-subscriber.d.ts.map +1 -0
  160. package/dist/lib/colony-subscriber.js +265 -0
  161. package/dist/lib/colony-subscriber.js.map +1 -0
  162. package/dist/lib/config.d.ts +62 -0
  163. package/dist/lib/config.d.ts.map +1 -0
  164. package/dist/lib/config.js +235 -0
  165. package/dist/lib/config.js.map +1 -0
  166. package/dist/lib/conflict-analyzer.d.ts +33 -0
  167. package/dist/lib/conflict-analyzer.d.ts.map +1 -0
  168. package/dist/lib/conflict-analyzer.js +114 -0
  169. package/dist/lib/conflict-analyzer.js.map +1 -0
  170. package/dist/lib/conflict-renderer.d.ts +7 -0
  171. package/dist/lib/conflict-renderer.d.ts.map +1 -0
  172. package/dist/lib/conflict-renderer.js +145 -0
  173. package/dist/lib/conflict-renderer.js.map +1 -0
  174. package/dist/lib/conflict-tier.d.ts +20 -0
  175. package/dist/lib/conflict-tier.d.ts.map +1 -0
  176. package/dist/lib/conflict-tier.js +49 -0
  177. package/dist/lib/conflict-tier.js.map +1 -0
  178. package/dist/lib/crypto.d.ts +71 -0
  179. package/dist/lib/crypto.d.ts.map +1 -0
  180. package/dist/lib/crypto.js +176 -0
  181. package/dist/lib/crypto.js.map +1 -0
  182. package/dist/lib/ecosystem-env.d.ts +33 -0
  183. package/dist/lib/ecosystem-env.d.ts.map +1 -0
  184. package/dist/lib/ecosystem-env.js +62 -0
  185. package/dist/lib/ecosystem-env.js.map +1 -0
  186. package/dist/lib/errors.d.ts +35 -0
  187. package/dist/lib/errors.d.ts.map +1 -0
  188. package/dist/lib/errors.js +71 -0
  189. package/dist/lib/errors.js.map +1 -0
  190. package/dist/lib/git-events-subscriber.d.ts +86 -0
  191. package/dist/lib/git-events-subscriber.d.ts.map +1 -0
  192. package/dist/lib/git-events-subscriber.js +870 -0
  193. package/dist/lib/git-events-subscriber.js.map +1 -0
  194. package/dist/lib/git-merge-analyzer.d.ts +38 -0
  195. package/dist/lib/git-merge-analyzer.d.ts.map +1 -0
  196. package/dist/lib/git-merge-analyzer.js +23 -0
  197. package/dist/lib/git-merge-analyzer.js.map +1 -0
  198. package/dist/lib/git.d.ts +103 -0
  199. package/dist/lib/git.d.ts.map +1 -0
  200. package/dist/lib/git.js +670 -0
  201. package/dist/lib/git.js.map +1 -0
  202. package/dist/lib/github.d.ts +151 -0
  203. package/dist/lib/github.d.ts.map +1 -0
  204. package/dist/lib/github.js +425 -0
  205. package/dist/lib/github.js.map +1 -0
  206. package/dist/lib/graph.d.ts +38 -0
  207. package/dist/lib/graph.d.ts.map +1 -0
  208. package/dist/lib/graph.js +165 -0
  209. package/dist/lib/graph.js.map +1 -0
  210. package/dist/lib/machine.d.ts +14 -0
  211. package/dist/lib/machine.d.ts.map +1 -0
  212. package/dist/lib/machine.js +38 -0
  213. package/dist/lib/machine.js.map +1 -0
  214. package/dist/lib/notify.d.ts +68 -0
  215. package/dist/lib/notify.d.ts.map +1 -0
  216. package/dist/lib/notify.js +111 -0
  217. package/dist/lib/notify.js.map +1 -0
  218. package/dist/lib/outline.d.ts +6 -0
  219. package/dist/lib/outline.d.ts.map +1 -0
  220. package/dist/lib/outline.js +60 -0
  221. package/dist/lib/outline.js.map +1 -0
  222. package/dist/lib/push-registry.d.ts +22 -0
  223. package/dist/lib/push-registry.d.ts.map +1 -0
  224. package/dist/lib/push-registry.js +21 -0
  225. package/dist/lib/push-registry.js.map +1 -0
  226. package/dist/lib/reconcile.d.ts +100 -0
  227. package/dist/lib/reconcile.d.ts.map +1 -0
  228. package/dist/lib/reconcile.js +121 -0
  229. package/dist/lib/reconcile.js.map +1 -0
  230. package/dist/lib/regex-utils.d.ts +6 -0
  231. package/dist/lib/regex-utils.d.ts.map +1 -0
  232. package/dist/lib/regex-utils.js +24 -0
  233. package/dist/lib/regex-utils.js.map +1 -0
  234. package/dist/lib/register-renderer.d.ts +10 -0
  235. package/dist/lib/register-renderer.d.ts.map +1 -0
  236. package/dist/lib/register-renderer.js +19 -0
  237. package/dist/lib/register-renderer.js.map +1 -0
  238. package/dist/lib/remote-drift.d.ts +61 -0
  239. package/dist/lib/remote-drift.d.ts.map +1 -0
  240. package/dist/lib/remote-drift.js +227 -0
  241. package/dist/lib/remote-drift.js.map +1 -0
  242. package/dist/lib/security.d.ts +72 -0
  243. package/dist/lib/security.d.ts.map +1 -0
  244. package/dist/lib/security.js +180 -0
  245. package/dist/lib/security.js.map +1 -0
  246. package/dist/lib/semantic-analysis.d.ts +31 -0
  247. package/dist/lib/semantic-analysis.d.ts.map +1 -0
  248. package/dist/lib/semantic-analysis.js +120 -0
  249. package/dist/lib/semantic-analysis.js.map +1 -0
  250. package/dist/lib/supabase-credentials.d.ts +36 -0
  251. package/dist/lib/supabase-credentials.d.ts.map +1 -0
  252. package/dist/lib/supabase-credentials.js +43 -0
  253. package/dist/lib/supabase-credentials.js.map +1 -0
  254. package/dist/lib/trunk.d.ts +39 -0
  255. package/dist/lib/trunk.d.ts.map +1 -0
  256. package/dist/lib/trunk.js +116 -0
  257. package/dist/lib/trunk.js.map +1 -0
  258. package/dist/lib/update-check.d.ts +11 -0
  259. package/dist/lib/update-check.d.ts.map +1 -0
  260. package/dist/lib/update-check.js +113 -0
  261. package/dist/lib/update-check.js.map +1 -0
  262. package/dist/lib/watch-renderer.d.ts +13 -0
  263. package/dist/lib/watch-renderer.d.ts.map +1 -0
  264. package/dist/lib/watch-renderer.js +35 -0
  265. package/dist/lib/watch-renderer.js.map +1 -0
  266. package/dist/storage/adapter.d.ts +81 -0
  267. package/dist/storage/adapter.d.ts.map +1 -0
  268. package/dist/storage/adapter.js +8 -0
  269. package/dist/storage/adapter.js.map +1 -0
  270. package/dist/storage/branch-registry-store.d.ts +13 -0
  271. package/dist/storage/branch-registry-store.d.ts.map +1 -0
  272. package/dist/storage/branch-registry-store.js +2 -0
  273. package/dist/storage/branch-registry-store.js.map +1 -0
  274. package/dist/storage/factory.d.ts +6 -0
  275. package/dist/storage/factory.d.ts.map +1 -0
  276. package/dist/storage/factory.js +14 -0
  277. package/dist/storage/factory.js.map +1 -0
  278. package/dist/storage/index.d.ts +10 -0
  279. package/dist/storage/index.d.ts.map +1 -0
  280. package/dist/storage/index.js +11 -0
  281. package/dist/storage/index.js.map +1 -0
  282. package/dist/storage/json-branch-registry-store.d.ts +19 -0
  283. package/dist/storage/json-branch-registry-store.d.ts.map +1 -0
  284. package/dist/storage/json-branch-registry-store.js +138 -0
  285. package/dist/storage/json-branch-registry-store.js.map +1 -0
  286. package/dist/storage/local.d.ts +20 -0
  287. package/dist/storage/local.d.ts.map +1 -0
  288. package/dist/storage/local.js +40 -0
  289. package/dist/storage/local.js.map +1 -0
  290. package/dist/storage/memory-branch-registry-store.d.ts +16 -0
  291. package/dist/storage/memory-branch-registry-store.d.ts.map +1 -0
  292. package/dist/storage/memory-branch-registry-store.js +68 -0
  293. package/dist/storage/memory-branch-registry-store.js.map +1 -0
  294. package/dist/storage/supabase-registry-sync-client-impl.d.ts +40 -0
  295. package/dist/storage/supabase-registry-sync-client-impl.d.ts.map +1 -0
  296. package/dist/storage/supabase-registry-sync-client-impl.js +278 -0
  297. package/dist/storage/supabase-registry-sync-client-impl.js.map +1 -0
  298. package/dist/storage/supabase-registry-sync-client.d.ts +9 -0
  299. package/dist/storage/supabase-registry-sync-client.d.ts.map +1 -0
  300. package/dist/storage/supabase-registry-sync-client.js +2 -0
  301. package/dist/storage/supabase-registry-sync-client.js.map +1 -0
  302. package/dist/storage/supabase.d.ts +28 -0
  303. package/dist/storage/supabase.d.ts.map +1 -0
  304. package/dist/storage/supabase.js +56 -0
  305. package/dist/storage/supabase.js.map +1 -0
  306. package/dist/types/cloud.d.ts +102 -0
  307. package/dist/types/cloud.d.ts.map +1 -0
  308. package/dist/types/cloud.js +13 -0
  309. package/dist/types/cloud.js.map +1 -0
  310. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carries.js","sourceRoot":"","sources":["../../src/lib/carries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAmB7C;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa,EAAE,eAAyB,EAAE;IACnF,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACD,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACxG,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IACnC,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,MAAM,SAAS,GAAsB,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjD,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEpD,IAAI,QAAQ,GAAa,EAAE,CAAC;QAC5B,IAAI,CAAC;YACD,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;iBACrF,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;iBAC7C,MAAM,CAAC,OAAO,CAAC;iBACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,kDAAkD;iBACrF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACL,oEAAoE;QACxE,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;;YAC/D,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Colony Subscriber — reads Colony in-progress signals
3
+ * and keeps the local Spidersan branch registry in sync.
4
+ *
5
+ * Design notes:
6
+ * - Queries the `colony_state` VIEW (not raw `colony_signals`) so that
7
+ * `is_stale` is already computed server-side.
8
+ * - Credentials come from COLONY_SUPABASE_URL + COLONY_SUPABASE_KEY env vars
9
+ * (the MycToak Supabase project, separate from Spidersan's own project).
10
+ * If env vars are absent, falls back to ~/.envoak/config.json + session files
11
+ * automatically (so `envoak vault login` is sufficient — no env vars needed).
12
+ * - Auth: COLONY_SESSION_JWT is required for RLS-scoped access to colony_state.
13
+ * Without it the query falls back to the anon key and will return 0 rows (RLS
14
+ * blocks unauthenticated reads of user-scoped signals).
15
+ * - Queries colony_state with status=in-progress — the status-based model
16
+ * replaces the old type=work_claim / type=work_release approach.
17
+ * - Full offline fallback: any network/auth error returns offline=true and
18
+ * the caller falls back to the local registry. Never throws.
19
+ * - Field mapping: task (branch name), files (top-level column), agent_label
20
+ * (top-level from colony_state view — no payload parsing needed).
21
+ *
22
+ * 🍄 hey treesan — the mycelium remembers. migration 025 opened the gradient.
23
+ * your spiders can smell the pheromones now. — mycsan
24
+ */
25
+ export interface ConflictReport {
26
+ branch: string;
27
+ conflictsWith: string;
28
+ files: string[];
29
+ agent?: string;
30
+ }
31
+ export interface SyncResult {
32
+ conflicts: ConflictReport[];
33
+ synced: number;
34
+ offline: boolean;
35
+ }
36
+ /**
37
+ * Resolve a human-readable agent name from a Colony agent key ID.
38
+ *
39
+ * Uses the `agent_label` field already present on `colony_state` rows.
40
+ * Falls back to a truncated UUID when no label is available.
41
+ */
42
+ export declare function resolveAgentName(agentKeyId: string, agentLabel?: string): string;
43
+ /**
44
+ * Sync the local Spidersan branch registry from Colony signals.
45
+ *
46
+ * Steps:
47
+ * 1. Query `colony_state` VIEW for in-progress signals (one per agent, deduped).
48
+ * 2. Upsert each active branch into the local registry.
49
+ * 3. Sweep: remove local active branches absent from the colony in-progress set.
50
+ * 4. Detect conflicts in the updated registry and return them.
51
+ *
52
+ * Returns `offline: true` and an empty conflicts list on any error so callers
53
+ * can display a warning and continue with existing local data.
54
+ */
55
+ export declare function syncFromColony(): Promise<SyncResult>;
56
+ //# sourceMappingURL=colony-subscriber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colony-subscriber.d.ts","sourceRoot":"","sources":["../../src/lib/colony-subscriber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AASH,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACvB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CACpB;AAmBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAIhF;AAiHD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC,CAwI1D"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Colony Subscriber — reads Colony in-progress signals
3
+ * and keeps the local Spidersan branch registry in sync.
4
+ *
5
+ * Design notes:
6
+ * - Queries the `colony_state` VIEW (not raw `colony_signals`) so that
7
+ * `is_stale` is already computed server-side.
8
+ * - Credentials come from COLONY_SUPABASE_URL + COLONY_SUPABASE_KEY env vars
9
+ * (the MycToak Supabase project, separate from Spidersan's own project).
10
+ * If env vars are absent, falls back to ~/.envoak/config.json + session files
11
+ * automatically (so `envoak vault login` is sufficient — no env vars needed).
12
+ * - Auth: COLONY_SESSION_JWT is required for RLS-scoped access to colony_state.
13
+ * Without it the query falls back to the anon key and will return 0 rows (RLS
14
+ * blocks unauthenticated reads of user-scoped signals).
15
+ * - Queries colony_state with status=in-progress — the status-based model
16
+ * replaces the old type=work_claim / type=work_release approach.
17
+ * - Full offline fallback: any network/auth error returns offline=true and
18
+ * the caller falls back to the local registry. Never throws.
19
+ * - Field mapping: task (branch name), files (top-level column), agent_label
20
+ * (top-level from colony_state view — no payload parsing needed).
21
+ *
22
+ * 🍄 hey treesan — the mycelium remembers. migration 025 opened the gradient.
23
+ * your spiders can smell the pheromones now. — mycsan
24
+ */
25
+ import { getStorage } from '../storage/index.js';
26
+ import { readFileSync, existsSync } from 'fs';
27
+ import { join } from 'path';
28
+ import { homedir } from 'os';
29
+ // ─── Agent name resolution ────────────────────────────────────────────────────
30
+ /**
31
+ * Resolve a human-readable agent name from a Colony agent key ID.
32
+ *
33
+ * Uses the `agent_label` field already present on `colony_state` rows.
34
+ * Falls back to a truncated UUID when no label is available.
35
+ */
36
+ export function resolveAgentName(agentKeyId, agentLabel) {
37
+ if (agentLabel)
38
+ return agentLabel;
39
+ if (!agentKeyId)
40
+ return 'unknown-agent';
41
+ return `agent:${agentKeyId.slice(0, 8)}`;
42
+ }
43
+ // ─── Supabase REST helpers ────────────────────────────────────────────────────
44
+ // ─── Envoak filesystem fallback ───────────────────────────────────────────────
45
+ /** Read a JSON file safely; returns null on any error (missing, malformed, mid-write). */
46
+ function readJsonSafe(filePath) {
47
+ try {
48
+ if (!existsSync(filePath))
49
+ return null;
50
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Resolve colony credentials from envoak's local session files.
58
+ *
59
+ * Resolution order:
60
+ * 1. ~/.envoak/sessions/current.json → clientSessionId
61
+ * 2. ~/.envoak/sessions/<id>.json → accessToken + expiresAt
62
+ * 3. Fallback: ~/.envoak/session.json (legacy single-session file)
63
+ *
64
+ * JWT is only used if not expired (or within 60s of expiry).
65
+ */
66
+ function resolveEnvoakCredentials() {
67
+ const envoakDir = join(homedir(), '.envoak');
68
+ const config = readJsonSafe(join(envoakDir, 'config.json'));
69
+ if (!config?.url || !config?.anonKey)
70
+ return null;
71
+ const nowMs = Date.now();
72
+ const EXPIRY_BUFFER_MS = 60_000; // reject tokens within 60s of expiry
73
+ function extractJwt(sessionData) {
74
+ if (!sessionData?.accessToken)
75
+ return null;
76
+ const exp = sessionData.expiresAt ?? 0;
77
+ if (exp && exp - nowMs < EXPIRY_BUFFER_MS) {
78
+ if (process.env.DEBUG_COLONY) {
79
+ console.warn(' [colony] envoak session JWT is expired or expiring soon — treating as offline');
80
+ }
81
+ return null;
82
+ }
83
+ return sessionData.accessToken;
84
+ }
85
+ // Try new per-session file via current.json pointer
86
+ const current = readJsonSafe(join(envoakDir, 'sessions', 'current.json'));
87
+ if (current?.clientSessionId) {
88
+ const sessFile = join(envoakDir, 'sessions', `${current.clientSessionId}.json`);
89
+ const jwt = extractJwt(readJsonSafe(sessFile));
90
+ if (process.env.DEBUG_COLONY) {
91
+ console.warn(` [colony] envoak fallback: using sessions/${current.clientSessionId}.json (jwt=${jwt ? 'ok' : 'missing/expired'})`);
92
+ }
93
+ return { url: config.url, anonKey: config.anonKey, sessionJwt: jwt };
94
+ }
95
+ // Legacy single session.json
96
+ const jwt = extractJwt(readJsonSafe(join(envoakDir, 'session.json')));
97
+ if (process.env.DEBUG_COLONY) {
98
+ console.warn(` [colony] envoak fallback: using legacy session.json (jwt=${jwt ? 'ok' : 'missing/expired'})`);
99
+ }
100
+ return { url: config.url, anonKey: config.anonKey, sessionJwt: jwt };
101
+ }
102
+ function getColonyCredentials() {
103
+ const url = process.env.COLONY_SUPABASE_URL || process.env.SUPABASE_URL;
104
+ const anonKey = process.env.COLONY_SUPABASE_KEY || process.env.SUPABASE_KEY;
105
+ // Session JWT is required for RLS — without it colony_state returns 0 rows
106
+ const sessionJwt = process.env.COLONY_SESSION_JWT || null;
107
+ if (url && anonKey)
108
+ return { url, anonKey, sessionJwt };
109
+ // Fall back to envoak's local session files when env vars aren't set
110
+ return resolveEnvoakCredentials();
111
+ }
112
+ async function fetchColonySignals(url, anonKey, sessionJwt, query) {
113
+ const endpoint = `${url}/rest/v1/${query}`;
114
+ // Use session JWT for Authorization when available — anon key alone is blocked by RLS
115
+ const authToken = sessionJwt ?? anonKey;
116
+ const response = await fetch(endpoint, {
117
+ headers: {
118
+ apikey: anonKey,
119
+ Authorization: `Bearer ${authToken}`,
120
+ 'Content-Type': 'application/json',
121
+ },
122
+ });
123
+ if (!response.ok) {
124
+ const text = await response.text();
125
+ throw new Error(`Colony query failed (${response.status}): ${text}`);
126
+ }
127
+ return (await response.json());
128
+ }
129
+ function isStale(row) {
130
+ // Prefer the view-computed flag when present
131
+ if (row.is_stale !== undefined)
132
+ return !!row.is_stale;
133
+ if (!row.stale_after_ms)
134
+ return false;
135
+ const age = Date.now() - new Date(row.updated_at).getTime();
136
+ return age > row.stale_after_ms;
137
+ }
138
+ // ─── Core sync logic ──────────────────────────────────────────────────────────
139
+ /**
140
+ * Sync the local Spidersan branch registry from Colony signals.
141
+ *
142
+ * Steps:
143
+ * 1. Query `colony_state` VIEW for in-progress signals (one per agent, deduped).
144
+ * 2. Upsert each active branch into the local registry.
145
+ * 3. Sweep: remove local active branches absent from the colony in-progress set.
146
+ * 4. Detect conflicts in the updated registry and return them.
147
+ *
148
+ * Returns `offline: true` and an empty conflicts list on any error so callers
149
+ * can display a warning and continue with existing local data.
150
+ */
151
+ export async function syncFromColony() {
152
+ const creds = getColonyCredentials();
153
+ if (!creds) {
154
+ // Credentials not configured — treat as offline (not an error)
155
+ return { conflicts: [], synced: 0, offline: true };
156
+ }
157
+ if (!creds.sessionJwt) {
158
+ // Warn but continue — queries will silently return 0 rows without session auth
159
+ console.warn('⚠ COLONY_SESSION_JWT not set — colony_state RLS will block reads. Set COLONY_SESSION_JWT to enable colony sync.');
160
+ }
161
+ try {
162
+ const storage = await getStorage();
163
+ // ── 1. Fetch all in-progress signals from colony_state VIEW ──────────
164
+ //
165
+ // colony_state (not colony_signals) is the correct target:
166
+ // - already deduped (one row per agent via colony_gc)
167
+ // - is_stale computed server-side
168
+ // - agent_label, task, files are top-level columns (no payload parsing)
169
+ // - requires session JWT for RLS — anon key returns 0 rows
170
+ //
171
+ // status=in-progress is the status-based replacement for type=work_claim.
172
+ const inProgressRows = await fetchColonySignals(creds.url, creds.anonKey, creds.sessionJwt, 'colony_state?status=eq.in-progress&select=*');
173
+ // Track branch names seen in the colony so we can sweep stale local entries
174
+ const colonyBranches = new Set();
175
+ let synced = 0;
176
+ // ── 2. Upsert claimed branches into local registry ────────────────────
177
+ for (const row of inProgressRows) {
178
+ if (isStale(row))
179
+ continue;
180
+ // Branch name: top-level task column (set by register_branch signal emitter)
181
+ // Fallback to payload.branch for backwards-compat with older signal emitters
182
+ const rawPayload = row.payload
183
+ ? (typeof row.payload === 'string' ? JSON.parse(row.payload) : row.payload)
184
+ : null;
185
+ const branch = row.task || rawPayload?.branch;
186
+ if (!branch)
187
+ continue;
188
+ colonyBranches.add(branch);
189
+ // Files: top-level column (no longer inside payload)
190
+ const files = Array.isArray(row.files) ? row.files : [];
191
+ // Agent name: top-level agent_label (visible with session JWT)
192
+ const agentName = resolveAgentName(row.agent_key_id ?? '', row.agent_label ?? rawPayload?.agent);
193
+ const existing = await storage.get(branch);
194
+ if (existing) {
195
+ const merged = [...new Set([...existing.files, ...files])];
196
+ const updatedAgent = (existing.agent?.startsWith('agent:') && agentName && !agentName.startsWith('agent:'))
197
+ ? agentName
198
+ : existing.agent;
199
+ await storage.update(branch, { files: merged, agent: updatedAgent, status: 'active' });
200
+ }
201
+ else {
202
+ await storage.register({
203
+ name: branch,
204
+ files,
205
+ agent: agentName,
206
+ status: 'active',
207
+ description: `Colony claim by ${agentName}`,
208
+ });
209
+ }
210
+ synced++;
211
+ }
212
+ // ── 3. Sweep released branches ────────────────────────────────────────
213
+ //
214
+ // Only sweep branches that were synced FROM colony (have a colony-sourced
215
+ // agent description). Manually-registered local branches are left alone.
216
+ const allBranches = await storage.list();
217
+ for (const localBranch of allBranches) {
218
+ const isColonySourced = localBranch.description?.startsWith('Colony claim by') ||
219
+ localBranch.agent?.startsWith('agent:');
220
+ if (localBranch.status === 'active' && !colonyBranches.has(localBranch.name) && isColonySourced) {
221
+ await storage.unregister(localBranch.name);
222
+ }
223
+ }
224
+ // ── 4. Detect conflicts in the updated registry ───────────────────────
225
+ const postSweepBranches = await storage.list();
226
+ const activeBranches = postSweepBranches.filter(b => b.status === 'active');
227
+ const conflicts = [];
228
+ // Performance Optimization: Pre-compute sets to avoid O(N^2) memory allocations
229
+ const branchFileSets = activeBranches.map(b => new Set(b.files));
230
+ for (let i = 0; i < activeBranches.length; i++) {
231
+ const a = activeBranches[i];
232
+ const aFiles = branchFileSets[i];
233
+ for (let j = i + 1; j < activeBranches.length; j++) {
234
+ const b = activeBranches[j];
235
+ // Prioritize standard loop over .filter for short-circuit and less allocations
236
+ const overlapping = [];
237
+ for (let k = 0; k < b.files.length; k++) {
238
+ const f = b.files[k];
239
+ if (aFiles.has(f)) {
240
+ overlapping.push(f);
241
+ }
242
+ }
243
+ if (overlapping.length > 0) {
244
+ conflicts.push({
245
+ branch: a.name,
246
+ conflictsWith: b.name,
247
+ files: overlapping,
248
+ agent: a.agent,
249
+ });
250
+ }
251
+ }
252
+ }
253
+ return { conflicts, synced, offline: false };
254
+ }
255
+ catch (err) {
256
+ // Any network/auth/parse error → offline fallback
257
+ const message = err instanceof Error ? err.message : String(err);
258
+ console.warn(`⚠ Colony unreachable — conflict detection using local registry only (may be incomplete)`);
259
+ if (process.env.DEBUG_COLONY) {
260
+ console.warn(` Colony error: ${message}`);
261
+ }
262
+ return { conflicts: [], synced: 0, offline: true };
263
+ }
264
+ }
265
+ //# sourceMappingURL=colony-subscriber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colony-subscriber.js","sourceRoot":"","sources":["../../src/lib/colony-subscriber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAgC7B,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB,EAAE,UAAmB;IACpE,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,CAAC,UAAU;QAAE,OAAO,eAAe,CAAC;IACxC,OAAO,SAAS,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC;AAED,iFAAiF;AAEjF,iFAAiF;AAEjF,0FAA0F;AAC1F,SAAS,YAAY,CAAI,QAAgB;IACrC,IAAI,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QACvC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAM,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,wBAAwB;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,YAAY,CAAqC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAChG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO;QAAE,OAAO,IAAI,CAAC;IAElD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,qCAAqC;IAEtE,SAAS,UAAU,CAAC,WAAgE;QAChF,IAAI,CAAC,WAAW,EAAE,WAAW;YAAE,OAAO,IAAI,CAAC;QAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,IAAI,CAAC,CAAC;QACvC,IAAI,GAAG,IAAI,GAAG,GAAG,KAAK,GAAG,gBAAgB,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;gBAC3B,OAAO,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;YACpG,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,WAAW,CAAC,WAAW,CAAC;IACnC,CAAC;IAED,oDAAoD;IACpD,MAAM,OAAO,GAAG,YAAY,CAA+B,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC;IACxG,IAAI,OAAO,EAAE,eAAe,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,eAAe,OAAO,CAAC,CAAC;QAChF,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,8CAA8C,OAAO,CAAC,eAAe,cAAc,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC;QACvI,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;IACzE,CAAC;IAED,6BAA6B;IAC7B,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,8DAA8D,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAClH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,oBAAoB;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC5E,2EAA2E;IAC3E,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,CAAC;IAE1D,IAAI,GAAG,IAAI,OAAO;QAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAExD,qEAAqE;IACrE,OAAO,wBAAwB,EAAE,CAAC;AACtC,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC7B,GAAW,EACX,OAAe,EACf,UAAyB,EACzB,KAAa;IAEb,MAAM,QAAQ,GAAG,GAAG,GAAG,YAAY,KAAK,EAAE,CAAC;IAC3C,sFAAsF;IACtF,MAAM,SAAS,GAAG,UAAU,IAAI,OAAO,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;QACnC,OAAO,EAAE;YACL,MAAM,EAAE,OAAO;YACf,aAAa,EAAE,UAAU,SAAS,EAAE;YACpC,cAAc,EAAE,kBAAkB;SACrC;KACJ,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAsB,CAAC;AACxD,CAAC;AAED,SAAS,OAAO,CAAC,GAAoB;IACjC,6CAA6C;IAC7C,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;IACtD,IAAI,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5D,OAAO,GAAG,GAAG,GAAG,CAAC,cAAc,CAAC;AACpC,CAAC;AAED,iFAAiF;AAEjF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAChC,MAAM,KAAK,GAAG,oBAAoB,EAAE,CAAC;IACrC,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,+DAA+D;QAC/D,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACpB,+EAA+E;QAC/E,OAAO,CAAC,IAAI,CAAC,kHAAkH,CAAC,CAAC;IACrI,CAAC;IAED,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;QAEnC,wEAAwE;QACxE,EAAE;QACF,2DAA2D;QAC3D,wDAAwD;QACxD,oCAAoC;QACpC,0EAA0E;QAC1E,6DAA6D;QAC7D,EAAE;QACF,0EAA0E;QAC1E,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAC3C,KAAK,CAAC,GAAG,EACT,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,UAAU,EAChB,6CAA6C,CAChD,CAAC;QAEF,4EAA4E;QAC5E,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QACzC,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,yEAAyE;QACzE,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,GAAG,CAAC;gBAAE,SAAS;YAE3B,6EAA6E;YAC7E,6EAA6E;YAC7E,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO;gBAC1B,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;gBAC3E,CAAC,CAAC,IAAI,CAAC;YACX,MAAM,MAAM,GAAuB,GAAG,CAAC,IAAI,IAAK,UAAyC,EAAE,MAAM,CAAC;YAClG,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE3B,qDAAqD;YACrD,MAAM,KAAK,GAAa,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAElE,+DAA+D;YAC/D,MAAM,SAAS,GAAG,gBAAgB,CAC9B,GAAG,CAAC,YAAY,IAAI,EAAE,EACtB,GAAG,CAAC,WAAW,IAAK,UAAwC,EAAE,KAAK,CACtE,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,QAAQ,EAAE,CAAC;gBACX,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC3D,MAAM,YAAY,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;oBACvG,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACrB,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3F,CAAC;iBAAM,CAAC;gBACJ,MAAM,OAAO,CAAC,QAAQ,CAAC;oBACnB,IAAI,EAAE,MAAM;oBACZ,KAAK;oBACL,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,mBAAmB,SAAS,EAAE;iBAC9C,CAAC,CAAC;YACP,CAAC;YACD,MAAM,EAAE,CAAC;QACb,CAAC;QAED,yEAAyE;QACzE,EAAE;QACF,0EAA0E;QAC1E,yEAAyE;QACzE,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACzC,KAAK,MAAM,WAAW,IAAI,WAAW,EAAE,CAAC;YACpC,MAAM,eAAe,GAAG,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,iBAAiB,CAAC;gBACtD,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;YAChE,IAAI,WAAW,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,eAAe,EAAE,CAAC;gBAC9F,MAAM,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC;QACL,CAAC;QAED,yEAAyE;QACzE,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/C,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAqB,EAAE,CAAC;QAEvC,gFAAgF;QAChF,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAEjE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjD,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAE5B,+EAA+E;gBAC/E,MAAM,WAAW,GAAa,EAAE,CAAC;gBACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACrB,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAChB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACxB,CAAC;gBACL,CAAC;gBAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzB,SAAS,CAAC,IAAI,CAAC;wBACX,MAAM,EAAE,CAAC,CAAC,IAAI;wBACd,aAAa,EAAE,CAAC,CAAC,IAAI;wBACrB,KAAK,EAAE,WAAW;wBAClB,KAAK,EAAE,CAAC,CAAC,KAAK;qBACjB,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;QACL,CAAC;QAED,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAEjD,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,kDAAkD;QAClD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,0FAA0F,CAAC,CAAC;QACzG,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC;AACL,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Spidersan Configuration Loader
3
+ *
4
+ * Loads and validates .spidersanrc configuration file.
5
+ */
6
+ export interface SpidersanConfig {
7
+ ecosystem: {
8
+ enabled: boolean;
9
+ };
10
+ agent: {
11
+ name?: string;
12
+ };
13
+ autoWatch: {
14
+ enabled: boolean;
15
+ paths: string[];
16
+ quiet: boolean;
17
+ legacy: boolean;
18
+ };
19
+ readyCheck: {
20
+ enableWipDetection: boolean;
21
+ wipPatterns: string[];
22
+ excludeFiles: string[];
23
+ enableExperimentalDetection: boolean;
24
+ experimentalPatterns: string[];
25
+ enableBuildCheck: boolean;
26
+ };
27
+ conflicts: {
28
+ highSeverityPatterns: string[];
29
+ mediumSeverityPatterns: string[];
30
+ /** Repo paths scanned by `conflicts --ecosystem` (see lib/ecosystem-env.ts). */
31
+ ecosystemRepos: string[];
32
+ };
33
+ storage: {
34
+ type: 'local' | 'supabase';
35
+ environment?: 'production' | 'staging' | 'local';
36
+ supabaseUrl?: string;
37
+ supabaseKey?: string;
38
+ supabaseUrlStaging?: string;
39
+ supabaseKeyStaging?: string;
40
+ };
41
+ }
42
+ export declare const CONFIG_FILES: string[];
43
+ interface ValidationError {
44
+ path: string;
45
+ message: string;
46
+ }
47
+ export declare function getConfigPaths(basePath?: string, includeGlobal?: boolean): string[];
48
+ export declare function loadConfigWithSources(basePath?: string, options?: {
49
+ includeGlobal?: boolean;
50
+ }): Promise<{
51
+ config: SpidersanConfig;
52
+ sources: string[];
53
+ errors: ValidationError[];
54
+ }>;
55
+ export declare function loadConfig(basePath?: string): Promise<SpidersanConfig>;
56
+ export declare function deepMerge(target: any, source: any): any;
57
+ export declare function getWipPatterns(config: SpidersanConfig): RegExp[];
58
+ export declare function getExcludePatterns(config: SpidersanConfig): string[];
59
+ export declare function getHighSeverityPatterns(config: SpidersanConfig): RegExp[];
60
+ export declare function getMediumSeverityPatterns(config: SpidersanConfig): RegExp[];
61
+ export {};
62
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,eAAe;IAC5B,SAAS,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;KACpB,CAAC;IACF,KAAK,EAAE;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,UAAU,EAAE;QACR,kBAAkB,EAAE,OAAO,CAAC;QAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,YAAY,EAAE,MAAM,EAAE,CAAC;QACvB,2BAA2B,EAAE,OAAO,CAAC;QACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;QAC/B,gBAAgB,EAAE,OAAO,CAAC;KAC7B,CAAC;IACF,SAAS,EAAE;QACP,oBAAoB,EAAE,MAAM,EAAE,CAAC;QAC/B,sBAAsB,EAAE,MAAM,EAAE,CAAC;QACjC,gFAAgF;QAChF,cAAc,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF,OAAO,EAAE;QACL,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;QAC3B,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;QACjD,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;CACL;AAkCD,eAAO,MAAM,YAAY,UAAkE,CAAC;AAE5F,UAAU,eAAe;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AA4GD,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAsB,EAAE,aAAa,GAAE,OAAc,GAAG,MAAM,EAAE,CAUxG;AAED,wBAAsB,qBAAqB,CACvC,QAAQ,GAAE,MAAsB,EAChC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,OAAO,CAAC;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CA8BpF;AAED,wBAAsB,UAAU,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CAO3F;AAGD,wBAAgB,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,GAAG,CAmBvD;AAUD,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAIhE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAEpE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAIzE;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAI3E"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Spidersan Configuration Loader
3
+ *
4
+ * Loads and validates .spidersanrc configuration file.
5
+ */
6
+ import { readFile } from 'fs/promises';
7
+ import { existsSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ const DEFAULT_CONFIG = {
11
+ ecosystem: {
12
+ enabled: true,
13
+ },
14
+ agent: {
15
+ name: '',
16
+ },
17
+ autoWatch: {
18
+ enabled: false,
19
+ paths: [],
20
+ quiet: false,
21
+ legacy: false,
22
+ },
23
+ readyCheck: {
24
+ enableWipDetection: true,
25
+ wipPatterns: ['TODO', 'FIXME', 'WIP', 'HACK', 'XXX'],
26
+ excludeFiles: ['tests/**', '*.test.js', '*.test.ts', '**/*.md', '**/docs/**', '**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml'],
27
+ enableExperimentalDetection: false,
28
+ experimentalPatterns: ['experimental/', 'test-'],
29
+ enableBuildCheck: true,
30
+ },
31
+ conflicts: {
32
+ highSeverityPatterns: ['package\\.json$', 'migrations/', '\\.env', 'middleware\\.', 'route\\.ts$'],
33
+ mediumSeverityPatterns: ['components/ui/', 'lib/', 'hooks/', 'utils/'],
34
+ ecosystemRepos: [],
35
+ },
36
+ storage: {
37
+ type: 'local',
38
+ environment: 'production',
39
+ },
40
+ };
41
+ export const CONFIG_FILES = ['.spidersanrc', '.spidersanrc.json', '.spidersan.config.json'];
42
+ function validateConfig(config) {
43
+ const errors = [];
44
+ if (typeof config !== 'object' || config === null) {
45
+ errors.push({ path: '', message: 'Config must be an object' });
46
+ return errors;
47
+ }
48
+ const obj = config;
49
+ // Validate ecosystem
50
+ if (obj.ecosystem !== undefined) {
51
+ if (typeof obj.ecosystem !== 'object' || obj.ecosystem === null) {
52
+ errors.push({ path: 'ecosystem', message: 'Must be an object' });
53
+ }
54
+ else {
55
+ const eco = obj.ecosystem;
56
+ if (eco.enabled !== undefined && typeof eco.enabled !== 'boolean') {
57
+ errors.push({ path: 'ecosystem.enabled', message: 'Must be a boolean' });
58
+ }
59
+ }
60
+ }
61
+ // Validate readyCheck
62
+ if (obj.readyCheck !== undefined) {
63
+ if (typeof obj.readyCheck !== 'object' || obj.readyCheck === null) {
64
+ errors.push({ path: 'readyCheck', message: 'Must be an object' });
65
+ }
66
+ else {
67
+ const rc = obj.readyCheck;
68
+ if (rc.wipPatterns !== undefined && !Array.isArray(rc.wipPatterns)) {
69
+ errors.push({ path: 'readyCheck.wipPatterns', message: 'Must be an array of strings' });
70
+ }
71
+ if (rc.excludeFiles !== undefined && !Array.isArray(rc.excludeFiles)) {
72
+ errors.push({ path: 'readyCheck.excludeFiles', message: 'Must be an array of strings' });
73
+ }
74
+ if (rc.enableWipDetection !== undefined && typeof rc.enableWipDetection !== 'boolean') {
75
+ errors.push({ path: 'readyCheck.enableWipDetection', message: 'Must be a boolean' });
76
+ }
77
+ }
78
+ }
79
+ // Validate conflicts.ecosystemRepos
80
+ if (obj.conflicts !== undefined && typeof obj.conflicts === 'object' && obj.conflicts !== null) {
81
+ const cf = obj.conflicts;
82
+ if (cf.ecosystemRepos !== undefined) {
83
+ if (!Array.isArray(cf.ecosystemRepos) || !cf.ecosystemRepos.every((p) => typeof p === 'string')) {
84
+ errors.push({ path: 'conflicts.ecosystemRepos', message: 'Must be an array of strings' });
85
+ }
86
+ }
87
+ }
88
+ // Validate agent
89
+ if (obj.agent !== undefined) {
90
+ if (typeof obj.agent !== 'object' || obj.agent === null) {
91
+ errors.push({ path: 'agent', message: 'Must be an object' });
92
+ }
93
+ else {
94
+ const agent = obj.agent;
95
+ if (agent.name !== undefined && typeof agent.name !== 'string') {
96
+ errors.push({ path: 'agent.name', message: 'Must be a string' });
97
+ }
98
+ }
99
+ }
100
+ // Validate autoWatch
101
+ if (obj.autoWatch !== undefined) {
102
+ if (typeof obj.autoWatch !== 'object' || obj.autoWatch === null) {
103
+ errors.push({ path: 'autoWatch', message: 'Must be an object' });
104
+ }
105
+ else {
106
+ const aw = obj.autoWatch;
107
+ if (aw.enabled !== undefined && typeof aw.enabled !== 'boolean') {
108
+ errors.push({ path: 'autoWatch.enabled', message: 'Must be a boolean' });
109
+ }
110
+ if (aw.paths !== undefined) {
111
+ if (!Array.isArray(aw.paths) || !aw.paths.every((p) => typeof p === 'string')) {
112
+ errors.push({ path: 'autoWatch.paths', message: 'Must be an array of strings' });
113
+ }
114
+ }
115
+ // autoWatch.hub / autoWatch.hubSync were dropped with the Hub
116
+ // transport (sp-hnjf). validateConfig only checks the keys it knows,
117
+ // so an existing .spidersanrc carrying them stays valid and inert.
118
+ if (aw.quiet !== undefined && typeof aw.quiet !== 'boolean') {
119
+ errors.push({ path: 'autoWatch.quiet', message: 'Must be a boolean' });
120
+ }
121
+ if (aw.legacy !== undefined && typeof aw.legacy !== 'boolean') {
122
+ errors.push({ path: 'autoWatch.legacy', message: 'Must be a boolean' });
123
+ }
124
+ }
125
+ }
126
+ // Validate storage
127
+ if (obj.storage !== undefined) {
128
+ if (typeof obj.storage !== 'object' || obj.storage === null) {
129
+ errors.push({ path: 'storage', message: 'Must be an object' });
130
+ }
131
+ else {
132
+ const st = obj.storage;
133
+ if (st.type !== undefined && !['local', 'supabase'].includes(st.type)) {
134
+ errors.push({ path: 'storage.type', message: 'Must be "local" or "supabase"' });
135
+ }
136
+ if (st.environment !== undefined && !['production', 'staging', 'local'].includes(st.environment)) {
137
+ errors.push({ path: 'storage.environment', message: 'Must be "production", "staging", or "local"' });
138
+ }
139
+ }
140
+ }
141
+ return errors;
142
+ }
143
+ export function getConfigPaths(basePath = process.cwd(), includeGlobal = true) {
144
+ const paths = [];
145
+ if (includeGlobal) {
146
+ const home = homedir();
147
+ CONFIG_FILES.forEach((filename) => paths.push(join(home, filename)));
148
+ }
149
+ CONFIG_FILES.forEach((filename) => paths.push(join(basePath, filename)));
150
+ return paths;
151
+ }
152
+ export async function loadConfigWithSources(basePath = process.cwd(), options = {}) {
153
+ const includeGlobal = options.includeGlobal !== false;
154
+ const sources = [];
155
+ const errors = [];
156
+ let merged = DEFAULT_CONFIG;
157
+ const configPaths = getConfigPaths(basePath, includeGlobal);
158
+ for (const configPath of configPaths) {
159
+ if (!existsSync(configPath))
160
+ continue;
161
+ try {
162
+ const content = await readFile(configPath, 'utf-8');
163
+ const userConfig = JSON.parse(content);
164
+ const validationErrors = validateConfig(userConfig);
165
+ if (validationErrors.length > 0) {
166
+ errors.push(...validationErrors.map(err => ({ ...err, path: `${configPath}:${err.path || ''}`.replace(/:$/, '') })));
167
+ }
168
+ merged = deepMerge(merged, userConfig);
169
+ sources.push(configPath);
170
+ }
171
+ catch (error) {
172
+ if (error instanceof SyntaxError) {
173
+ errors.push({ path: configPath, message: `Invalid JSON: ${error.message}` });
174
+ }
175
+ else {
176
+ errors.push({ path: configPath, message: 'Failed to read config file' });
177
+ }
178
+ }
179
+ }
180
+ return { config: merged, sources, errors };
181
+ }
182
+ export async function loadConfig(basePath = process.cwd()) {
183
+ const result = await loadConfigWithSources(basePath);
184
+ if (result.errors.length > 0) {
185
+ console.warn('⚠️ Config validation warnings:');
186
+ result.errors.forEach(e => console.warn(` ${e.path}: ${e.message}`));
187
+ }
188
+ return result.config;
189
+ }
190
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
191
+ export function deepMerge(target, source) {
192
+ const result = { ...target };
193
+ for (const key of Object.keys(source)) {
194
+ // Security: Prevent prototype pollution
195
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
196
+ throw new Error(`Invalid config key: ${key}`);
197
+ }
198
+ if (source[key] !== undefined) {
199
+ if (typeof source[key] === 'object' && !Array.isArray(source[key]) && source[key] !== null) {
200
+ result[key] = deepMerge(result[key] || {}, source[key]);
201
+ }
202
+ else {
203
+ result[key] = source[key];
204
+ }
205
+ }
206
+ }
207
+ return result;
208
+ }
209
+ function safeRegExp(pattern, flags) {
210
+ try {
211
+ return new RegExp(pattern, flags);
212
+ }
213
+ catch {
214
+ return null;
215
+ }
216
+ }
217
+ export function getWipPatterns(config) {
218
+ return config.readyCheck.wipPatterns
219
+ .map(p => safeRegExp(`\\b${p}\\b`, 'i'))
220
+ .filter((r) => r !== null);
221
+ }
222
+ export function getExcludePatterns(config) {
223
+ return config.readyCheck.excludeFiles;
224
+ }
225
+ export function getHighSeverityPatterns(config) {
226
+ return config.conflicts.highSeverityPatterns
227
+ .map(p => safeRegExp(p))
228
+ .filter((r) => r !== null);
229
+ }
230
+ export function getMediumSeverityPatterns(config) {
231
+ return config.conflicts.mediumSeverityPatterns
232
+ .map(p => safeRegExp(p))
233
+ .filter((r) => r !== null);
234
+ }
235
+ //# sourceMappingURL=config.js.map