thevoidforge 21.0.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 (328) hide show
  1. package/dist/scripts/vault-read.d.ts +11 -0
  2. package/dist/scripts/vault-read.js +89 -0
  3. package/dist/scripts/voidforge.d.ts +20 -0
  4. package/dist/scripts/voidforge.js +404 -0
  5. package/dist/tsconfig.tsbuildinfo +1 -0
  6. package/dist/wizard/api/auth.d.ts +5 -0
  7. package/dist/wizard/api/auth.js +133 -0
  8. package/dist/wizard/api/blueprint.d.ts +45 -0
  9. package/dist/wizard/api/blueprint.js +184 -0
  10. package/dist/wizard/api/cloud-providers.d.ts +16 -0
  11. package/dist/wizard/api/cloud-providers.js +363 -0
  12. package/dist/wizard/api/credentials.d.ts +1 -0
  13. package/dist/wizard/api/credentials.js +258 -0
  14. package/dist/wizard/api/danger-room.d.ts +18 -0
  15. package/dist/wizard/api/danger-room.js +401 -0
  16. package/dist/wizard/api/deploy.d.ts +4 -0
  17. package/dist/wizard/api/deploy.js +164 -0
  18. package/dist/wizard/api/prd.d.ts +1 -0
  19. package/dist/wizard/api/prd.js +363 -0
  20. package/dist/wizard/api/project.d.ts +1 -0
  21. package/dist/wizard/api/project.js +239 -0
  22. package/dist/wizard/api/projects.d.ts +6 -0
  23. package/dist/wizard/api/projects.js +648 -0
  24. package/dist/wizard/api/provision.d.ts +4 -0
  25. package/dist/wizard/api/provision.js +535 -0
  26. package/dist/wizard/api/terminal.d.ts +25 -0
  27. package/dist/wizard/api/terminal.js +241 -0
  28. package/dist/wizard/api/users.d.ts +6 -0
  29. package/dist/wizard/api/users.js +244 -0
  30. package/dist/wizard/api/war-room.d.ts +14 -0
  31. package/dist/wizard/api/war-room.js +45 -0
  32. package/dist/wizard/lib/ad-platform-core.d.ts +6 -0
  33. package/dist/wizard/lib/ad-platform-core.js +1 -0
  34. package/dist/wizard/lib/adapters/index.d.ts +52 -0
  35. package/dist/wizard/lib/adapters/index.js +38 -0
  36. package/dist/wizard/lib/adapters/sandbox-bank.d.ts +17 -0
  37. package/dist/wizard/lib/adapters/sandbox-bank.js +77 -0
  38. package/dist/wizard/lib/adapters/sandbox.d.ts +39 -0
  39. package/dist/wizard/lib/adapters/sandbox.js +174 -0
  40. package/dist/wizard/lib/adapters/stripe.d.ts +19 -0
  41. package/dist/wizard/lib/adapters/stripe.js +143 -0
  42. package/dist/wizard/lib/adapters/types.d.ts +9 -0
  43. package/dist/wizard/lib/adapters/types.js +10 -0
  44. package/dist/wizard/lib/agent-memory.d.ts +36 -0
  45. package/dist/wizard/lib/agent-memory.js +114 -0
  46. package/dist/wizard/lib/anomaly-detection.d.ts +59 -0
  47. package/dist/wizard/lib/anomaly-detection.js +122 -0
  48. package/dist/wizard/lib/anthropic.d.ts +21 -0
  49. package/dist/wizard/lib/anthropic.js +105 -0
  50. package/dist/wizard/lib/asset-scanner.d.ts +23 -0
  51. package/dist/wizard/lib/asset-scanner.js +107 -0
  52. package/dist/wizard/lib/audit-log.d.ts +23 -0
  53. package/dist/wizard/lib/audit-log.js +70 -0
  54. package/dist/wizard/lib/autonomy-controller.d.ts +76 -0
  55. package/dist/wizard/lib/autonomy-controller.js +183 -0
  56. package/dist/wizard/lib/body-parser.d.ts +2 -0
  57. package/dist/wizard/lib/body-parser.js +36 -0
  58. package/dist/wizard/lib/build-analytics.d.ts +39 -0
  59. package/dist/wizard/lib/build-analytics.js +91 -0
  60. package/dist/wizard/lib/build-step.d.ts +21 -0
  61. package/dist/wizard/lib/build-step.js +104 -0
  62. package/dist/wizard/lib/campaign-proposer.d.ts +39 -0
  63. package/dist/wizard/lib/campaign-proposer.js +180 -0
  64. package/dist/wizard/lib/campaign-state-machine.d.ts +63 -0
  65. package/dist/wizard/lib/campaign-state-machine.js +114 -0
  66. package/dist/wizard/lib/ci-generator.d.ts +14 -0
  67. package/dist/wizard/lib/ci-generator.js +187 -0
  68. package/dist/wizard/lib/claude-merge.d.ts +38 -0
  69. package/dist/wizard/lib/claude-merge.js +115 -0
  70. package/dist/wizard/lib/codegen/erd-gen.d.ts +16 -0
  71. package/dist/wizard/lib/codegen/erd-gen.js +98 -0
  72. package/dist/wizard/lib/codegen/integrations.d.ts +18 -0
  73. package/dist/wizard/lib/codegen/integrations.js +189 -0
  74. package/dist/wizard/lib/codegen/openapi-gen.d.ts +15 -0
  75. package/dist/wizard/lib/codegen/openapi-gen.js +79 -0
  76. package/dist/wizard/lib/codegen/prisma-types.d.ts +15 -0
  77. package/dist/wizard/lib/codegen/prisma-types.js +44 -0
  78. package/dist/wizard/lib/codegen/seed-gen.d.ts +16 -0
  79. package/dist/wizard/lib/codegen/seed-gen.js +128 -0
  80. package/dist/wizard/lib/compliance.d.ts +51 -0
  81. package/dist/wizard/lib/compliance.js +112 -0
  82. package/dist/wizard/lib/correlation-engine.d.ts +59 -0
  83. package/dist/wizard/lib/correlation-engine.js +151 -0
  84. package/dist/wizard/lib/cost-estimator.d.ts +22 -0
  85. package/dist/wizard/lib/cost-estimator.js +72 -0
  86. package/dist/wizard/lib/cost-tracker.d.ts +27 -0
  87. package/dist/wizard/lib/cost-tracker.js +37 -0
  88. package/dist/wizard/lib/daemon-aggregator.d.ts +71 -0
  89. package/dist/wizard/lib/daemon-aggregator.js +204 -0
  90. package/dist/wizard/lib/daemon-core.d.ts +6 -0
  91. package/dist/wizard/lib/daemon-core.js +5 -0
  92. package/dist/wizard/lib/dashboard-data.d.ts +132 -0
  93. package/dist/wizard/lib/dashboard-data.js +336 -0
  94. package/dist/wizard/lib/dashboard-ws.d.ts +25 -0
  95. package/dist/wizard/lib/dashboard-ws.js +91 -0
  96. package/dist/wizard/lib/deep-current.d.ts +77 -0
  97. package/dist/wizard/lib/deep-current.js +234 -0
  98. package/dist/wizard/lib/deploy-coordinator.d.ts +40 -0
  99. package/dist/wizard/lib/deploy-coordinator.js +86 -0
  100. package/dist/wizard/lib/deploy-log.d.ts +28 -0
  101. package/dist/wizard/lib/deploy-log.js +52 -0
  102. package/dist/wizard/lib/desktop-notify.d.ts +27 -0
  103. package/dist/wizard/lib/desktop-notify.js +98 -0
  104. package/dist/wizard/lib/dns/cloudflare-dns.d.ts +35 -0
  105. package/dist/wizard/lib/dns/cloudflare-dns.js +216 -0
  106. package/dist/wizard/lib/dns/cloudflare-registrar.d.ts +31 -0
  107. package/dist/wizard/lib/dns/cloudflare-registrar.js +148 -0
  108. package/dist/wizard/lib/dns/types.d.ts +22 -0
  109. package/dist/wizard/lib/dns/types.js +4 -0
  110. package/dist/wizard/lib/document-discovery.d.ts +33 -0
  111. package/dist/wizard/lib/document-discovery.js +145 -0
  112. package/dist/wizard/lib/env-validator.d.ts +14 -0
  113. package/dist/wizard/lib/env-validator.js +205 -0
  114. package/dist/wizard/lib/env-writer.d.ts +13 -0
  115. package/dist/wizard/lib/env-writer.js +26 -0
  116. package/dist/wizard/lib/exec.d.ts +30 -0
  117. package/dist/wizard/lib/exec.js +52 -0
  118. package/dist/wizard/lib/experiment.d.ts +70 -0
  119. package/dist/wizard/lib/experiment.js +169 -0
  120. package/dist/wizard/lib/extensions.d.ts +20 -0
  121. package/dist/wizard/lib/extensions.js +183 -0
  122. package/dist/wizard/lib/financial/adapter-factory.d.ts +47 -0
  123. package/dist/wizard/lib/financial/adapter-factory.js +225 -0
  124. package/dist/wizard/lib/financial/billing/base.d.ts +6 -0
  125. package/dist/wizard/lib/financial/billing/base.js +1 -0
  126. package/dist/wizard/lib/financial/billing/google-billing.d.ts +56 -0
  127. package/dist/wizard/lib/financial/billing/google-billing.js +298 -0
  128. package/dist/wizard/lib/financial/billing/meta-billing.d.ts +54 -0
  129. package/dist/wizard/lib/financial/billing/meta-billing.js +243 -0
  130. package/dist/wizard/lib/financial/billing/tiktok-billing.d.ts +54 -0
  131. package/dist/wizard/lib/financial/billing/tiktok-billing.js +260 -0
  132. package/dist/wizard/lib/financial/campaign/base.d.ts +13 -0
  133. package/dist/wizard/lib/financial/campaign/base.js +1 -0
  134. package/dist/wizard/lib/financial/campaign/google-campaign.d.ts +42 -0
  135. package/dist/wizard/lib/financial/campaign/google-campaign.js +388 -0
  136. package/dist/wizard/lib/financial/campaign/meta-campaign.d.ts +41 -0
  137. package/dist/wizard/lib/financial/campaign/meta-campaign.js +311 -0
  138. package/dist/wizard/lib/financial/campaign/sandbox-campaign.d.ts +45 -0
  139. package/dist/wizard/lib/financial/campaign/sandbox-campaign.js +261 -0
  140. package/dist/wizard/lib/financial/campaign/tiktok-campaign.d.ts +40 -0
  141. package/dist/wizard/lib/financial/campaign/tiktok-campaign.js +350 -0
  142. package/dist/wizard/lib/financial/funding-auto.d.ts +44 -0
  143. package/dist/wizard/lib/financial/funding-auto.js +52 -0
  144. package/dist/wizard/lib/financial/funding-policy.d.ts +60 -0
  145. package/dist/wizard/lib/financial/funding-policy.js +179 -0
  146. package/dist/wizard/lib/financial/platform-planner.d.ts +47 -0
  147. package/dist/wizard/lib/financial/platform-planner.js +134 -0
  148. package/dist/wizard/lib/financial/reconciliation-engine.d.ts +78 -0
  149. package/dist/wizard/lib/financial/reconciliation-engine.js +193 -0
  150. package/dist/wizard/lib/financial/registry.d.ts +22 -0
  151. package/dist/wizard/lib/financial/registry.js +26 -0
  152. package/dist/wizard/lib/financial/reporting.d.ts +96 -0
  153. package/dist/wizard/lib/financial/reporting.js +198 -0
  154. package/dist/wizard/lib/financial/stablecoin/base.d.ts +6 -0
  155. package/dist/wizard/lib/financial/stablecoin/base.js +1 -0
  156. package/dist/wizard/lib/financial/stablecoin/circle.d.ts +54 -0
  157. package/dist/wizard/lib/financial/stablecoin/circle.js +367 -0
  158. package/dist/wizard/lib/financial/stablecoin/mercury.d.ts +24 -0
  159. package/dist/wizard/lib/financial/stablecoin/mercury.js +171 -0
  160. package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.d.ts +47 -0
  161. package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.js +202 -0
  162. package/dist/wizard/lib/financial/treasury-planner.d.ts +52 -0
  163. package/dist/wizard/lib/financial/treasury-planner.js +128 -0
  164. package/dist/wizard/lib/financial-core.d.ts +6 -0
  165. package/dist/wizard/lib/financial-core.js +5 -0
  166. package/dist/wizard/lib/financial-vault.d.ts +34 -0
  167. package/dist/wizard/lib/financial-vault.js +199 -0
  168. package/dist/wizard/lib/frontmatter.d.ts +30 -0
  169. package/dist/wizard/lib/frontmatter.js +96 -0
  170. package/dist/wizard/lib/gap-analysis.d.ts +37 -0
  171. package/dist/wizard/lib/gap-analysis.js +218 -0
  172. package/dist/wizard/lib/github.d.ts +22 -0
  173. package/dist/wizard/lib/github.js +261 -0
  174. package/dist/wizard/lib/headless-deploy.d.ts +14 -0
  175. package/dist/wizard/lib/headless-deploy.js +452 -0
  176. package/dist/wizard/lib/health-monitor.d.ts +15 -0
  177. package/dist/wizard/lib/health-monitor.js +91 -0
  178. package/dist/wizard/lib/health-poller.d.ts +9 -0
  179. package/dist/wizard/lib/health-poller.js +123 -0
  180. package/dist/wizard/lib/heartbeat.d.ts +15 -0
  181. package/dist/wizard/lib/heartbeat.js +827 -0
  182. package/dist/wizard/lib/http-helpers.d.ts +9 -0
  183. package/dist/wizard/lib/http-helpers.js +24 -0
  184. package/dist/wizard/lib/image-gen.d.ts +56 -0
  185. package/dist/wizard/lib/image-gen.js +159 -0
  186. package/dist/wizard/lib/instance-sizing.d.ts +26 -0
  187. package/dist/wizard/lib/instance-sizing.js +51 -0
  188. package/dist/wizard/lib/kongo/analytics.d.ts +29 -0
  189. package/dist/wizard/lib/kongo/analytics.js +179 -0
  190. package/dist/wizard/lib/kongo/campaigns.d.ts +52 -0
  191. package/dist/wizard/lib/kongo/campaigns.js +91 -0
  192. package/dist/wizard/lib/kongo/client.d.ts +58 -0
  193. package/dist/wizard/lib/kongo/client.js +221 -0
  194. package/dist/wizard/lib/kongo/jobs.d.ts +57 -0
  195. package/dist/wizard/lib/kongo/jobs.js +122 -0
  196. package/dist/wizard/lib/kongo/pages.d.ts +60 -0
  197. package/dist/wizard/lib/kongo/pages.js +150 -0
  198. package/dist/wizard/lib/kongo/provisioner.d.ts +64 -0
  199. package/dist/wizard/lib/kongo/provisioner.js +116 -0
  200. package/dist/wizard/lib/kongo/seed.d.ts +49 -0
  201. package/dist/wizard/lib/kongo/seed.js +237 -0
  202. package/dist/wizard/lib/kongo/types.d.ts +323 -0
  203. package/dist/wizard/lib/kongo/types.js +11 -0
  204. package/dist/wizard/lib/kongo/variants.d.ts +57 -0
  205. package/dist/wizard/lib/kongo/variants.js +88 -0
  206. package/dist/wizard/lib/kongo/webhooks.d.ts +41 -0
  207. package/dist/wizard/lib/kongo/webhooks.js +112 -0
  208. package/dist/wizard/lib/marker.d.ts +28 -0
  209. package/dist/wizard/lib/marker.js +79 -0
  210. package/dist/wizard/lib/migrator.d.ts +35 -0
  211. package/dist/wizard/lib/migrator.js +190 -0
  212. package/dist/wizard/lib/natural-language-deploy.d.ts +30 -0
  213. package/dist/wizard/lib/natural-language-deploy.js +186 -0
  214. package/dist/wizard/lib/network.d.ts +22 -0
  215. package/dist/wizard/lib/network.js +72 -0
  216. package/dist/wizard/lib/oauth-core.d.ts +6 -0
  217. package/dist/wizard/lib/oauth-core.js +5 -0
  218. package/dist/wizard/lib/open-browser.d.ts +1 -0
  219. package/dist/wizard/lib/open-browser.js +26 -0
  220. package/dist/wizard/lib/patterns/ad-billing-adapter.d.ts +209 -0
  221. package/dist/wizard/lib/patterns/ad-billing-adapter.js +269 -0
  222. package/dist/wizard/lib/patterns/ad-platform-adapter.d.ts +200 -0
  223. package/dist/wizard/lib/patterns/ad-platform-adapter.js +212 -0
  224. package/dist/wizard/lib/patterns/daemon-process.d.ts +88 -0
  225. package/dist/wizard/lib/patterns/daemon-process.js +271 -0
  226. package/dist/wizard/lib/patterns/financial-transaction.d.ts +161 -0
  227. package/dist/wizard/lib/patterns/financial-transaction.js +132 -0
  228. package/dist/wizard/lib/patterns/funding-plan.d.ts +136 -0
  229. package/dist/wizard/lib/patterns/funding-plan.js +200 -0
  230. package/dist/wizard/lib/patterns/oauth-token-lifecycle.d.ts +94 -0
  231. package/dist/wizard/lib/patterns/oauth-token-lifecycle.js +139 -0
  232. package/dist/wizard/lib/patterns/outbound-rate-limiter.d.ts +67 -0
  233. package/dist/wizard/lib/patterns/outbound-rate-limiter.js +216 -0
  234. package/dist/wizard/lib/patterns/revenue-source-adapter.d.ts +96 -0
  235. package/dist/wizard/lib/patterns/revenue-source-adapter.js +182 -0
  236. package/dist/wizard/lib/patterns/stablecoin-adapter.d.ts +218 -0
  237. package/dist/wizard/lib/patterns/stablecoin-adapter.js +264 -0
  238. package/dist/wizard/lib/prd-validator.d.ts +39 -0
  239. package/dist/wizard/lib/prd-validator.js +137 -0
  240. package/dist/wizard/lib/project-init.d.ts +24 -0
  241. package/dist/wizard/lib/project-init.js +193 -0
  242. package/dist/wizard/lib/project-registry.d.ts +86 -0
  243. package/dist/wizard/lib/project-registry.js +359 -0
  244. package/dist/wizard/lib/provision-manifest.d.ts +44 -0
  245. package/dist/wizard/lib/provision-manifest.js +164 -0
  246. package/dist/wizard/lib/provisioner-registry.d.ts +15 -0
  247. package/dist/wizard/lib/provisioner-registry.js +34 -0
  248. package/dist/wizard/lib/provisioners/aws-vps.d.ts +6 -0
  249. package/dist/wizard/lib/provisioners/aws-vps.js +643 -0
  250. package/dist/wizard/lib/provisioners/cloudflare.d.ts +6 -0
  251. package/dist/wizard/lib/provisioners/cloudflare.js +300 -0
  252. package/dist/wizard/lib/provisioners/docker.d.ts +6 -0
  253. package/dist/wizard/lib/provisioners/docker.js +75 -0
  254. package/dist/wizard/lib/provisioners/http-client.d.ts +20 -0
  255. package/dist/wizard/lib/provisioners/http-client.js +79 -0
  256. package/dist/wizard/lib/provisioners/railway.d.ts +6 -0
  257. package/dist/wizard/lib/provisioners/railway.js +413 -0
  258. package/dist/wizard/lib/provisioners/scripts/caddyfile.d.ts +10 -0
  259. package/dist/wizard/lib/provisioners/scripts/caddyfile.js +54 -0
  260. package/dist/wizard/lib/provisioners/scripts/deploy-vps.d.ts +10 -0
  261. package/dist/wizard/lib/provisioners/scripts/deploy-vps.js +112 -0
  262. package/dist/wizard/lib/provisioners/scripts/docker-compose.d.ts +11 -0
  263. package/dist/wizard/lib/provisioners/scripts/docker-compose.js +91 -0
  264. package/dist/wizard/lib/provisioners/scripts/dockerfile.d.ts +5 -0
  265. package/dist/wizard/lib/provisioners/scripts/dockerfile.js +185 -0
  266. package/dist/wizard/lib/provisioners/scripts/ecosystem-config.d.ts +10 -0
  267. package/dist/wizard/lib/provisioners/scripts/ecosystem-config.js +36 -0
  268. package/dist/wizard/lib/provisioners/scripts/provision-vps.d.ts +14 -0
  269. package/dist/wizard/lib/provisioners/scripts/provision-vps.js +202 -0
  270. package/dist/wizard/lib/provisioners/scripts/rollback-vps.d.ts +10 -0
  271. package/dist/wizard/lib/provisioners/scripts/rollback-vps.js +67 -0
  272. package/dist/wizard/lib/provisioners/self-deploy.d.ts +41 -0
  273. package/dist/wizard/lib/provisioners/self-deploy.js +185 -0
  274. package/dist/wizard/lib/provisioners/static-s3.d.ts +6 -0
  275. package/dist/wizard/lib/provisioners/static-s3.js +235 -0
  276. package/dist/wizard/lib/provisioners/types.d.ts +40 -0
  277. package/dist/wizard/lib/provisioners/types.js +4 -0
  278. package/dist/wizard/lib/provisioners/vercel.d.ts +6 -0
  279. package/dist/wizard/lib/provisioners/vercel.js +287 -0
  280. package/dist/wizard/lib/pty-manager.d.ts +42 -0
  281. package/dist/wizard/lib/pty-manager.js +231 -0
  282. package/dist/wizard/lib/rate-limiter-core.d.ts +5 -0
  283. package/dist/wizard/lib/rate-limiter-core.js +5 -0
  284. package/dist/wizard/lib/reconciliation.d.ts +43 -0
  285. package/dist/wizard/lib/reconciliation.js +173 -0
  286. package/dist/wizard/lib/revenue-types.d.ts +5 -0
  287. package/dist/wizard/lib/revenue-types.js +1 -0
  288. package/dist/wizard/lib/route-optimizer.d.ts +28 -0
  289. package/dist/wizard/lib/route-optimizer.js +93 -0
  290. package/dist/wizard/lib/s3-deploy.d.ts +19 -0
  291. package/dist/wizard/lib/s3-deploy.js +156 -0
  292. package/dist/wizard/lib/safety-tiers.d.ts +76 -0
  293. package/dist/wizard/lib/safety-tiers.js +134 -0
  294. package/dist/wizard/lib/sentry-generator.d.ts +15 -0
  295. package/dist/wizard/lib/sentry-generator.js +116 -0
  296. package/dist/wizard/lib/server-config.d.ts +13 -0
  297. package/dist/wizard/lib/server-config.js +23 -0
  298. package/dist/wizard/lib/service-install.d.ts +18 -0
  299. package/dist/wizard/lib/service-install.js +182 -0
  300. package/dist/wizard/lib/site-scanner.d.ts +80 -0
  301. package/dist/wizard/lib/site-scanner.js +262 -0
  302. package/dist/wizard/lib/ssh-deploy.d.ts +25 -0
  303. package/dist/wizard/lib/ssh-deploy.js +225 -0
  304. package/dist/wizard/lib/templates.d.ts +24 -0
  305. package/dist/wizard/lib/templates.js +219 -0
  306. package/dist/wizard/lib/totp.d.ts +35 -0
  307. package/dist/wizard/lib/totp.js +276 -0
  308. package/dist/wizard/lib/tower-auth.d.ts +43 -0
  309. package/dist/wizard/lib/tower-auth.js +352 -0
  310. package/dist/wizard/lib/tower-rate-limit.d.ts +14 -0
  311. package/dist/wizard/lib/tower-rate-limit.js +61 -0
  312. package/dist/wizard/lib/tower-session.d.ts +28 -0
  313. package/dist/wizard/lib/tower-session.js +119 -0
  314. package/dist/wizard/lib/treasury-backup.d.ts +23 -0
  315. package/dist/wizard/lib/treasury-backup.js +126 -0
  316. package/dist/wizard/lib/treasury-heartbeat.d.ts +82 -0
  317. package/dist/wizard/lib/treasury-heartbeat.js +1104 -0
  318. package/dist/wizard/lib/updater.d.ts +29 -0
  319. package/dist/wizard/lib/updater.js +190 -0
  320. package/dist/wizard/lib/user-manager.d.ts +39 -0
  321. package/dist/wizard/lib/user-manager.js +182 -0
  322. package/dist/wizard/lib/vault.d.ts +26 -0
  323. package/dist/wizard/lib/vault.js +161 -0
  324. package/dist/wizard/router.d.ts +5 -0
  325. package/dist/wizard/router.js +15 -0
  326. package/dist/wizard/server.d.ts +18 -0
  327. package/dist/wizard/server.js +436 -0
  328. package/package.json +59 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Kongo Pages — Page lifecycle operations.
