@bugmole/cli 0.4.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 (308) hide show
  1. package/.bugmole.env.example +20 -0
  2. package/LICENSE +7 -0
  3. package/README.md +293 -0
  4. package/TESTING.md +117 -0
  5. package/bugmole.config.yaml +39 -0
  6. package/package.json +85 -0
  7. package/scripts/billing/paypal-setup.mjs +121 -0
  8. package/scripts/bugmole-continue.ts +318 -0
  9. package/scripts/bugmole-init.ts +188 -0
  10. package/scripts/bugmole.cjs +17 -0
  11. package/scripts/bugmole.test.ts +344 -0
  12. package/scripts/bugmole.ts +657 -0
  13. package/scripts/ensure-maestro.cjs +79 -0
  14. package/scripts/ios-tunnel-keeper.sh +45 -0
  15. package/scripts/ios-wda-keeper.sh +66 -0
  16. package/scripts/sync-plan-catalog.d.mts +3 -0
  17. package/scripts/sync-plan-catalog.mjs +16 -0
  18. package/scripts/ui-parity-diff.py +65 -0
  19. package/scripts/ui-parity-requirements.txt +1 -0
  20. package/scripts/verify-manage-to-plans.mts +194 -0
  21. package/spec/app-ui-audit.schema.json +176 -0
  22. package/spec/blockers.yaml +79 -0
  23. package/spec/bugs.index.json +42 -0
  24. package/spec/design-dna.schema.json +38 -0
  25. package/spec/domain_rules.yaml +24 -0
  26. package/spec/flows/flow_manage-to-plans-64c3c61b.yaml +8 -0
  27. package/spec/flows/flow_screen-to-evidence-6c3ab309.yaml +7 -0
  28. package/spec/journey_graph.yaml +126 -0
  29. package/spec/journeys.graph.json +2618 -0
  30. package/spec/plans/dashboard-smoke.flow.yaml +20 -0
  31. package/spec/plans/example.flow.yaml +99 -0
  32. package/spec/plans/flow_api-keys-to-logout-7396cd5d.flow.yaml +33 -0
  33. package/spec/plans/flow_api-keys-to-screen-157e10a6.flow.yaml +33 -0
  34. package/spec/plans/flow_manage-to-audits-176c1eb8.flow.yaml +33 -0
  35. package/spec/plans/flow_manage-to-blockers-633282c8.flow.yaml +112 -0
  36. package/spec/plans/flow_manage-to-devices-ad57e202.flow.yaml +33 -0
  37. package/spec/plans/flow_manage-to-logout-86c54656.flow.yaml +33 -0
  38. package/spec/plans/flow_manage-to-manage-resource-action-6325f99a.flow.yaml +185 -0
  39. package/spec/plans/flow_manage-to-parity-issues-01fa2579.flow.yaml +34 -0
  40. package/spec/plans/flow_manage-to-plans-64c3c61b.flow.yaml +123 -0
  41. package/spec/plans/flow_manage-to-screen-6857f915.flow.yaml +106 -0
  42. package/spec/plans/flow_manage-to-tasks-c5791c95.flow.yaml +33 -0
  43. package/spec/plans/flow_profile-to-screen-6045aa3d.flow.yaml +33 -0
  44. package/spec/plans/flow_register-to-api-auth-login-460a9cc8.flow.yaml +34 -0
  45. package/spec/plans/flow_screen-to-audits-07666356.flow.yaml +33 -0
  46. package/spec/plans/flow_screen-to-blockers-091d258b.flow.yaml +33 -0
  47. package/spec/plans/flow_screen-to-devices-cad72f75.flow.yaml +33 -0
  48. package/spec/plans/flow_screen-to-evidence-6c3ab309.flow.yaml +126 -0
  49. package/spec/plans/flow_screen-to-parity-issues-2218e3ad.flow.yaml +34 -0
  50. package/spec/plans/flow_screen-to-plans-8232a94f.flow.yaml +33 -0
  51. package/spec/plans/flow_screen-to-tasks-540671d1.flow.yaml +33 -0
  52. package/spec/plans/login.flow.yaml +22 -0
  53. package/spec/plans/owner-operations.flow.yaml +20 -0
  54. package/spec/project_config.yaml +55 -0
  55. package/spec/roles.yaml +30 -0
  56. package/spec/schema.md +394 -0
  57. package/spec/test-case-results.schema.json +62 -0
  58. package/spec/test-cases.schema.json +85 -0
  59. package/spec/ui-parity-audit.schema.json +194 -0
  60. package/spec/ui-reverse-engineering.schema.json +94 -0
  61. package/src/billing/plan-catalog.test.ts +46 -0
  62. package/src/billing/plan-catalog.ts +199 -0
  63. package/src/integrations/aws-sigv4.test.ts +42 -0
  64. package/src/integrations/aws-sigv4.ts +72 -0
  65. package/src/integrations/device-farm.ts +155 -0
  66. package/src/integrations/github-app.test.ts +57 -0
  67. package/src/integrations/github-app.ts +143 -0
  68. package/src/integrations/gitlab.ts +81 -0
  69. package/src/integrations/temp-email.test.ts +123 -0
  70. package/src/integrations/temp-email.ts +175 -0
  71. package/src/integrations/testflight-feedback.test.ts +51 -0
  72. package/src/integrations/testflight-feedback.ts +173 -0
  73. package/src/integrations/webdriver-client.ts +131 -0
  74. package/src/mcp/server.test.ts +1220 -0
  75. package/src/mcp/server.ts +3064 -0
  76. package/src/mcp/write-test-cases.test.ts +287 -0
  77. package/src/registry/api-key-client.ts +39 -0
  78. package/src/registry/control-plane-client.ts +212 -0
  79. package/src/registry/migrations/0001_registry.sql +47 -0
  80. package/src/registry/migrations/0002_device_authorizations.sql +23 -0
  81. package/src/registry/migrations/0003_project_environments.sql +25 -0
  82. package/src/registry/migrations/0004_device_authorization_email.sql +1 -0
  83. package/src/registry/migrations/0005_testing_control_plane.sql +55 -0
  84. package/src/registry/migrations/0006_workspaces.sql +36 -0
  85. package/src/registry/migrations/0007_project_apps.sql +26 -0
  86. package/src/registry/migrations/0008_agent_tasks.sql +30 -0
  87. package/src/registry/migrations/0009_journey_revisions.sql +17 -0
  88. package/src/registry/migrations/0010_agent_task_journey.sql +2 -0
  89. package/src/registry/migrations/0011_run_journey_revision.sql +1 -0
  90. package/src/registry/migrations/0012_canonical_flow_execution.sql +10 -0
  91. package/src/registry/migrations/0013_device_sessions.sql +22 -0
  92. package/src/registry/migrations/0014_agent_task_step.sql +1 -0
  93. package/src/registry/migrations/0015_agent_task_attempts.sql +6 -0
  94. package/src/registry/migrations/0016_github_issue_tracker.sql +54 -0
  95. package/src/registry/migrations/0017_run_targets.sql +7 -0
  96. package/src/registry/migrations/0018_run_fix_from.sql +4 -0
  97. package/src/registry/migrations/0019_workspace_flags.sql +9 -0
  98. package/src/registry/migrations/0020_orgs.sql +40 -0
  99. package/src/registry/migrations/0021_billing_core.sql +58 -0
  100. package/src/registry/migrations/0022_cloud_runners.sql +19 -0
  101. package/src/registry/migrations/0023_signup.sql +4 -0
  102. package/src/registry/migrations/0024_billing.sql +67 -0
  103. package/src/registry/migrations/0025_notifications.sql +47 -0
  104. package/src/registry/migrations/0026_repo_bindings.sql +28 -0
  105. package/src/registry/migrations/0027_feedback.sql +29 -0
  106. package/src/registry/migrations/0028_devices.sql +48 -0
  107. package/src/registry/migrations/0029_sso.sql +31 -0
  108. package/src/registry/migrations/0030_workspace_domains.sql +18 -0
  109. package/src/registry/migrations/0031_gitlab_and_teams.sql +45 -0
  110. package/src/registry/migrations/0032_personas.sql +15 -0
  111. package/src/registry/migrations/0033_bugmole_rename.sql +11 -0
  112. package/src/registry/task-scheduling.test.ts +100 -0
  113. package/src/registry/task-scheduling.ts +80 -0
  114. package/src/registry-worker/ai/platform-model.ts +77 -0
  115. package/src/registry-worker/ai/routes.test.ts +88 -0
  116. package/src/registry-worker/ai/routes.ts +90 -0
  117. package/src/registry-worker/artifacts.test.ts +98 -0
  118. package/src/registry-worker/artifacts.ts +85 -0
  119. package/src/registry-worker/billing/billing-core.test.ts +175 -0
  120. package/src/registry-worker/billing/checkout-routes.ts +209 -0
  121. package/src/registry-worker/billing/enforcement.ts +69 -0
  122. package/src/registry-worker/billing/entitlements.ts +108 -0
  123. package/src/registry-worker/billing/ledger.ts +186 -0
  124. package/src/registry-worker/billing/paypal/api.ts +259 -0
  125. package/src/registry-worker/billing/paypal/client.ts +91 -0
  126. package/src/registry-worker/billing/paypal/provider.ts +143 -0
  127. package/src/registry-worker/billing/paypal.test.ts +466 -0
  128. package/src/registry-worker/billing/provider.ts +114 -0
  129. package/src/registry-worker/billing/routes.ts +66 -0
  130. package/src/registry-worker/billing/subscriptions.ts +780 -0
  131. package/src/registry-worker/billing/thresholds.ts +107 -0
  132. package/src/registry-worker/core.ts +308 -0
  133. package/src/registry-worker/devices/devices.test.ts +185 -0
  134. package/src/registry-worker/devices/policy.ts +71 -0
  135. package/src/registry-worker/devices/routes.ts +453 -0
  136. package/src/registry-worker/domains/domains.test.ts +210 -0
  137. package/src/registry-worker/domains/routes.ts +139 -0
  138. package/src/registry-worker/domains.ts +88 -0
  139. package/src/registry-worker/email/sender.ts +75 -0
  140. package/src/registry-worker/env.d.ts +14716 -0
  141. package/src/registry-worker/features.ts +20 -0
  142. package/src/registry-worker/feedback/feedback.test.ts +230 -0
  143. package/src/registry-worker/feedback/format.ts +148 -0
  144. package/src/registry-worker/feedback/routes.ts +386 -0
  145. package/src/registry-worker/flags.ts +39 -0
  146. package/src/registry-worker/github/checks.test.ts +177 -0
  147. package/src/registry-worker/github/checks.ts +374 -0
  148. package/src/registry-worker/gitlab/checks.test.ts +141 -0
  149. package/src/registry-worker/gitlab/checks.ts +349 -0
  150. package/src/registry-worker/hooks.ts +54 -0
  151. package/src/registry-worker/index.ts +2077 -0
  152. package/src/registry-worker/jobs/index.ts +29 -0
  153. package/src/registry-worker/jobs/retention.ts +68 -0
  154. package/src/registry-worker/mcp/mcp.test.ts +355 -0
  155. package/src/registry-worker/mcp/routes.ts +215 -0
  156. package/src/registry-worker/mcp/token.ts +126 -0
  157. package/src/registry-worker/mcp/tools.ts +563 -0
  158. package/src/registry-worker/notifications/alerts.ts +212 -0
  159. package/src/registry-worker/notifications/notifications.test.ts +298 -0
  160. package/src/registry-worker/notifications/outbox.ts +83 -0
  161. package/src/registry-worker/notifications/routes.ts +280 -0
  162. package/src/registry-worker/notifications/secrets.ts +49 -0
  163. package/src/registry-worker/notifications/slack.ts +96 -0
  164. package/src/registry-worker/notifications/teams.ts +46 -0
  165. package/src/registry-worker/org/audit.ts +116 -0
  166. package/src/registry-worker/org/routes.test.ts +163 -0
  167. package/src/registry-worker/org/routes.ts +302 -0
  168. package/src/registry-worker/personas/personas.test.ts +78 -0
  169. package/src/registry-worker/personas/routes.ts +100 -0
  170. package/src/registry-worker/repo-triggers.ts +20 -0
  171. package/src/registry-worker/routes/index.ts +74 -0
  172. package/src/registry-worker/run-events.ts +24 -0
  173. package/src/registry-worker/runner/dispatch.ts +219 -0
  174. package/src/registry-worker/runner/jobs.ts +43 -0
  175. package/src/registry-worker/runner/metering.ts +82 -0
  176. package/src/registry-worker/runner/policy.ts +59 -0
  177. package/src/registry-worker/runner/routes.ts +171 -0
  178. package/src/registry-worker/runner/runner.test.ts +358 -0
  179. package/src/registry-worker/runner/tokens.ts +93 -0
  180. package/src/registry-worker/runs.test.ts +60 -0
  181. package/src/registry-worker/signup/policy.ts +57 -0
  182. package/src/registry-worker/signup/routes.ts +106 -0
  183. package/src/registry-worker/signup/signup.test.ts +81 -0
  184. package/src/registry-worker/sso/aegis.ts +141 -0
  185. package/src/registry-worker/sso/membership.ts +157 -0
  186. package/src/registry-worker/sso/routes.ts +458 -0
  187. package/src/registry-worker/sso/sso.test.ts +344 -0
  188. package/src/registry-worker/testing/d1-shim.ts +180 -0
  189. package/src/registry-worker/testing/harness.ts +137 -0
  190. package/src/runner-worker/index.ts +108 -0
  191. package/src/runtime/ai-analysis.ts +97 -0
  192. package/src/runtime/ai-exploration.test.ts +32 -0
  193. package/src/runtime/ai-exploration.ts +69 -0
  194. package/src/runtime/ai-repair.ts +74 -0
  195. package/src/runtime/ai-work.test.ts +99 -0
  196. package/src/runtime/android-screen-record.test.ts +75 -0
  197. package/src/runtime/android-screen-record.ts +192 -0
  198. package/src/runtime/app-understanding.test.ts +123 -0
  199. package/src/runtime/app-understanding.ts +201 -0
  200. package/src/runtime/appium-driver.test.ts +179 -0
  201. package/src/runtime/appium-driver.ts +295 -0
  202. package/src/runtime/blocker-resolution.test.ts +113 -0
  203. package/src/runtime/blocker-resolution.ts +111 -0
  204. package/src/runtime/browser-matrix.integration.test.ts +212 -0
  205. package/src/runtime/browser-matrix.test.ts +143 -0
  206. package/src/runtime/browser-matrix.ts +200 -0
  207. package/src/runtime/canonical-flow.test.ts +52 -0
  208. package/src/runtime/config-validate.ts +185 -0
  209. package/src/runtime/continuous-execution.ts +291 -0
  210. package/src/runtime/cursor-applescript.ts +573 -0
  211. package/src/runtime/cursor-cli-driver.test.ts +78 -0
  212. package/src/runtime/cursor-cli-driver.ts +156 -0
  213. package/src/runtime/cursor-driver-example.ts +117 -0
  214. package/src/runtime/cursor-driver-index.ts +65 -0
  215. package/src/runtime/cursor-driver-init.ts +277 -0
  216. package/src/runtime/cursor-driver-run.test.ts +15 -0
  217. package/src/runtime/cursor-driver-run.ts +323 -0
  218. package/src/runtime/cursor-driver.ts +332 -0
  219. package/src/runtime/cursor-llm-example.ts +90 -0
  220. package/src/runtime/cursor-llm.ts +206 -0
  221. package/src/runtime/cursor-mcp-monitor.ts +386 -0
  222. package/src/runtime/device-clouds/browserstack.ts +73 -0
  223. package/src/runtime/device-clouds/device-farm.ts +52 -0
  224. package/src/runtime/device-clouds/index.ts +92 -0
  225. package/src/runtime/device-clouds/kobiton.ts +70 -0
  226. package/src/runtime/device-clouds/targets.ts +44 -0
  227. package/src/runtime/device-clouds/types.ts +62 -0
  228. package/src/runtime/diff-proposal.ts +84 -0
  229. package/src/runtime/discovery-task.test.ts +29 -0
  230. package/src/runtime/discovery-task.ts +284 -0
  231. package/src/runtime/driver-recovery.ts +69 -0
  232. package/src/runtime/driver.ts +79 -0
  233. package/src/runtime/environment.test.ts +104 -0
  234. package/src/runtime/environment.ts +137 -0
  235. package/src/runtime/executor.test.ts +509 -0
  236. package/src/runtime/executor.ts +921 -0
  237. package/src/runtime/explorer.test.ts +101 -0
  238. package/src/runtime/explorer.ts +1013 -0
  239. package/src/runtime/failure-analysis.test.ts +111 -0
  240. package/src/runtime/failure-analysis.ts +272 -0
  241. package/src/runtime/fixtures/fake-maestro.sh +36 -0
  242. package/src/runtime/flow-language.test.ts +268 -0
  243. package/src/runtime/flow-language.ts +414 -0
  244. package/src/runtime/init-wizard.ts +354 -0
  245. package/src/runtime/ios-screen-record.test.ts +68 -0
  246. package/src/runtime/ios-screen-record.ts +155 -0
  247. package/src/runtime/journey-editor.ts +452 -0
  248. package/src/runtime/journey-evidence.test.ts +161 -0
  249. package/src/runtime/journey-evidence.ts +180 -0
  250. package/src/runtime/journey-graph.test.ts +257 -0
  251. package/src/runtime/journey-graph.ts +170 -0
  252. package/src/runtime/legacy-names.ts +32 -0
  253. package/src/runtime/llm-example.ts +105 -0
  254. package/src/runtime/llm.ts +527 -0
  255. package/src/runtime/local-browser.test.ts +45 -0
  256. package/src/runtime/local-browser.ts +48 -0
  257. package/src/runtime/local-registry-stub.test.ts +325 -0
  258. package/src/runtime/local-registry-stub.ts +803 -0
  259. package/src/runtime/maestro-driver.test.ts +84 -0
  260. package/src/runtime/maestro-driver.ts +209 -0
  261. package/src/runtime/mole-voice.ts +21 -0
  262. package/src/runtime/nav-crawl.test.ts +100 -0
  263. package/src/runtime/nav-crawl.ts +153 -0
  264. package/src/runtime/pipeline.test.ts +405 -0
  265. package/src/runtime/pipeline.ts +833 -0
  266. package/src/runtime/planner.test.ts +37 -0
  267. package/src/runtime/planner.ts +274 -0
  268. package/src/runtime/platform-ai.ts +76 -0
  269. package/src/runtime/playwright-driver.test.ts +93 -0
  270. package/src/runtime/playwright-driver.ts +620 -0
  271. package/src/runtime/project-spec.ts +140 -0
  272. package/src/runtime/record-run-verdicts.ts +68 -0
  273. package/src/runtime/reporter.test.ts +56 -0
  274. package/src/runtime/reporter.ts +158 -0
  275. package/src/runtime/reset.test.ts +44 -0
  276. package/src/runtime/reset.ts +61 -0
  277. package/src/runtime/reviewer.test.ts +73 -0
  278. package/src/runtime/reviewer.ts +158 -0
  279. package/src/runtime/run-job.ts +136 -0
  280. package/src/runtime/run-once.test.ts +207 -0
  281. package/src/runtime/run-once.ts +168 -0
  282. package/src/runtime/run.ts +132 -0
  283. package/src/runtime/screen-recording.ts +34 -0
  284. package/src/runtime/serve-gateway.test.ts +74 -0
  285. package/src/runtime/serve-gateway.ts +164 -0
  286. package/src/runtime/serve-worker.test.ts +23 -0
  287. package/src/runtime/serve-worker.ts +278 -0
  288. package/src/runtime/site-discovery.test.ts +168 -0
  289. package/src/runtime/site-discovery.ts +308 -0
  290. package/src/runtime/target-runner.ts +144 -0
  291. package/src/runtime/test-case-verdicts.test.ts +94 -0
  292. package/src/runtime/test-case-verdicts.ts +120 -0
  293. package/src/runtime/ui-reverse-engineering/coordinator.test.ts +59 -0
  294. package/src/runtime/ui-reverse-engineering/coordinator.ts +391 -0
  295. package/src/runtime/ui-reverse-engineering/types.ts +197 -0
  296. package/src/runtime/web-suite.test.ts +97 -0
  297. package/src/runtime/web-suite.ts +176 -0
  298. package/src/storage/create-object-store.ts +144 -0
  299. package/src/storage/keys.ts +34 -0
  300. package/src/storage/local-artifact-server.test.ts +314 -0
  301. package/src/storage/local-artifact-server.ts +357 -0
  302. package/src/storage/object-store.test.ts +28 -0
  303. package/src/storage/object-store.ts +101 -0
  304. package/src/storage/registry-object-store.ts +88 -0
  305. package/src/storage/remote-object-store.ts +104 -0
  306. package/src/storage/storage-directory.test.ts +43 -0
  307. package/src/storage/storage-directory.ts +24 -0
  308. package/tsconfig.json +24 -0
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ // Creates Bugmole's PayPal product and its four billing plans (Team and
3
+ // Business, monthly and yearly) from the plan catalog, and prints the plan ids
4
+ // to set as registry vars (plan ids aren't secret).
5
+ //
6
+ // Sandbox first, then live; each environment needs its own plans. Credentials
7
+ // come from Arcana so they never reach the shell history:
8
+ //
9
+ // arcana run --secret arcana://paypal/bugmole/sandbox-client-id --env PAYPAL_CLIENT_ID -- \
10
+ // arcana run --secret arcana://paypal/bugmole/sandbox-client-secret --env PAYPAL_CLIENT_SECRET -- \
11
+ // env PAYPAL_ENV=sandbox node scripts/billing/paypal-setup.mjs
12
+ //
13
+ // Set PAYPAL_PLANS=0 to skip creating plans (e.g. to add only the webhook).
14
+ // PAYPAL_PRODUCT_ID=PROD-… reuses an existing product. Running it twice
15
+ // creates duplicate plans (PayPal has no "ensure"); deactivate extras in the
16
+ // PayPal dashboard.
17
+ //
18
+ // Plan choices (from realistiz-dd's plan script):
19
+ // - total_cycles 0: renews until cancelled.
20
+ // - auto_bill_outstanding: a failed renewal is retried with the next charge.
21
+ // - payment_failure_threshold 1: one failed renewal suspends the subscription,
22
+ // which Bugmole turns into a 7-day grace period.
23
+ import { PLANS } from "../../src/billing/plan-catalog.ts";
24
+
25
+ const sandbox = process.env.PAYPAL_ENV === "sandbox";
26
+ const apiBase = sandbox ? "https://api-m.sandbox.paypal.com" : "https://api-m.paypal.com";
27
+ const { PAYPAL_CLIENT_ID: clientId, PAYPAL_CLIENT_SECRET: clientSecret } = process.env;
28
+ if (!clientId || !clientSecret) {
29
+ console.error("Set PAYPAL_CLIENT_ID and PAYPAL_CLIENT_SECRET (and PAYPAL_ENV=sandbox for the sandbox).");
30
+ process.exit(1);
31
+ }
32
+
33
+ async function paypal(path, init = {}) {
34
+ const res = await fetch(`${apiBase}${path}`, init);
35
+ const text = await res.text();
36
+ if (!res.ok) throw new Error(`${init.method ?? "GET"} ${path} failed: ${res.status} ${text}`);
37
+ return text ? JSON.parse(text) : {};
38
+ }
39
+
40
+ const { access_token: token } = await paypal("/v1/oauth2/token", {
41
+ method: "POST",
42
+ headers: {
43
+ Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`,
44
+ "content-type": "application/x-www-form-urlencoded",
45
+ },
46
+ body: "grant_type=client_credentials",
47
+ });
48
+
49
+ const post = (body) => ({
50
+ method: "POST",
51
+ headers: {
52
+ Authorization: `Bearer ${token}`,
53
+ "content-type": "application/json",
54
+ Prefer: "return=representation",
55
+ "PayPal-Request-Id": crypto.randomUUID(),
56
+ },
57
+ body: JSON.stringify(body),
58
+ });
59
+
60
+ const product = process.env.PAYPAL_PRODUCT_ID
61
+ ? { id: process.env.PAYPAL_PRODUCT_ID }
62
+ : await paypal("/v1/catalogs/products", post({
63
+ name: "Bugmole",
64
+ description: "AI-powered end-to-end testing: cloud runs, AI credits and team features.",
65
+ type: "SERVICE",
66
+ category: "SOFTWARE",
67
+ home_url: "https://bugmole.com",
68
+ }));
69
+
70
+ const dollars = (cents) => (cents / 100).toFixed(2);
71
+ const lines = [];
72
+ for (const planId of process.env.PAYPAL_PLANS === "0" ? [] : ["team", "business"]) {
73
+ const plan = PLANS[planId];
74
+ for (const interval of ["month", "year"]) {
75
+ const cents = interval === "year" ? plan.priceYearlyMonthlyCents * 12 : plan.priceMonthlyCents;
76
+ const created = await paypal("/v1/billing/plans", post({
77
+ product_id: product.id,
78
+ name: `Bugmole ${plan.name} - ${interval === "year" ? "yearly" : "monthly"}`,
79
+ description: `USD ${dollars(cents)} per ${interval}, renews until cancelled. Usage beyond the allowance is invoiced monthly.`,
80
+ status: "ACTIVE",
81
+ billing_cycles: [{
82
+ frequency: { interval_unit: interval === "year" ? "YEAR" : "MONTH", interval_count: 1 },
83
+ tenure_type: "REGULAR",
84
+ sequence: 1,
85
+ total_cycles: 0,
86
+ pricing_scheme: { fixed_price: { value: dollars(cents), currency_code: "USD" } },
87
+ }],
88
+ payment_preferences: {
89
+ auto_bill_outstanding: true,
90
+ setup_fee_failure_action: "CANCEL",
91
+ payment_failure_threshold: 1,
92
+ },
93
+ }));
94
+ lines.push(`PAYPAL_PLAN_${planId.toUpperCase()}_${interval.toUpperCase()}=${created.id}`);
95
+ }
96
+ }
97
+
98
+ // PAYPAL_WEBHOOK_URL (e.g. https://api.bugmole.com/api/billing/webhooks/paypal)
99
+ // also registers the webhook; its id goes in PAYPAL_WEBHOOK_ID.
100
+ if (process.env.PAYPAL_WEBHOOK_URL) {
101
+ const hook = await paypal("/v1/notifications/webhooks", post({
102
+ url: process.env.PAYPAL_WEBHOOK_URL,
103
+ event_types: [
104
+ "BILLING.SUBSCRIPTION.ACTIVATED",
105
+ "BILLING.SUBSCRIPTION.UPDATED",
106
+ "BILLING.SUBSCRIPTION.RE-ACTIVATED",
107
+ "BILLING.SUBSCRIPTION.SUSPENDED",
108
+ "BILLING.SUBSCRIPTION.CANCELLED",
109
+ "BILLING.SUBSCRIPTION.EXPIRED",
110
+ "BILLING.SUBSCRIPTION.PAYMENT.FAILED",
111
+ "PAYMENT.SALE.COMPLETED",
112
+ "PAYMENT.SALE.REFUNDED",
113
+ "INVOICING.INVOICE.PAID",
114
+ "INVOICING.INVOICE.CANCELLED",
115
+ ].map((name) => ({ name })),
116
+ }));
117
+ lines.push(`PAYPAL_WEBHOOK_ID=${hook.id}`);
118
+ }
119
+
120
+ console.log(`PayPal ${sandbox ? "sandbox" : "LIVE"} product: ${product.id}`);
121
+ for (const line of lines) console.log(line);
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Bugmole MCP Continuation Script
3
+ *
4
+ * After initialization, this script uses Cursor LLM to:
5
+ * 1. Investigate the project structure
6
+ * 2. Detect how to start the application
7
+ * 3. Determine URLs and ports
8
+ * 4. Continue with exploration and test creation
9
+ *
10
+ * Usage:
11
+ * npm run bugmole:continue
12
+ * npm run bugmole:continue -- --project-directory /path/to/project
13
+ * npm run bugmole:continue -- --max-iterations 100
14
+ * npm run bugmole:continue -- --project-directory /path/to/project --max-iterations 100 --timeout 900000
15
+ */
16
+
17
+ import { executeContinuously } from "../src/runtime/continuous-execution.js";
18
+
19
+ function readArg(name: string): string | undefined {
20
+ const args = process.argv;
21
+ const i = args.indexOf(name);
22
+ if (i >= 0 && i + 1 < args.length) return args[i + 1];
23
+ return undefined;
24
+ }
25
+
26
+ function hasFlag(name: string): boolean {
27
+ return process.argv.includes(name);
28
+ }
29
+
30
+ /**
31
+ * Generates the continuation task that asks Cursor to investigate and continue
32
+ */
33
+ function generateContinuationTask(projectDirectory?: string): string {
34
+ return `# Bugmole MCP Continuation Task
35
+
36
+ You are continuing the Bugmole MCP setup for this project. The initial spec files have been created, and now you need to:
37
+
38
+ 1. **Investigate the project structure** to understand:
39
+ - What type of application(s) this is (monorepo, single app, etc.)
40
+ - How to start the application(s)
41
+ - What URLs/ports the applications run on
42
+ - What dependencies need to be installed or started first
43
+
44
+ 2. **Determine the base URL** for testing:
45
+ - Check package.json scripts (start, dev, etc.)
46
+ - Check configuration files (.env, config files)
47
+ - Check documentation (README.md, docs/)
48
+ - Look for port numbers in code or config
49
+ - Identify the main frontend application URL
50
+
51
+ 3. **Start the application** (if not already running):
52
+ - Determine the correct start command
53
+ - Check if services are already running on expected ports
54
+ - Use appropriate commands to start the application
55
+
56
+ 4. **Continue with exploration**:
57
+ - Once the application is running, use \`bugmole_explore\` to discover user journeys
58
+ - Update the journey graph with discovered screens and actions
59
+ - Create test plans for key user journeys
60
+
61
+ 5. **Create initial test plans**:
62
+ - Use \`bugmole_plan\` to generate test plans for discovered journeys
63
+ - Focus on critical user flows first
64
+
65
+ ## Available MCP Tools
66
+
67
+ You have access to these Bugmole MCP tools:
68
+ - \`bugmole_explore\` - Explore the application and discover user journeys (requires baseUrl)
69
+ - \`bugmole_read_spec\` - Read existing spec files
70
+ - \`bugmole_write_spec\` - Write or update spec files
71
+ - \`bugmole_plan\` - Generate journey plans from discovered journeys
72
+ - \`bugmole_report_progress\` - Report your progress periodically (use every 2-3 minutes for long tasks)
73
+
74
+ ## CRITICAL: About next_steps
75
+
76
+ When you commit your response, if you mention ANY of the following in your answer, you MUST include them in the "next_steps" array:
77
+ - "Next Steps" section
78
+ - "TODO" items
79
+ - "should do", "need to", "use bugmole_", "run bugmole_"
80
+ - Any future actions or commands
81
+
82
+ Example: If you write "Next: Run bugmole_explore with baseUrl=http://localhost:8000", then your commit MUST include:
83
+ \`\`\`json
84
+ {
85
+ "next_steps": ["Run bugmole_explore with baseUrl=http://localhost:8000"]
86
+ }
87
+ \`\`\`
88
+
89
+ ONLY omit next_steps when EVERYTHING is 100% complete and there is NO remaining work.
90
+
91
+ ## Your Investigation Steps
92
+
93
+ ### Step 1: Understand Project Structure
94
+
95
+ Analyze the codebase to determine:
96
+ - Is this a monorepo? (check for apps/, packages/, libs/ directories)
97
+ - What applications exist? (check apps/ directory or root package.json)
98
+ - What frameworks are used? (React, Next.js, Vue, Express, etc.)
99
+ - Are there multiple services? (APIs, frontends, etc.)
100
+
101
+ ### Step 2: Find How to Start the Application
102
+
103
+ Look for:
104
+ - \`package.json\` scripts (start, dev, serve, etc.)
105
+ - \`README.md\` or documentation with setup instructions
106
+ - \`.env\` files or config files with port/URL information
107
+ - Docker compose files or startup scripts
108
+ - Any existing dev scripts (scripts/dev.sh, etc.)
109
+
110
+ ### Step 3: Determine Base URL
111
+
112
+ Figure out:
113
+ - What port does the main frontend run on? (common: 3000, 3001, 5173, 8000, etc.)
114
+ - What is the full URL? (usually http://localhost:PORT)
115
+ - Are there multiple services? Which one should be tested first?
116
+ - Check for environment variables like PORT, BASE_URL, etc.
117
+
118
+ ### Step 4: Check if Application is Running
119
+
120
+ Before starting, check if services are already running:
121
+ - Try to detect running processes on expected ports
122
+ - Check if the application responds to HTTP requests
123
+ - If running, proceed to exploration
124
+ - If not running, determine how to start it
125
+
126
+ ### Step 5: Start the Application (if needed)
127
+
128
+ If the application is not running:
129
+ - Determine the correct command to start it
130
+ - Consider dependencies (databases, other services)
131
+ - Start the application in a way that allows testing
132
+
133
+ ### Step 6: Explore the Application (Optional)
134
+
135
+ **NOTE:** The \`bugmole_explore\` tool may not be fully implemented yet. If it returns an error, **do NOT keep retrying**. Instead:
136
+ - Work with existing journey graph if it exists (check spec/journeys.graph.json)
137
+ - Create test plans based on codebase analysis
138
+ - Proceed with other tasks like creating plans, reading/writing specs
139
+
140
+ If you want to try exploration:
141
+ - Use \`bugmole_explore\` with the discovered baseUrl
142
+ - Set appropriate maxDepth (start with 3-5)
143
+ - If it fails, move on immediately - don't get stuck
144
+
145
+ ### Step 7: Create Test Plans
146
+
147
+ After exploration:
148
+ - Identify key user journeys from the journey graph
149
+ - Use \`bugmole_plan\` to create test plans for important journeys
150
+ - Start with critical user flows (login, main features, etc.)
151
+
152
+ ## Important Notes
153
+
154
+ - **You have full access to the codebase** - use it to understand the project
155
+ - **Use MCP tools** - don't just read files, use the tools to interact with the framework
156
+ - **Be thorough** - investigate multiple sources (package.json, README, code, config files)
157
+ - **Start simple** - focus on the main application first, then expand
158
+ - **Document findings** - update spec files with discovered information
159
+ - **CRITICAL: Do not get stuck on exploration** - If \`bugmole_explore\` fails or returns errors, immediately move on to other productive tasks like creating test plans, reading/writing specs, or executing existing plans. Do NOT retry exploration repeatedly.
160
+
161
+ ## Project Context
162
+
163
+ ${projectDirectory ? `- Project directory: ${projectDirectory}` : "- Current working directory"}
164
+ - Spec files have been initialized in spec/ directory
165
+ - You need to figure out how to proceed from here
166
+
167
+ ## Expected Outcome
168
+
169
+ After completing this task:
170
+ - āœ… Application is running (or instructions provided on how to start it)
171
+ - āœ… Base URL is determined and documented
172
+ - āœ… Journey graph is populated with discovered screens/actions
173
+ - āœ… Initial test plans are created for key user journeys
174
+ - āœ… All findings are documented in spec files
175
+
176
+ ## Important: Next Steps
177
+
178
+ If you cannot complete all steps in a single response, you MUST include a \`next_steps\` field in your commit payload with the remaining steps. For example:
179
+
180
+ \`\`\`json
181
+ {
182
+ "status": "ok",
183
+ "summary": "Investigated project structure, need to start application",
184
+ "next_steps": [
185
+ "Start the application using npm run dev",
186
+ "Wait for application to be ready on port 3000",
187
+ "Use bugmole_explore with http://localhost:3000 to discover journeys"
188
+ ]
189
+ }
190
+ \`\`\`
191
+
192
+ The framework will automatically continue with these next steps. Only omit \`next_steps\` when the task is fully complete.
193
+
194
+ Begin by investigating the project structure and determining how to start the application.`;
195
+ }
196
+
197
+ async function main() {
198
+ const projectDirectory =
199
+ readArg("--project-directory") ||
200
+ readArg("--projectDirectory") ||
201
+ process.env.CURSOR_PROJECT_DIRECTORY;
202
+
203
+ const timeout = Number(readArg("--timeout") || "900000"); // 15 minutes default
204
+ const configPath = readArg("--config");
205
+ const maxIterations = Number(readArg("--max-iterations") || readArg("--maxIterations") || "100");
206
+
207
+ console.log("[Bugmole MCP Continue] Starting framework continuation...");
208
+ console.log(
209
+ `[Bugmole MCP Continue] Project Directory: ${projectDirectory || "(current directory)"}`,
210
+ );
211
+ console.log(`[Bugmole MCP Continue] Timeout: ${timeout}ms`);
212
+ console.log(`[Bugmole MCP Continue] Max Iterations: ${maxIterations}\n`);
213
+
214
+ // Generate continuation task
215
+ const continuationTask = generateContinuationTask(projectDirectory);
216
+
217
+ console.log("[Bugmole MCP Continue] Generated continuation task");
218
+ console.log("[Bugmole MCP Continue] Starting continuous execution loop...");
219
+ console.log(
220
+ "[Bugmole MCP Continue] Cursor will investigate and continue until complete...\n",
221
+ );
222
+
223
+ // Use continuous execution to automatically follow next_steps
224
+ const result = await executeContinuously(continuationTask, {
225
+ configPath,
226
+ timeout,
227
+ projectDirectory,
228
+ useCursor: true,
229
+ maxIterations: Number(maxIterations), // Configurable via --max-iterations flag
230
+ iterationDelay: 3000, // 3 second delay between iterations
231
+ customInstructions:
232
+ "Please thoroughly investigate the project structure, determine how to start the application, find the base URL, and continue with exploration and test creation using the MCP tools. Include next_steps in your response if there are more steps to complete.",
233
+ });
234
+
235
+ console.log("\n[Bugmole MCP Continue] Continuous execution completed\n");
236
+
237
+ if (result.success) {
238
+ console.log(`āœ… Task completed successfully in ${result.iterations} iteration(s)!`);
239
+
240
+ // Show summary of all iterations
241
+ console.log(`\n--- Execution Summary (${result.iterations} iteration(s)) ---`);
242
+ result.responses.forEach((response, index) => {
243
+ if ("payload" in response && response.payload) {
244
+ const cursorResponse = response as any;
245
+ console.log(`\nIteration ${index + 1}:`);
246
+ console.log(` Summary: ${cursorResponse.payload?.summary || "N/A"}`);
247
+ if (cursorResponse.payload?.next_steps) {
248
+ console.log(
249
+ ` Next Steps: ${cursorResponse.payload.next_steps.length} step(s) remaining`,
250
+ );
251
+ } else {
252
+ console.log(` Status: Complete (no next steps)`);
253
+ }
254
+ }
255
+ });
256
+
257
+ // Show final response details
258
+ const finalResponse = result.finalResponse;
259
+ if ("payload" in finalResponse && finalResponse.payload) {
260
+ const cursorResponse = finalResponse as any;
261
+
262
+ console.log(`\n--- Final Response ---`);
263
+ console.log(`Summary: ${cursorResponse.payload?.summary || "No summary provided"}`);
264
+
265
+ if (cursorResponse.payload?.answer_markdown) {
266
+ console.log("\n--- Full Answer ---");
267
+ console.log(cursorResponse.payload.answer_markdown);
268
+ }
269
+
270
+ if (cursorResponse.payload?.actions && cursorResponse.payload.actions.length > 0) {
271
+ console.log("\n--- Actions Performed ---");
272
+ cursorResponse.payload.actions.forEach((action: any, i: number) => {
273
+ console.log(`${i + 1}. ${action.type}: ${action.target}`);
274
+ if (action.details) {
275
+ console.log(` ${action.details}`);
276
+ }
277
+ });
278
+ }
279
+
280
+ if (cursorResponse.payload?.artifacts && cursorResponse.payload.artifacts.length > 0) {
281
+ console.log("\n--- Artifacts Generated ---");
282
+ cursorResponse.payload.artifacts.forEach((artifact: any, i: number) => {
283
+ console.log(`${i + 1}. ${artifact.type}`);
284
+ if (artifact.content) {
285
+ const preview = artifact.content.substring(0, 200);
286
+ console.log(` ${preview}${artifact.content.length > 200 ? "..." : ""}`);
287
+ }
288
+ });
289
+ }
290
+ }
291
+
292
+ console.log("\nšŸ“ Check the spec/ directory for updated files:");
293
+ console.log(" - spec/journeys.graph.json (should have discovered journeys)");
294
+ console.log(" - spec/plans/*.flow.yaml (should have test plans)");
295
+
296
+ process.exit(0);
297
+ } else {
298
+ console.error("āŒ Continuation failed!");
299
+ console.error(`Error: ${result.error}`);
300
+ console.error(`Iterations completed: ${result.iterations}`);
301
+
302
+ if (result.iterations >= Number(maxIterations)) {
303
+ console.error(
304
+ `\nšŸ’” Reached maximum iterations (${maxIterations}). The task may be too complex.`,
305
+ );
306
+ console.error(
307
+ " Consider breaking it into smaller tasks or increasing maxIterations with --max-iterations flag.",
308
+ );
309
+ }
310
+
311
+ process.exit(1);
312
+ }
313
+ }
314
+
315
+ main().catch((err) => {
316
+ console.error(`[Bugmole MCP Continue] Fatal error: ${err?.message ?? err}`);
317
+ process.exit(1);
318
+ });
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Bugmole MCP Initialization Script
4
+ *
5
+ * Uses CURSOR_DRIVER to automatically explore a project and initialize
6
+ * all required spec files using MCP tools.
7
+ *
8
+ * Usage:
9
+ * npm run bugmole:init
10
+ * npm run bugmole:init -- --base-url http://localhost:3000
11
+ * npm run bugmole:init -- --project-directory /path/to/project
12
+ */
13
+
14
+ import { executeContinuously } from "../src/runtime/continuous-execution.js";
15
+ import { generateInitTask, inferApplicationDetails } from "../src/runtime/cursor-driver-init.js";
16
+
17
+ function readArg(name: string): string | undefined {
18
+ const args = process.argv;
19
+ const i = args.indexOf(name);
20
+ if (i >= 0 && i + 1 < args.length) return args[i + 1];
21
+ return undefined;
22
+ }
23
+
24
+ function hasFlag(name: string): boolean {
25
+ return process.argv.includes(name);
26
+ }
27
+
28
+ async function main() {
29
+ // Parse arguments
30
+ const baseUrl = readArg("--base-url") || readArg("--baseUrl") || process.env.PLAYWRIGHT_BASE_URL;
31
+
32
+ const projectDirectory =
33
+ readArg("--project-directory") ||
34
+ readArg("--projectDirectory") ||
35
+ process.env.CURSOR_PROJECT_DIRECTORY;
36
+
37
+ const maxDepth = Number(readArg("--max-depth") || readArg("--maxDepth") || "5");
38
+ const force = hasFlag("--force");
39
+ const timeout = Number(readArg("--timeout") || "600000"); // 10 minutes default for init
40
+ const configPath = readArg("--config");
41
+ const maxIterations = Number(readArg("--max-iterations") || readArg("--maxIterations") || "100");
42
+
43
+ console.log("[Bugmole MCP Init] Starting framework initialization...");
44
+ console.log(
45
+ `[Bugmole MCP Init] Base URL: ${baseUrl || "(not specified, will infer from codebase)"}`,
46
+ );
47
+ console.log(
48
+ `[Bugmole MCP Init] Project Directory: ${projectDirectory || "(current directory)"}`,
49
+ );
50
+ console.log(`[Bugmole MCP Init] Max Depth: ${maxDepth}`);
51
+ console.log(`[Bugmole MCP Init] Force: ${force}`);
52
+ console.log(`[Bugmole MCP Init] Timeout: ${timeout}ms`);
53
+ console.log(`[Bugmole MCP Init] Max Iterations: ${maxIterations}`);
54
+
55
+ // Infer application details if baseUrl not provided
56
+ let inferredBaseUrl = baseUrl;
57
+ if (!inferredBaseUrl && projectDirectory) {
58
+ const details = inferApplicationDetails(projectDirectory);
59
+ if (details.baseUrl) {
60
+ inferredBaseUrl = details.baseUrl;
61
+ console.log(`[Bugmole MCP Init] Inferred base URL: ${inferredBaseUrl}`);
62
+ }
63
+ }
64
+
65
+ // Generate initialization task
66
+ const initTask = generateInitTask({
67
+ baseUrl: inferredBaseUrl,
68
+ maxDepth,
69
+ projectDirectory,
70
+ force,
71
+ });
72
+
73
+ console.log("[Bugmole MCP Init] Generated initialization task");
74
+ console.log("[Bugmole MCP Init] Starting continuous execution loop...");
75
+ console.log(
76
+ "[Bugmole MCP Init] Cursor will initialize the framework and continue until complete...\n",
77
+ );
78
+
79
+ // Use continuous execution to automatically follow next_steps
80
+ const result = await executeContinuously(initTask, {
81
+ configPath,
82
+ timeout,
83
+ projectDirectory,
84
+ useCursor: true,
85
+ maxIterations: Number(maxIterations), // Configurable via --max-iterations flag
86
+ iterationDelay: 3000, // 3 second delay between iterations
87
+ customInstructions:
88
+ "Please continue with the Bugmole MCP initialization. Use the MCP tools to explore and create spec files. Include next_steps in your response if there are more steps to complete.",
89
+ });
90
+
91
+ console.log("\n[Bugmole MCP Init] Continuous execution completed\n");
92
+
93
+ if (result.success) {
94
+ console.log(`āœ… Initialization completed successfully in ${result.iterations} iteration(s)!`);
95
+
96
+ // Show summary of all iterations
97
+ console.log(`\n--- Execution Summary (${result.iterations} iteration(s)) ---`);
98
+ result.responses.forEach((response, index) => {
99
+ if ("payload" in response && response.payload) {
100
+ const cursorResponse = response as any;
101
+ console.log(`\nIteration ${index + 1}:`);
102
+ console.log(` Summary: ${cursorResponse.payload?.summary || "N/A"}`);
103
+ if (cursorResponse.payload?.next_steps) {
104
+ console.log(
105
+ ` Next Steps: ${cursorResponse.payload.next_steps.length} step(s) remaining`,
106
+ );
107
+ } else {
108
+ console.log(` Status: Complete (no next steps)`);
109
+ }
110
+ }
111
+ });
112
+
113
+ // Show final response details
114
+ const finalResponse = result.finalResponse;
115
+ if ("payload" in finalResponse && finalResponse.payload) {
116
+ const cursorResponse = finalResponse as any;
117
+
118
+ console.log(`\n--- Final Response ---`);
119
+ console.log(`Summary: ${cursorResponse.payload?.summary || "No summary provided"}`);
120
+
121
+ if (cursorResponse.payload?.answer_markdown) {
122
+ console.log("\n--- Full Answer ---");
123
+ console.log(cursorResponse.payload.answer_markdown);
124
+ }
125
+
126
+ if (cursorResponse.payload?.actions && cursorResponse.payload.actions.length > 0) {
127
+ console.log("\n--- Actions Performed ---");
128
+ cursorResponse.payload.actions.forEach((action: any, i: number) => {
129
+ console.log(`${i + 1}. ${action.type}: ${action.target}`);
130
+ if (action.details) {
131
+ console.log(` ${action.details}`);
132
+ }
133
+ });
134
+ }
135
+
136
+ if (cursorResponse.payload?.artifacts && cursorResponse.payload.artifacts.length > 0) {
137
+ console.log("\n--- Artifacts Generated ---");
138
+ cursorResponse.payload.artifacts.forEach((artifact: any, i: number) => {
139
+ console.log(`${i + 1}. ${artifact.type}`);
140
+ if (artifact.content) {
141
+ const preview = artifact.content.substring(0, 200);
142
+ console.log(` ${preview}${artifact.content.length > 200 ? "..." : ""}`);
143
+ }
144
+ });
145
+ }
146
+ }
147
+
148
+ console.log("\nšŸ“ Check the spec/ directory for initialized files:");
149
+ console.log(" - spec/roles.yaml");
150
+ console.log(" - spec/domain_rules.yaml");
151
+ console.log(" - spec/blockers.yaml");
152
+ console.log(" - spec/journeys.graph.json");
153
+ console.log(" - spec/bugs.index.json");
154
+
155
+ process.exit(0);
156
+ } else {
157
+ console.error("āŒ Initialization failed!");
158
+ console.error(`Error: ${result.error}`);
159
+ console.error(`Iterations completed: ${result.iterations}`);
160
+
161
+ if (result.iterations >= Number(maxIterations)) {
162
+ console.error(
163
+ `\nšŸ’” Reached maximum iterations (${maxIterations}). The task may be too complex.`,
164
+ );
165
+ console.error(
166
+ " Consider breaking it into smaller tasks or increasing maxIterations with --max-iterations flag.",
167
+ );
168
+ } else if (result.responses.length > 0) {
169
+ const lastResponse = result.responses[result.responses.length - 1];
170
+ if ("errorCode" in lastResponse) {
171
+ const cursorResponse = lastResponse as any;
172
+ if (cursorResponse.errorCode === "MCP_UNAVAILABLE") {
173
+ console.error("\nšŸ’” Make sure:");
174
+ console.error(" 1. MCP server is running (npm run bugmole:mcp)");
175
+ console.error(" 2. Cursor is configured to use the Bugmole MCP server");
176
+ console.error(" 3. MCP tools are available in Cursor");
177
+ }
178
+ }
179
+ }
180
+
181
+ process.exit(1);
182
+ }
183
+ }
184
+
185
+ main().catch((err) => {
186
+ console.error(`[Bugmole MCP Init] Fatal error: ${err?.message ?? err}`);
187
+ process.exit(1);
188
+ });
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ const { spawnSync } = require("node:child_process");
3
+ const path = require("node:path");
4
+
5
+ const tsxCli = require.resolve("tsx/cli");
6
+ const script = path.join(__dirname, "bugmole.ts");
7
+ const result = spawnSync(process.execPath, [tsxCli, script, ...process.argv.slice(2)], {
8
+ stdio: "inherit",
9
+ env: process.env,
10
+ });
11
+
12
+ if (result.error) {
13
+ console.error(`[Bugmole CLI] failed to start: ${result.error.message}`);
14
+ process.exit(1);
15
+ }
16
+
17
+ process.exit(result.status ?? 1);