3
+ *
4
+ * Generate landing pages from PRD seed content, poll for completion,
5
+ * retrieve HTML, list/delete pages, and batch generate.
6
+ *
7
+ * Uses the real Kongo API surface:
8
+ * - POST /engine/pages — generate a page (accepts brief + template for structured input)
9
+ * - GET /engine/pages/:pageId — poll status until READY
10
+ * - GET /engine/pages/:pageId/html — get raw HTML
11
+ * - GET /engine/pages — list pages (cursor pagination)
12
+ * - DELETE /engine/pages/:pageId — soft delete
13
+ * - POST /engine/pages/batch — batch generate 1-50 pages
14
+ *
15
+ * PRD Reference: PRD-kongo-integration.md §4.1
16
+ */
17
+ import { randomUUID } from 'node:crypto';
18
+ import { KongoApiError } from './client.js';
19
+ // ── Page Operations ──────────────────────────────────────
20
+ const DEFAULT_POLL_INTERVAL_MS = 3_000;
21
+ // Kongo page generation takes 2-10 minutes. Default timeout covers the full range.
22
+ const DEFAULT_POLL_TIMEOUT_MS = 660_000; // 11 minutes (10 min upper bound + 1 min buffer)
23
+ /**
24
+ * Create a page from raw configuration.
25
+ * Returns immediately with pageId — generation runs async (2-10 min).
26
+ */
27
+ export async function createPage(client, config) {
28
+ return client.post('/engine/pages', config, { 'Idempotency-Key': randomUUID() });
29
+ }
30
+ /**
31
+ * Create a landing page from PRD seed content.
32
+ * Maps PrdSeedContent to Kongo's CreatePageRequest with brief + template: 'landing-page'.
33
+ */
34
+ export async function createPageFromPrd(client, seed) {
35
+ const brief = {
36
+ companyName: seed.projectName,
37
+ headline: seed.headline,
38
+ subheadline: seed.subheadline,
39
+ valuePropositions: seed.valueProps,
40
+ ctaText: seed.ctaText,
41
+ ctaUrl: seed.ctaUrl,
42
+ };
43
+ if (seed.logoUrl)
44
+ brief.logoUrl = seed.logoUrl;
45
+ if (seed.socialProof?.length)
46
+ brief.socialProof = seed.socialProof;
47
+ const metadata = {
48
+ source: 'voidforge',
49
+ projectName: seed.projectName,
50
+ };
51
+ if (seed.campaignId)
52
+ metadata.campaignId = seed.campaignId;
53
+ if (seed.platform)
54
+ metadata.platform = seed.platform;
55
+ return createPage(client, {
56
+ companyName: seed.projectName,
57
+ content: [
58
+ seed.headline,
59
+ seed.subheadline,
60
+ ...seed.valueProps,
61
+ seed.ctaText,
62
+ ...(seed.socialProof ?? []),
63
+ ].join('\n\n'),
64
+ brief,
65
+ template: 'landing-page',
66
+ style: {
67
+ colors: seed.brandColors,
68
+ },
69
+ hosted: true,
70
+ metadata,
71
+ });
72
+ }
73
+ /**
74
+ * Get the current status and details of a page.
75
+ */
76
+ export async function getPageStatus(client, pageId) {
77
+ return client.get(`/engine/pages/${encodeURIComponent(pageId)}`);
78
+ }
79
+ /**
80
+ * Get the raw HTML of a generated page.
81
+ * Only works when status is READY.
82
+ */
83
+ export async function getPageHtml(client, pageId, options) {
84
+ const query = {};
85
+ if (options?.tracking !== undefined)
86
+ query.tracking = String(options.tracking);
87
+ if (options?.minify !== undefined)
88
+ query.minify = String(options.minify);
89
+ return client.get(`/engine/pages/${encodeURIComponent(pageId)}/html`, query);
90
+ }
91
+ /**
92
+ * Poll a page until it reaches READY status or timeout.
93
+ * Throws on ERROR status or timeout.
94
+ */
95
+ export async function awaitPage(client, pageId, options) {
96
+ const timeoutMs = options?.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
97
+ const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
98
+ const deadline = Date.now() + timeoutMs;
99
+ while (Date.now() < deadline) {
100
+ const page = await getPageStatus(client, pageId);
101
+ if (page.status === 'READY')
102
+ return page;
103
+ if (page.status === 'ERROR') {
104
+ throw new KongoApiError('GENERATION_FAILED', `Page generation failed: ${page.error?.message ?? 'Unknown error'}`, 500);
105
+ }
106
+ // Still GENERATING — wait and retry
107
+ const remaining = deadline - Date.now();
108
+ if (remaining <= 0)
109
+ break;
110
+ await sleep(Math.min(intervalMs, remaining));
111
+ }
112
+ throw new KongoApiError('TIMEOUT', `Page ${pageId} generation timed out after ${timeoutMs / 1000}s`, 408, true);
113
+ }
114
+ /**
115
+ * List pages with cursor-based pagination.
116
+ */
117
+ export async function listPages(client, options) {
118
+ const query = {};
119
+ if (options?.cursor)
120
+ query.cursor = options.cursor;
121
+ if (options?.limit)
122
+ query.limit = options.limit;
123
+ if (options?.status)
124
+ query.status = options.status;
125
+ if (options?.sort)
126
+ query.sort = options.sort;
127
+ if (options?.order)
128
+ query.order = options.order;
129
+ return client.get('/engine/pages', query);
130
+ }
131
+ /**
132
+ * Soft-delete a page. HTML is purged immediately, metadata retained 90 days.
133
+ */
134
+ export async function deletePage(client, pageId) {
135
+ await client.delete(`/engine/pages/${encodeURIComponent(pageId)}`);
136
+ }
137
+ /**
138
+ * Batch generate 1-50 pages in a single request.
139
+ */
140
+ export async function batchGenerate(client, configs) {
141
+ if (configs.length === 0 || configs.length > 50) {
142
+ throw new KongoApiError('VALIDATION_ERROR', `Batch size must be 1-50, got ${configs.length}`, 400);
143
+ }
144
+ const result = await client.post('/engine/pages/batch', { pages: configs }, { 'Idempotency-Key': randomUUID() });
145
+ return result.pages;
146
+ }
147
+ // ── Helpers ──────────────────────────────────────────────
148
+ function sleep(ms) {
149
+ return new Promise((resolve) => setTimeout(resolve, ms));
150
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Kongo Provisioner — API key setup and connection verification.
3
+ *
4
+ * Called during /cultivation install Step 2b: "Connect Kongo for landing pages?"
5
+ *
6
+ * Kongo uses API keys (ke_live_ prefix), not OAuth. Keys are created in the
7
+ * Kongo dashboard at kongo.io/dashboard/api. The provisioner:
8
+ * 1. Accepts a user-provided API key
9
+ * 2. Verifies the connection with GET /engine/pages (expects 200)
10
+ * 3. Stores the key in the financial vault
11
+ * 4. Stores the webhook signing secret (optional)
12
+ *
13
+ * PRD Reference: PRD-kongo-integration.md §4.4 (adjusted from OAuth to manual)
14
+ */
15
+ import { KongoClient } from './client.js';
16
+ /** Vault key for the Kongo API key */
17
+ export declare const KONGO_API_KEY_VAULT_KEY = "kongo-api-key";
18
+ /** Vault key for the webhook signing secret */
19
+ export declare const KONGO_WEBHOOK_SECRET_VAULT_KEY = "kongo-webhook-secret";
20
+ export interface KongoConnectionStatus {
21
+ readonly connected: boolean;
22
+ readonly pageCount?: number;
23
+ readonly error?: string;
24
+ }
25
+ /**
26
+ * Verify a Kongo API key by making a read-only API call.
27
+ * Returns connection status with page count on success.
28
+ */
29
+ export declare function verifyKongoConnection(apiKey: string): Promise<KongoConnectionStatus>;
30
+ export interface KongoProvisionConfig {
31
+ readonly apiKey: string;
32
+ readonly webhookSecret?: string;
33
+ }
34
+ export interface KongoProvisionResult {
35
+ readonly success: boolean;
36
+ readonly message: string;
37
+ readonly connection?: KongoConnectionStatus;
38
+ }
39
+ /**
40
+ * Provision Kongo access during /cultivation install.
41
+ *
42
+ * Steps:
43
+ * 1. Validate key format (ke_live_ prefix)
44
+ * 2. Verify connection with read-only API call
45
+ * 3. Store key in financial vault
46
+ * 4. Optionally store webhook signing secret
47
+ *
48
+ * @param config - API key and optional webhook secret
49
+ * @param vaultSet - Financial vault setter (injected for testability)
50
+ */
51
+ export declare function provisionKongo(config: KongoProvisionConfig, vaultSet: (key: string, value: string) => Promise<void>): Promise<KongoProvisionResult>;
52
+ /**
53
+ * Check if Kongo is connected (API key exists in vault).
54
+ */
55
+ export declare function isKongoConnected(vaultGet: (key: string) => Promise<string | null>): Promise<boolean>;
56
+ /**
57
+ * Create a KongoClient from vault credentials.
58
+ * Returns null if Kongo is not connected.
59
+ */
60
+ export declare function getKongoClient(vaultGet: (key: string) => Promise<string | null>): Promise<KongoClient | null>;
61
+ /**
62
+ * Remove Kongo credentials from vault (disconnect).
63
+ */
64
+ export declare function disconnectKongo(vaultDelete: (key: string) => Promise<void>): Promise<void>;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Kongo Provisioner — API key setup and connection verification.
3
+ *
4
+ * Called during /cultivation install Step 2b: "Connect Kongo for landing pages?"
5
+ *
6
+ * Kongo uses API keys (ke_live_ prefix), not OAuth. Keys are created in the
7
+ * Kongo dashboard at kongo.io/dashboard/api. The provisioner:
8
+ * 1. Accepts a user-provided API key
9
+ * 2. Verifies the connection with GET /engine/pages (expects 200)
10
+ * 3. Stores the key in the financial vault
11
+ * 4. Stores the webhook signing secret (optional)
12
+ *
13
+ * PRD Reference: PRD-kongo-integration.md §4.4 (adjusted from OAuth to manual)
14
+ */
15
+ import { KongoClient, KongoApiError } from './client.js';
16
+ // ── Vault Keys ───────────────────────────────────────────
17
+ /** Vault key for the Kongo API key */
18
+ export const KONGO_API_KEY_VAULT_KEY = 'kongo-api-key';
19
+ /** Vault key for the webhook signing secret */
20
+ export const KONGO_WEBHOOK_SECRET_VAULT_KEY = 'kongo-webhook-secret';
21
+ /**
22
+ * Verify a Kongo API key by making a read-only API call.
23
+ * Returns connection status with page count on success.
24
+ */
25
+ export async function verifyKongoConnection(apiKey) {
26
+ try {
27
+ const client = new KongoClient({ apiKey });
28
+ const result = await client.get('/engine/pages', { limit: 1 });
29
+ return {
30
+ connected: true,
31
+ pageCount: result.items.length > 0 ? undefined : 0, // Can't know total from first page
32
+ };
33
+ }
34
+ catch (err) {
35
+ if (err instanceof KongoApiError) {
36
+ return {
37
+ connected: false,
38
+ error: `${err.code}: ${err.message}`,
39
+ };
40
+ }
41
+ return {
42
+ connected: false,
43
+ error: err instanceof Error ? err.message : 'Unknown error',
44
+ };
45
+ }
46
+ }
47
+ /**
48
+ * Provision Kongo access during /cultivation install.
49
+ *
50
+ * Steps:
51
+ * 1. Validate key format (ke_live_ prefix)
52
+ * 2. Verify connection with read-only API call
53
+ * 3. Store key in financial vault
54
+ * 4. Optionally store webhook signing secret
55
+ *
56
+ * @param config - API key and optional webhook secret
57
+ * @param vaultSet - Financial vault setter (injected for testability)
58
+ */
59
+ export async function provisionKongo(config, vaultSet) {
60
+ // Validate key format
61
+ if (!config.apiKey.startsWith('ke_live_')) {
62
+ return {
63
+ success: false,
64
+ message: 'Invalid API key format. Kongo keys use the ke_live_ prefix. Get yours at kongo.io/dashboard/api',
65
+ };
66
+ }
67
+ // Verify connection
68
+ const connection = await verifyKongoConnection(config.apiKey);
69
+ if (!connection.connected) {
70
+ return {
71
+ success: false,
72
+ message: `Kongo connection failed: ${connection.error}`,
73
+ connection,
74
+ };
75
+ }
76
+ // Store in vault
77
+ await vaultSet(KONGO_API_KEY_VAULT_KEY, config.apiKey);
78
+ if (config.webhookSecret) {
79
+ await vaultSet(KONGO_WEBHOOK_SECRET_VAULT_KEY, config.webhookSecret);
80
+ }
81
+ return {
82
+ success: true,
83
+ message: 'Kongo connected successfully.',
84
+ connection,
85
+ };
86
+ }
87
+ // ── Connection Check ─────────────────────────────────────
88
+ /**
89
+ * Check if Kongo is connected (API key exists in vault).
90
+ */
91
+ export async function isKongoConnected(vaultGet) {
92
+ const apiKey = await vaultGet(KONGO_API_KEY_VAULT_KEY);
93
+ return apiKey !== null && apiKey.startsWith('ke_live_');
94
+ }
95
+ /**
96
+ * Create a KongoClient from vault credentials.
97
+ * Returns null if Kongo is not connected.
98
+ */
99
+ export async function getKongoClient(vaultGet) {
100
+ const apiKey = await vaultGet(KONGO_API_KEY_VAULT_KEY);
101
+ if (!apiKey)
102
+ return null;
103
+ try {
104
+ return new KongoClient({ apiKey });
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ /**
111
+ * Remove Kongo credentials from vault (disconnect).
112
+ */
113
+ export async function disconnectKongo(vaultDelete) {
114
+ await vaultDelete(KONGO_API_KEY_VAULT_KEY);
115
+ await vaultDelete(KONGO_WEBHOOK_SECRET_VAULT_KEY);
116
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Kongo Seed — Extract seed content from PRDs for landing page generation.
3
+ *
4
+ * Phase 3.5 of /grow: Before you distribute, you need somewhere to send them.
5
+ *
6
+ * Extracts headline, value props, CTA, brand colors, and social proof from
7
+ * PRD YAML frontmatter and prose content. Maps to PrdSeedContent which
8
+ * feeds into createPageFromPrd().
9
+ *
10
+ * PRD Reference: PRD-kongo-integration.md §4.5
11
+ */
12
+ import type { PrdSeedContent } from './types.js';
13
+ export interface PrdContent {
14
+ /** YAML frontmatter parsed as object */
15
+ readonly frontmatter: Record<string, unknown>;
16
+ /** Full PRD text content (after frontmatter) */
17
+ readonly body: string;
18
+ }
19
+ /**
20
+ * Extract PrdSeedContent from a PRD document.
21
+ *
22
+ * Strategy:
23
+ * 1. Use frontmatter `name` for project name
24
+ * 2. Extract first ## heading or overview section for headline
25
+ * 3. Extract value props from feature descriptions or bullet lists
26
+ * 4. Use brand colors from frontmatter `style` or defaults
27
+ * 5. Extract CTA from conversion or signup references
28
+ */
29
+ export declare function extractSeedFromPrd(prd: PrdContent): PrdSeedContent;
30
+ /**
31
+ * Extract seed content for a specific campaign.
32
+ * Enriches the base PRD seed with campaign-specific metadata.
33
+ *
34
+ * Self-marketing mode: When the product domain matches the Kongo domain
35
+ * (dogfooding), destination URLs use the /lp/ direct-render path instead
36
+ * of subdomain URLs. This avoids the iframe sandbox constraint that breaks
37
+ * GA4 cookie tracking and UTM relay. See GROWTH_STRATEGIST.md "Iframe
38
+ * Sandbox Constraint" section.
39
+ */
40
+ export declare function extractSeedForCampaign(prd: PrdContent, campaignId: string, platform: string, options?: {
41
+ kongoDomain?: string;
42
+ selfMarketing?: boolean;
43
+ slug?: string;
44
+ }): PrdSeedContent;
45
+ /**
46
+ * Parse PRD text into frontmatter and body.
47
+ * Handles ```yaml fenced frontmatter and --- delimited frontmatter.
48
+ */
49
+ export declare function parsePrdContent(raw: string): PrdContent;
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Kongo Seed — Extract seed content from PRDs for landing page generation.
3
+ *
4
+ * Phase 3.5 of /grow: Before you distribute, you need somewhere to send them.
5
+ *
6
+ * Extracts headline, value props, CTA, brand colors, and social proof from
7
+ * PRD YAML frontmatter and prose content. Maps to PrdSeedContent which
8
+ * feeds into createPageFromPrd().
9
+ *
10
+ * PRD Reference: PRD-kongo-integration.md §4.5
11
+ */
12
+ /**
13
+ * Extract PrdSeedContent from a PRD document.
14
+ *
15
+ * Strategy:
16
+ * 1. Use frontmatter `name` for project name
17
+ * 2. Extract first ## heading or overview section for headline
18
+ * 3. Extract value props from feature descriptions or bullet lists
19
+ * 4. Use brand colors from frontmatter `style` or defaults
20
+ * 5. Extract CTA from conversion or signup references
21
+ */
22
+ export function extractSeedFromPrd(prd) {
23
+ const fm = prd.frontmatter;
24
+ const body = prd.body;
25
+ const projectName = extractProjectName(fm);
26
+ const headline = extractHeadline(fm, body);
27
+ const subheadline = extractSubheadline(fm, body);
28
+ const valueProps = extractValueProps(body);
29
+ const { ctaText, ctaUrl } = extractCta(fm, body);
30
+ const brandColors = extractBrandColors(fm);
31
+ const socialProof = extractSocialProof(body);
32
+ return {
33
+ projectName,
34
+ headline,
35
+ subheadline,
36
+ valueProps,
37
+ ctaText,
38
+ ctaUrl,
39
+ brandColors,
40
+ socialProof: socialProof.length > 0 ? socialProof : undefined,
41
+ };
42
+ }
43
+ /**
44
+ * Extract seed content for a specific campaign.
45
+ * Enriches the base PRD seed with campaign-specific metadata.
46
+ *
47
+ * Self-marketing mode: When the product domain matches the Kongo domain
48
+ * (dogfooding), destination URLs use the /lp/ direct-render path instead
49
+ * of subdomain URLs. This avoids the iframe sandbox constraint that breaks
50
+ * GA4 cookie tracking and UTM relay. See GROWTH_STRATEGIST.md "Iframe
51
+ * Sandbox Constraint" section.
52
+ */
53
+ export function extractSeedForCampaign(prd, campaignId, platform, options) {
54
+ const baseSeed = extractSeedFromPrd(prd);
55
+ const kongoDomain = options?.kongoDomain ?? 'kongo.io';
56
+ const slug = options?.slug ?? slugify(baseSeed.projectName, campaignId);
57
+ const isSelfMarketing = options?.selfMarketing ?? false;
58
+ // Self-marketing: use /lp/ direct-render path (no iframe sandbox)
59
+ // Standard: use subdomain URL
60
+ const destinationUrl = isSelfMarketing
61
+ ? `https://${kongoDomain}/lp/${slug}`
62
+ : `https://${slug}.${kongoDomain}`;
63
+ return {
64
+ ...baseSeed,
65
+ campaignId,
66
+ platform,
67
+ ctaUrl: destinationUrl,
68
+ };
69
+ }
70
+ /** Generate a URL-safe slug from project name and campaign ID */
71
+ function slugify(projectName, campaignId) {
72
+ return `${projectName}-${campaignId}`
73
+ .toLowerCase()
74
+ .replace(/[^a-z0-9-]/g, '-')
75
+ .replace(/-+/g, '-')
76
+ .replace(/^-|-$/g, '');
77
+ }
78
+ // ── Frontmatter Parsing ──────────────────────────────────
79
+ /**
80
+ * Parse PRD text into frontmatter and body.
81
+ * Handles ```yaml fenced frontmatter and --- delimited frontmatter.
82
+ */
83
+ export function parsePrdContent(raw) {
84
+ const lines = raw.split('\n');
85
+ let frontmatterStr = '';
86
+ let bodyStart = 0;
87
+ // Try ```yaml fenced block
88
+ if (lines[0]?.trim() === '```yaml' || lines[0]?.trim() === '---') {
89
+ const delimiter = lines[0].trim() === '```yaml' ? '```' : '---';
90
+ let found = false;
91
+ for (let i = 1; i < lines.length; i++) {
92
+ if (lines[i].trim() === delimiter) {
93
+ bodyStart = i + 1;
94
+ found = true;
95
+ break;
96
+ }
97
+ frontmatterStr += lines[i] + '\n';
98
+ }
99
+ // No closing delimiter — treat as no frontmatter
100
+ if (!found) {
101
+ frontmatterStr = '';
102
+ bodyStart = 0;
103
+ }
104
+ }
105
+ // Simple YAML key: value parsing (no dependency on yaml parser)
106
+ const frontmatter = {};
107
+ for (const line of frontmatterStr.split('\n')) {
108
+ const match = line.match(/^(\w[\w-]*)\s*:\s*(.+)/);
109
+ if (match) {
110
+ const key = match[1];
111
+ let value = match[2].trim();
112
+ // Strip quotes
113
+ if (typeof value === 'string' && value.startsWith('"') && value.endsWith('"')) {
114
+ value = value.slice(1, -1);
115
+ }
116
+ frontmatter[key] = value;
117
+ }
118
+ }
119
+ return {
120
+ frontmatter,
121
+ body: lines.slice(bodyStart).join('\n'),
122
+ };
123
+ }
124
+ // ── Extraction Helpers ───────────────────────────────────
125
+ function extractProjectName(fm) {
126
+ return String(fm.name ?? fm.projectName ?? fm.title ?? 'Untitled Project');
127
+ }
128
+ function extractHeadline(fm, body) {
129
+ // Check frontmatter tagline
130
+ if (fm.tagline)
131
+ return String(fm.tagline);
132
+ // First ## Overview section, or first sentence of body
133
+ const overviewMatch = body.match(/##\s+(?:Overview|Introduction|About)\s*\n+(.+)/i);
134
+ if (overviewMatch) {
135
+ return truncate(overviewMatch[1].trim(), 100);
136
+ }
137
+ // First meaningful paragraph
138
+ const firstParagraph = body.split('\n\n').find(p => p.trim().length > 20 && !p.startsWith('#'));
139
+ if (firstParagraph) {
140
+ return truncate(firstParagraph.split('.')[0].trim(), 100);
141
+ }
142
+ return String(fm.name ?? 'Your Next Big Thing');
143
+ }
144
+ function extractSubheadline(fm, body) {
145
+ if (fm.description)
146
+ return truncate(String(fm.description), 200);
147
+ // Second sentence of overview
148
+ const overviewMatch = body.match(/##\s+(?:Overview|Introduction|About)\s*\n+([\s\S]*?)(?=\n##|\n---)/i);
149
+ if (overviewMatch) {
150
+ const sentences = overviewMatch[1].trim().split(/\.\s+/);
151
+ if (sentences.length > 1)
152
+ return truncate(sentences[1].trim(), 200);
153
+ }
154
+ return `Built with ${String(fm.name ?? 'innovation')}`;
155
+ }
156
+ function extractValueProps(body) {
157
+ const props = [];
158
+ // Look for bullet lists in Features section
159
+ const featuresMatch = body.match(/##\s+(?:Features|Core Features|Key Features|Capabilities)\s*\n([\s\S]*?)(?=\n##|$)/i);
160
+ if (featuresMatch) {
161
+ const bullets = featuresMatch[1].match(/^[-*]\s+(.+)/gm);
162
+ if (bullets) {
163
+ for (const bullet of bullets.slice(0, 5)) {
164
+ props.push(bullet.replace(/^[-*]\s+/, '').trim());
165
+ }
166
+ }
167
+ }
168
+ // Fallback: any bullet lists in the first half of the document
169
+ if (props.length === 0) {
170
+ const halfBody = body.slice(0, body.length / 2);
171
+ const bullets = halfBody.match(/^[-*]\s+(.+)/gm);
172
+ if (bullets) {
173
+ for (const bullet of bullets.slice(0, 5)) {
174
+ props.push(bullet.replace(/^[-*]\s+/, '').trim());
175
+ }
176
+ }
177
+ }
178
+ // Ensure at least 3 value props
179
+ while (props.length < 3) {
180
+ props.push(props.length === 0 ? 'Built for speed' : props.length === 1 ? 'Easy to use' : 'Trusted by teams');
181
+ }
182
+ return props.slice(0, 5);
183
+ }
184
+ function extractCta(fm, body) {
185
+ // Check frontmatter for CTA
186
+ if (fm.ctaText && fm.ctaUrl) {
187
+ return { ctaText: String(fm.ctaText), ctaUrl: String(fm.ctaUrl) };
188
+ }
189
+ // Look for signup/demo/trial references
190
+ const ctaPatterns = [
191
+ { pattern: /sign\s*up|get\s*started|start\s*(free\s*)?trial/i, text: 'Get Started Free' },
192
+ { pattern: /request\s*(a\s*)?demo/i, text: 'Request a Demo' },
193
+ { pattern: /join\s*waitlist/i, text: 'Join the Waitlist' },
194
+ { pattern: /download/i, text: 'Download Now' },
195
+ { pattern: /subscribe/i, text: 'Subscribe' },
196
+ ];
197
+ for (const { pattern, text } of ctaPatterns) {
198
+ if (pattern.test(body))
199
+ return { ctaText: text, ctaUrl: '#signup' };
200
+ }
201
+ return { ctaText: 'Get Started', ctaUrl: '#signup' };
202
+ }
203
+ function extractBrandColors(fm) {
204
+ const style = fm.style;
205
+ const colors = style?.colors;
206
+ return {
207
+ primary: colors?.primary ?? '#1a1a2e',
208
+ secondary: colors?.secondary ?? '#16213e',
209
+ accent: colors?.accent ?? '#0f3460',
210
+ };
211
+ }
212
+ function extractSocialProof(body) {
213
+ const proof = [];
214
+ // Look for testimonials section
215
+ const testimonialsMatch = body.match(/##\s+(?:Testimonials|Social Proof|What .+ Say)\s*\n([\s\S]*?)(?=\n##|$)/i);
216
+ if (testimonialsMatch) {
217
+ const quotes = testimonialsMatch[1].match(/>\s*(.+)/gm);
218
+ if (quotes) {
219
+ for (const quote of quotes.slice(0, 3)) {
220
+ proof.push(quote.replace(/^>\s*/, '').trim());
221
+ }
222
+ }
223
+ }
224
+ // Look for stats
225
+ const statsMatch = body.match(/(\d+[+kKmM]?\s+(?:users|teams|companies|customers|downloads|stars))/gi);
226
+ if (statsMatch) {
227
+ for (const stat of statsMatch.slice(0, 2)) {
228
+ proof.push(stat.trim());
229
+ }
230
+ }
231
+ return proof;
232
+ }
233
+ function truncate(str, maxLen) {
234
+ if (str.length <= maxLen)
235
+ return str;
236
+ return str.slice(0, maxLen - 3) + '...';
237
+ }