godpowers 0.15.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 (444) hide show
  1. package/AGENTS.md +37 -0
  2. package/CHANGELOG.md +639 -0
  3. package/INSPIRATION.md +52 -0
  4. package/LICENSE +21 -0
  5. package/README.md +232 -0
  6. package/SKILL.md +500 -0
  7. package/agents/god-archaeologist.md +139 -0
  8. package/agents/god-architect.md +92 -0
  9. package/agents/god-auditor.md +150 -0
  10. package/agents/god-browser-tester.md +144 -0
  11. package/agents/god-context-writer.md +137 -0
  12. package/agents/god-coordinator.md +138 -0
  13. package/agents/god-debt-assessor.md +132 -0
  14. package/agents/god-debugger.md +77 -0
  15. package/agents/god-deploy-engineer.md +87 -0
  16. package/agents/god-deps-auditor.md +111 -0
  17. package/agents/god-design-reviewer.md +137 -0
  18. package/agents/god-designer.md +171 -0
  19. package/agents/god-docs-writer.md +102 -0
  20. package/agents/god-executor.md +76 -0
  21. package/agents/god-explorer.md +110 -0
  22. package/agents/god-harden-auditor.md +163 -0
  23. package/agents/god-incident-investigator.md +144 -0
  24. package/agents/god-launch-strategist.md +103 -0
  25. package/agents/god-migration-strategist.md +126 -0
  26. package/agents/god-observability-engineer.md +76 -0
  27. package/agents/god-orchestrator.md +728 -0
  28. package/agents/god-org-context-loader.md +124 -0
  29. package/agents/god-planner.md +73 -0
  30. package/agents/god-pm.md +105 -0
  31. package/agents/god-quality-reviewer.md +74 -0
  32. package/agents/god-reconciler.md +230 -0
  33. package/agents/god-reconstructor.md +124 -0
  34. package/agents/god-repo-scaffolder.md +60 -0
  35. package/agents/god-retrospective.md +109 -0
  36. package/agents/god-roadmap-reconciler.md +123 -0
  37. package/agents/god-roadmap-updater.md +89 -0
  38. package/agents/god-roadmapper.md +82 -0
  39. package/agents/god-spec-reviewer.md +70 -0
  40. package/agents/god-spike-runner.md +119 -0
  41. package/agents/god-stack-selector.md +93 -0
  42. package/agents/god-standards-check.md +132 -0
  43. package/agents/god-storyteller.md +116 -0
  44. package/agents/god-updater.md +174 -0
  45. package/bin/install.js +514 -0
  46. package/extensions/data-pack/README.md +33 -0
  47. package/extensions/data-pack/agents/god-dashboard-builder.md +66 -0
  48. package/extensions/data-pack/agents/god-etl-engineer.md +64 -0
  49. package/extensions/data-pack/agents/god-ml-feature-engineer.md +66 -0
  50. package/extensions/data-pack/manifest.yaml +39 -0
  51. package/extensions/data-pack/package.json +42 -0
  52. package/extensions/data-pack/skills/god-dashboard.md +28 -0
  53. package/extensions/data-pack/skills/god-etl.md +28 -0
  54. package/extensions/data-pack/skills/god-ml-feature.md +28 -0
  55. package/extensions/data-pack/workflows/dashboard-arc.yaml +13 -0
  56. package/extensions/data-pack/workflows/etl-arc.yaml +13 -0
  57. package/extensions/data-pack/workflows/ml-feature-arc.yaml +13 -0
  58. package/extensions/launch-pack/README.md +36 -0
  59. package/extensions/launch-pack/agents/god-indie-hackers-strategist.md +128 -0
  60. package/extensions/launch-pack/agents/god-oss-release-strategist.md +125 -0
  61. package/extensions/launch-pack/agents/god-product-hunt-strategist.md +118 -0
  62. package/extensions/launch-pack/agents/god-show-hn-strategist.md +113 -0
  63. package/extensions/launch-pack/manifest.yaml +45 -0
  64. package/extensions/launch-pack/package.json +41 -0
  65. package/extensions/launch-pack/skills/god-indie-hackers.md +39 -0
  66. package/extensions/launch-pack/skills/god-oss-release.md +43 -0
  67. package/extensions/launch-pack/skills/god-product-hunt.md +41 -0
  68. package/extensions/launch-pack/skills/god-show-hn.md +40 -0
  69. package/extensions/launch-pack/workflows/indie-hackers.yaml +13 -0
  70. package/extensions/launch-pack/workflows/oss-release.yaml +13 -0
  71. package/extensions/launch-pack/workflows/product-hunt.yaml +13 -0
  72. package/extensions/launch-pack/workflows/show-hn.yaml +13 -0
  73. package/extensions/security-pack/README.md +48 -0
  74. package/extensions/security-pack/agents/god-hipaa-auditor.md +117 -0
  75. package/extensions/security-pack/agents/god-pci-auditor.md +100 -0
  76. package/extensions/security-pack/agents/god-soc2-auditor.md +107 -0
  77. package/extensions/security-pack/manifest.yaml +39 -0
  78. package/extensions/security-pack/package.json +42 -0
  79. package/extensions/security-pack/skills/god-hipaa-audit.md +41 -0
  80. package/extensions/security-pack/skills/god-pci-audit.md +40 -0
  81. package/extensions/security-pack/skills/god-soc2-audit.md +42 -0
  82. package/extensions/security-pack/workflows/hipaa-arc.yaml +15 -0
  83. package/extensions/security-pack/workflows/pci-arc.yaml +15 -0
  84. package/extensions/security-pack/workflows/soc2-arc.yaml +15 -0
  85. package/hooks/pre-tool-use.sh +40 -0
  86. package/hooks/session-start.sh +74 -0
  87. package/lib/README.md +28 -0
  88. package/lib/agent-browser-driver.js +215 -0
  89. package/lib/agent-cache.js +194 -0
  90. package/lib/agent-validator.js +275 -0
  91. package/lib/artifact-diff.js +168 -0
  92. package/lib/artifact-linter.js +142 -0
  93. package/lib/awesome-design.js +312 -0
  94. package/lib/browser-bridge.js +209 -0
  95. package/lib/budget.js +215 -0
  96. package/lib/checkpoint.js +390 -0
  97. package/lib/code-scanner.js +262 -0
  98. package/lib/context-budget.js +170 -0
  99. package/lib/context-writer.js +348 -0
  100. package/lib/cost-tracker.js +325 -0
  101. package/lib/cross-artifact-impact.js +162 -0
  102. package/lib/cross-repo-linkage.js +150 -0
  103. package/lib/design-detector.js +167 -0
  104. package/lib/design-spec.js +348 -0
  105. package/lib/drift-detector.js +212 -0
  106. package/lib/event-reader.js +174 -0
  107. package/lib/events.js +183 -0
  108. package/lib/extensions.js +257 -0
  109. package/lib/have-nots-validator.js +647 -0
  110. package/lib/impact.js +314 -0
  111. package/lib/impeccable-bridge.js +139 -0
  112. package/lib/intent.js +177 -0
  113. package/lib/linkage.js +232 -0
  114. package/lib/meta-linter.js +263 -0
  115. package/lib/multi-repo-detector.js +182 -0
  116. package/lib/otel-exporter.js +308 -0
  117. package/lib/recipes.js +186 -0
  118. package/lib/reverse-sync.js +332 -0
  119. package/lib/review-required.js +224 -0
  120. package/lib/router.js +278 -0
  121. package/lib/runtime-audit.js +455 -0
  122. package/lib/runtime-test.js +309 -0
  123. package/lib/skillui-bridge.js +216 -0
  124. package/lib/state-lock.js +201 -0
  125. package/lib/state.js +142 -0
  126. package/lib/story-validator.js +301 -0
  127. package/lib/suite-state.js +220 -0
  128. package/lib/workflow-parser.js +109 -0
  129. package/lib/workflow-runner.js +221 -0
  130. package/package.json +63 -0
  131. package/references/HAVE-NOTS.md +573 -0
  132. package/references/building/BUILD-ANTIPATTERNS.md +102 -0
  133. package/references/building/BUILD-VERTICAL-SLICES.md +75 -0
  134. package/references/building/BUILD-WAVES.md +61 -0
  135. package/references/building/README.md +17 -0
  136. package/references/design/COLOR.md +122 -0
  137. package/references/design/DESIGN-ANATOMY.md +121 -0
  138. package/references/design/DESIGN-ANTIPATTERNS.md +108 -0
  139. package/references/design/INTERACTION.md +148 -0
  140. package/references/design/MOTION.md +120 -0
  141. package/references/design/RESPONSIVE.md +157 -0
  142. package/references/design/SPATIAL.md +109 -0
  143. package/references/design/TYPOGRAPHY.md +121 -0
  144. package/references/design/UX-WRITING.md +135 -0
  145. package/references/orchestration/MODE-DETECTION.md +74 -0
  146. package/references/orchestration/README.md +18 -0
  147. package/references/orchestration/SCALE-DETECTION.md +81 -0
  148. package/references/planning/ARCH-ANATOMY.md +143 -0
  149. package/references/planning/ARCH-ANTIPATTERNS.md +52 -0
  150. package/references/planning/PRD-ANATOMY.md +117 -0
  151. package/references/planning/PRD-ANTIPATTERNS.md +138 -0
  152. package/references/planning/README.md +16 -0
  153. package/references/planning/ROADMAP-ANATOMY.md +43 -0
  154. package/references/planning/ROADMAP-ANTIPATTERNS.md +94 -0
  155. package/references/planning/STACK-ANATOMY.md +60 -0
  156. package/references/planning/STACK-ANTIPATTERNS.md +95 -0
  157. package/references/shared/GLOSSARY.md +80 -0
  158. package/references/shared/ORCHESTRATORS.md +76 -0
  159. package/references/shared/README.md +14 -0
  160. package/references/shipping/DEPLOY-ANTIPATTERNS.md +64 -0
  161. package/references/shipping/DEPLOY-PATTERNS.md +110 -0
  162. package/references/shipping/HARDEN-ANTIPATTERNS.md +66 -0
  163. package/references/shipping/HARDEN-OWASP-WORKSHEETS.md +89 -0
  164. package/references/shipping/LAUNCH-ANTIPATTERNS.md +68 -0
  165. package/references/shipping/OBSERVE-ANTIPATTERNS.md +62 -0
  166. package/references/shipping/OBSERVE-SLO-EXAMPLES.md +107 -0
  167. package/references/shipping/README.md +18 -0
  168. package/routing/god-add-backlog.yaml +24 -0
  169. package/routing/god-add-tests.yaml +27 -0
  170. package/routing/god-add-todo.yaml +24 -0
  171. package/routing/god-agent-audit.yaml +24 -0
  172. package/routing/god-arch.yaml +46 -0
  173. package/routing/god-archaeology.yaml +28 -0
  174. package/routing/god-audit.yaml +32 -0
  175. package/routing/god-budget.yaml +24 -0
  176. package/routing/god-build-agent.yaml +24 -0
  177. package/routing/god-build.yaml +46 -0
  178. package/routing/god-cache-clear.yaml +24 -0
  179. package/routing/god-check-todos.yaml +24 -0
  180. package/routing/god-context-scan.yaml +24 -0
  181. package/routing/god-context.yaml +44 -0
  182. package/routing/god-cost.yaml +24 -0
  183. package/routing/god-debug.yaml +28 -0
  184. package/routing/god-deploy.yaml +34 -0
  185. package/routing/god-design-impact.yaml +25 -0
  186. package/routing/god-design.yaml +67 -0
  187. package/routing/god-discuss.yaml +27 -0
  188. package/routing/god-docs.yaml +33 -0
  189. package/routing/god-doctor.yaml +27 -0
  190. package/routing/god-explore.yaml +27 -0
  191. package/routing/god-extension-add.yaml +24 -0
  192. package/routing/god-extension-info.yaml +24 -0
  193. package/routing/god-extension-list.yaml +24 -0
  194. package/routing/god-extension-remove.yaml +24 -0
  195. package/routing/god-extract-learnings.yaml +24 -0
  196. package/routing/god-fast.yaml +27 -0
  197. package/routing/god-feature.yaml +34 -0
  198. package/routing/god-graph.yaml +24 -0
  199. package/routing/god-harden.yaml +41 -0
  200. package/routing/god-help.yaml +27 -0
  201. package/routing/god-hotfix.yaml +34 -0
  202. package/routing/god-hygiene.yaml +28 -0
  203. package/routing/god-init.yaml +37 -0
  204. package/routing/god-intel.yaml +24 -0
  205. package/routing/god-launch.yaml +41 -0
  206. package/routing/god-lifecycle.yaml +27 -0
  207. package/routing/god-link.yaml +24 -0
  208. package/routing/god-lint.yaml +24 -0
  209. package/routing/god-list-assumptions.yaml +27 -0
  210. package/routing/god-locate.yaml +24 -0
  211. package/routing/god-logs.yaml +24 -0
  212. package/routing/god-map-codebase.yaml +24 -0
  213. package/routing/god-metrics.yaml +24 -0
  214. package/routing/god-mode.yaml +31 -0
  215. package/routing/god-next.yaml +27 -0
  216. package/routing/god-note.yaml +24 -0
  217. package/routing/god-observe.yaml +34 -0
  218. package/routing/god-org-context.yaml +28 -0
  219. package/routing/god-party.yaml +24 -0
  220. package/routing/god-pause-work.yaml +27 -0
  221. package/routing/god-plant-seed.yaml +24 -0
  222. package/routing/god-postmortem.yaml +34 -0
  223. package/routing/god-pr-branch.yaml +25 -0
  224. package/routing/god-prd.yaml +49 -0
  225. package/routing/god-quick.yaml +28 -0
  226. package/routing/god-reconcile.yaml +48 -0
  227. package/routing/god-reconstruct.yaml +36 -0
  228. package/routing/god-redo.yaml +27 -0
  229. package/routing/god-refactor.yaml +36 -0
  230. package/routing/god-repair.yaml +27 -0
  231. package/routing/god-repo.yaml +35 -0
  232. package/routing/god-restore.yaml +27 -0
  233. package/routing/god-resume-work.yaml +27 -0
  234. package/routing/god-review-changes.yaml +25 -0
  235. package/routing/god-review.yaml +28 -0
  236. package/routing/god-roadmap-check.yaml +39 -0
  237. package/routing/god-roadmap-update.yaml +37 -0
  238. package/routing/god-roadmap.yaml +42 -0
  239. package/routing/god-rollback.yaml +27 -0
  240. package/routing/god-scan.yaml +24 -0
  241. package/routing/god-set-profile.yaml +24 -0
  242. package/routing/god-settings.yaml +24 -0
  243. package/routing/god-skip.yaml +27 -0
  244. package/routing/god-smite.yaml +29 -0
  245. package/routing/god-spike.yaml +35 -0
  246. package/routing/god-sprint.yaml +25 -0
  247. package/routing/god-stack.yaml +41 -0
  248. package/routing/god-standards.yaml +24 -0
  249. package/routing/god-status.yaml +27 -0
  250. package/routing/god-stories.yaml +24 -0
  251. package/routing/god-story-build.yaml +25 -0
  252. package/routing/god-story-close.yaml +25 -0
  253. package/routing/god-story-verify.yaml +25 -0
  254. package/routing/god-story.yaml +24 -0
  255. package/routing/god-suite-init.yaml +24 -0
  256. package/routing/god-suite-patch.yaml +25 -0
  257. package/routing/god-suite-release.yaml +25 -0
  258. package/routing/god-suite-status.yaml +25 -0
  259. package/routing/god-suite-sync.yaml +25 -0
  260. package/routing/god-sync.yaml +33 -0
  261. package/routing/god-tech-debt.yaml +32 -0
  262. package/routing/god-test-extension.yaml +24 -0
  263. package/routing/god-test-runtime.yaml +25 -0
  264. package/routing/god-thread.yaml +24 -0
  265. package/routing/god-trace.yaml +24 -0
  266. package/routing/god-undo.yaml +27 -0
  267. package/routing/god-update-deps.yaml +39 -0
  268. package/routing/god-upgrade.yaml +33 -0
  269. package/routing/god-version.yaml +24 -0
  270. package/routing/god-workstream.yaml +24 -0
  271. package/routing/god.yaml +24 -0
  272. package/routing/recipes/add-feature-defer-current-milestone.yaml +21 -0
  273. package/routing/recipes/add-feature-future-conditional.yaml +21 -0
  274. package/routing/recipes/add-feature-mid-arc-pause.yaml +33 -0
  275. package/routing/recipes/add-feature-next-milestone.yaml +23 -0
  276. package/routing/recipes/add-feature-parallel.yaml +29 -0
  277. package/routing/recipes/add-feature-prd-update.yaml +21 -0
  278. package/routing/recipes/add-feature-small.yaml +24 -0
  279. package/routing/recipes/add-feature-tiny.yaml +24 -0
  280. package/routing/recipes/bluefield-org-aware.yaml +27 -0
  281. package/routing/recipes/broken-install.yaml +22 -0
  282. package/routing/recipes/brownfield-onboarding.yaml +32 -0
  283. package/routing/recipes/bug-no-urgency.yaml +21 -0
  284. package/routing/recipes/capture-idea.yaml +22 -0
  285. package/routing/recipes/capture-todo.yaml +21 -0
  286. package/routing/recipes/clean-pr.yaml +21 -0
  287. package/routing/recipes/code-cleanup.yaml +23 -0
  288. package/routing/recipes/docs-drift.yaml +21 -0
  289. package/routing/recipes/existing-codebase-onboarding.yaml +32 -0
  290. package/routing/recipes/extract-learnings.yaml +22 -0
  291. package/routing/recipes/greenfield-fast.yaml +25 -0
  292. package/routing/recipes/greenfield-manual.yaml +32 -0
  293. package/routing/recipes/greenfield-with-ideation.yaml +29 -0
  294. package/routing/recipes/incident-postmortem.yaml +24 -0
  295. package/routing/recipes/major-framework-upgrade.yaml +23 -0
  296. package/routing/recipes/monthly-deps.yaml +22 -0
  297. package/routing/recipes/multi-repo-suite.yaml +56 -0
  298. package/routing/recipes/parallel-engineers.yaml +26 -0
  299. package/routing/recipes/pause-handoff.yaml +21 -0
  300. package/routing/recipes/production-broken.yaml +26 -0
  301. package/routing/recipes/rerun-tier.yaml +21 -0
  302. package/routing/recipes/returning-after-break.yaml +31 -0
  303. package/routing/recipes/state-drift.yaml +21 -0
  304. package/routing/recipes/undo-last.yaml +21 -0
  305. package/routing/recipes/weekly-health-check.yaml +24 -0
  306. package/routing/recipes/whats-next.yaml +22 -0
  307. package/routing/recipes/where-am-i.yaml +21 -0
  308. package/schema/events.v1.json +63 -0
  309. package/schema/extension-manifest.v1.json +84 -0
  310. package/schema/intent.v1.yaml.json +116 -0
  311. package/schema/recipe.v1.json +120 -0
  312. package/schema/routing.v1.json +163 -0
  313. package/schema/state.v1.json +146 -0
  314. package/schema/workflow.v1.json +96 -0
  315. package/skills/god-add-backlog.md +40 -0
  316. package/skills/god-add-tests.md +53 -0
  317. package/skills/god-add-todo.md +32 -0
  318. package/skills/god-agent-audit.md +87 -0
  319. package/skills/god-arch.md +81 -0
  320. package/skills/god-archaeology.md +48 -0
  321. package/skills/god-audit.md +65 -0
  322. package/skills/god-budget.md +103 -0
  323. package/skills/god-build-agent.md +91 -0
  324. package/skills/god-build.md +90 -0
  325. package/skills/god-cache-clear.md +75 -0
  326. package/skills/god-check-todos.md +42 -0
  327. package/skills/god-context-scan.md +125 -0
  328. package/skills/god-context.md +147 -0
  329. package/skills/god-cost.md +118 -0
  330. package/skills/god-debug.md +30 -0
  331. package/skills/god-deploy.md +76 -0
  332. package/skills/god-design-impact.md +86 -0
  333. package/skills/god-design.md +275 -0
  334. package/skills/god-discuss.md +46 -0
  335. package/skills/god-docs.md +81 -0
  336. package/skills/god-doctor.md +94 -0
  337. package/skills/god-explore.md +50 -0
  338. package/skills/god-export-otel.md +87 -0
  339. package/skills/god-extension-add.md +79 -0
  340. package/skills/god-extension-info.md +75 -0
  341. package/skills/god-extension-list.md +55 -0
  342. package/skills/god-extension-remove.md +66 -0
  343. package/skills/god-extract-learnings.md +60 -0
  344. package/skills/god-fast.md +47 -0
  345. package/skills/god-feature.md +114 -0
  346. package/skills/god-graph.md +56 -0
  347. package/skills/god-harden.md +106 -0
  348. package/skills/god-help.md +66 -0
  349. package/skills/god-hotfix.md +139 -0
  350. package/skills/god-hygiene.md +104 -0
  351. package/skills/god-init.md +161 -0
  352. package/skills/god-intel.md +36 -0
  353. package/skills/god-launch.md +86 -0
  354. package/skills/god-lifecycle.md +119 -0
  355. package/skills/god-link.md +90 -0
  356. package/skills/god-lint.md +128 -0
  357. package/skills/god-list-assumptions.md +56 -0
  358. package/skills/god-locate.md +97 -0
  359. package/skills/god-logs.md +57 -0
  360. package/skills/god-map-codebase.md +45 -0
  361. package/skills/god-metrics.md +51 -0
  362. package/skills/god-mode.md +159 -0
  363. package/skills/god-next.md +257 -0
  364. package/skills/god-note.md +39 -0
  365. package/skills/god-observe.md +76 -0
  366. package/skills/god-org-context.md +81 -0
  367. package/skills/god-party.md +87 -0
  368. package/skills/god-pause-work.md +64 -0
  369. package/skills/god-plant-seed.md +59 -0
  370. package/skills/god-postmortem.md +103 -0
  371. package/skills/god-pr-branch.md +50 -0
  372. package/skills/god-prd.md +90 -0
  373. package/skills/god-quick.md +50 -0
  374. package/skills/god-reconcile.md +90 -0
  375. package/skills/god-reconstruct.md +72 -0
  376. package/skills/god-redo.md +73 -0
  377. package/skills/god-refactor.md +137 -0
  378. package/skills/god-repair.md +82 -0
  379. package/skills/god-repo.md +49 -0
  380. package/skills/god-restore.md +91 -0
  381. package/skills/god-resume-work.md +42 -0
  382. package/skills/god-review-changes.md +93 -0
  383. package/skills/god-review.md +52 -0
  384. package/skills/god-roadmap-check.md +66 -0
  385. package/skills/god-roadmap-update.md +64 -0
  386. package/skills/god-roadmap.md +77 -0
  387. package/skills/god-rollback.md +88 -0
  388. package/skills/god-scan.md +106 -0
  389. package/skills/god-set-profile.md +58 -0
  390. package/skills/god-settings.md +44 -0
  391. package/skills/god-skip.md +78 -0
  392. package/skills/god-smite.md +86 -0
  393. package/skills/god-spike.md +120 -0
  394. package/skills/god-sprint.md +77 -0
  395. package/skills/god-stack.md +74 -0
  396. package/skills/god-standards.md +62 -0
  397. package/skills/god-status.md +99 -0
  398. package/skills/god-stories.md +60 -0
  399. package/skills/god-story-build.md +76 -0
  400. package/skills/god-story-close.md +82 -0
  401. package/skills/god-story-verify.md +71 -0
  402. package/skills/god-story.md +55 -0
  403. package/skills/god-suite-init.md +75 -0
  404. package/skills/god-suite-patch.md +64 -0
  405. package/skills/god-suite-release.md +58 -0
  406. package/skills/god-suite-status.md +63 -0
  407. package/skills/god-suite-sync.md +49 -0
  408. package/skills/god-sync.md +102 -0
  409. package/skills/god-tech-debt.md +56 -0
  410. package/skills/god-test-extension.md +87 -0
  411. package/skills/god-test-runtime.md +144 -0
  412. package/skills/god-thread.md +39 -0
  413. package/skills/god-trace.md +50 -0
  414. package/skills/god-undo.md +68 -0
  415. package/skills/god-update-deps.md +134 -0
  416. package/skills/god-upgrade.md +139 -0
  417. package/skills/god-version.md +37 -0
  418. package/skills/god-workstream.md +61 -0
  419. package/skills/god.md +207 -0
  420. package/templates/ARCH.md +99 -0
  421. package/templates/DEPS-AUDIT.md +66 -0
  422. package/templates/DESIGN.md +71 -0
  423. package/templates/DOCS-UPDATE-LOG.md +64 -0
  424. package/templates/HARDEN-FINDINGS.md +69 -0
  425. package/templates/MIGRATION.md +86 -0
  426. package/templates/POSTMORTEM.md +88 -0
  427. package/templates/PRD.md +80 -0
  428. package/templates/PROGRESS.md +49 -0
  429. package/templates/ROADMAP.md +47 -0
  430. package/templates/SPIKE.md +72 -0
  431. package/templates/STACK-DECISION.md +61 -0
  432. package/workflows/audit-only.yaml +22 -0
  433. package/workflows/bluefield-arc.yaml +87 -0
  434. package/workflows/brownfield-arc.yaml +44 -0
  435. package/workflows/deps-audit.yaml +56 -0
  436. package/workflows/docs-arc.yaml +22 -0
  437. package/workflows/feature-arc.yaml +59 -0
  438. package/workflows/full-arc.yaml +84 -0
  439. package/workflows/hotfix-arc.yaml +59 -0
  440. package/workflows/hygiene.yaml +43 -0
  441. package/workflows/migration-arc.yaml +73 -0
  442. package/workflows/postmortem.yaml +31 -0
  443. package/workflows/refactor-arc.yaml +59 -0
  444. package/workflows/spike.yaml +23 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Artifact Diff
3
+ *
4
+ * Regression detection between two versions of an artifact. Finds:
5
+ * - Removed sections (regression)
6
+ * - DECISION downgraded to HYPOTHESIS (regression)
7
+ * - Reduced acceptance criteria (regression)
8
+ * - New open questions without resolution (info)
9
+ * - Added sections (info)
10
+ *
11
+ * Public API:
12
+ * diffArtifacts(oldContent, newContent) -> { changes, regression }
13
+ */
14
+
15
+ /**
16
+ * Extract markdown sections (## headings) into a map: { heading: body }.
17
+ */
18
+ function extractSections(content) {
19
+ const sections = {};
20
+ const lines = content.split('\n');
21
+ let currentHeading = null;
22
+ let buffer = [];
23
+ for (const line of lines) {
24
+ const m = line.match(/^##\s+(.+?)\s*$/);
25
+ if (m) {
26
+ if (currentHeading) {
27
+ sections[currentHeading] = buffer.join('\n').trim();
28
+ }
29
+ currentHeading = m[1].trim();
30
+ buffer = [];
31
+ } else if (currentHeading) {
32
+ buffer.push(line);
33
+ }
34
+ }
35
+ if (currentHeading) {
36
+ sections[currentHeading] = buffer.join('\n').trim();
37
+ }
38
+ return sections;
39
+ }
40
+
41
+ /**
42
+ * Count occurrences of label tags ([DECISION], [HYPOTHESIS], etc.) in content.
43
+ */
44
+ function countLabels(content) {
45
+ const counts = {
46
+ DECISION: (content.match(/\[DECISION\]/g) || []).length,
47
+ HYPOTHESIS: (content.match(/\[HYPOTHESIS\]/g) || []).length,
48
+ 'OPEN QUESTION': (content.match(/\[OPEN QUESTION\]/g) || []).length
49
+ };
50
+ return counts;
51
+ }
52
+
53
+ /**
54
+ * Count list items (bullets) in content.
55
+ */
56
+ function countListItems(content) {
57
+ return (content.match(/^[\s]*[-*]\s+/gm) || []).length;
58
+ }
59
+
60
+ /**
61
+ * Diff two artifact versions and detect regressions.
62
+ *
63
+ * Returns:
64
+ * {
65
+ * regression: bool,
66
+ * changes: [{ kind, severity, section, message }]
67
+ * }
68
+ */
69
+ function diffArtifacts(oldContent, newContent) {
70
+ const changes = [];
71
+ const oldSections = extractSections(oldContent);
72
+ const newSections = extractSections(newContent);
73
+
74
+ // Check for removed sections
75
+ for (const heading of Object.keys(oldSections)) {
76
+ if (!(heading in newSections)) {
77
+ changes.push({
78
+ kind: 'section-removed',
79
+ severity: 'error',
80
+ section: heading,
81
+ message: `Section "${heading}" was removed.`
82
+ });
83
+ }
84
+ }
85
+
86
+ // Check for added sections (informational)
87
+ for (const heading of Object.keys(newSections)) {
88
+ if (!(heading in oldSections)) {
89
+ changes.push({
90
+ kind: 'section-added',
91
+ severity: 'info',
92
+ section: heading,
93
+ message: `Section "${heading}" was added.`
94
+ });
95
+ }
96
+ }
97
+
98
+ // Check for label downgrades (DECISION -> HYPOTHESIS) per section
99
+ for (const heading of Object.keys(newSections)) {
100
+ if (!(heading in oldSections)) continue;
101
+ const oldCounts = countLabels(oldSections[heading]);
102
+ const newCounts = countLabels(newSections[heading]);
103
+
104
+ if (newCounts.DECISION < oldCounts.DECISION) {
105
+ const dropped = oldCounts.DECISION - newCounts.DECISION;
106
+ changes.push({
107
+ kind: 'decision-downgraded',
108
+ severity: 'warning',
109
+ section: heading,
110
+ message: `${dropped} [DECISION] tag(s) lost in section "${heading}" (was ${oldCounts.DECISION}, now ${newCounts.DECISION}).`
111
+ });
112
+ }
113
+
114
+ // Reduced acceptance criteria: if list item count drops in MUST/SHOULD requirements
115
+ if (heading.match(/Functional Requirements|Requirements/i)) {
116
+ const oldItems = countListItems(oldSections[heading]);
117
+ const newItems = countListItems(newSections[heading]);
118
+ if (newItems < oldItems) {
119
+ changes.push({
120
+ kind: 'acceptance-reduced',
121
+ severity: 'warning',
122
+ section: heading,
123
+ message: `Acceptance criteria reduced in "${heading}" (${oldItems} -> ${newItems} items).`
124
+ });
125
+ }
126
+ }
127
+
128
+ // New open questions without resolution
129
+ if (heading.match(/Open Questions/i)) {
130
+ const oldOQ = oldCounts['OPEN QUESTION'];
131
+ const newOQ = newCounts['OPEN QUESTION'];
132
+ if (newOQ > oldOQ) {
133
+ changes.push({
134
+ kind: 'open-question-added',
135
+ severity: 'info',
136
+ section: heading,
137
+ message: `${newOQ - oldOQ} new open question(s) added.`
138
+ });
139
+ }
140
+ }
141
+ }
142
+
143
+ // Determine regression: any error or warning is a regression
144
+ const regression = changes.some(c => c.severity === 'error' || c.severity === 'warning');
145
+
146
+ return { regression, changes };
147
+ }
148
+
149
+ /**
150
+ * Format diff as human-readable report.
151
+ */
152
+ function formatDiff(diff) {
153
+ const lines = [];
154
+ lines.push(`Regression: ${diff.regression ? 'YES' : 'no'}`);
155
+ lines.push(`Changes: ${diff.changes.length}`);
156
+ for (const c of diff.changes) {
157
+ lines.push(` [${c.kind}] ${c.severity.toUpperCase()} (${c.section}): ${c.message}`);
158
+ }
159
+ return lines.join('\n');
160
+ }
161
+
162
+ module.exports = {
163
+ diffArtifacts,
164
+ extractSections,
165
+ countLabels,
166
+ countListItems,
167
+ formatDiff
168
+ };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Artifact Linter
3
+ *
4
+ * Orchestrator for per-artifact lint runs. Detects artifact type from path,
5
+ * loads the file, runs the right have-nots checks, returns structured
6
+ * findings.
7
+ *
8
+ * Public API:
9
+ * detectType(filePath) -> 'prd'|'arch'|'roadmap'|'stack'|'design'|'product'|null
10
+ * lintFile(filePath, opts) -> { type, findings, summary }
11
+ * lintAll(projectRoot, opts) -> [{ path, type, findings, summary }, ...]
12
+ *
13
+ * Findings structure:
14
+ * { code, severity, line, column, message, suggestion }
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const validator = require('./have-nots-validator');
20
+
21
+ /**
22
+ * Detect artifact type from path. Returns null for unknown.
23
+ */
24
+ function detectType(filePath) {
25
+ const lower = filePath.toLowerCase();
26
+ const basename = path.basename(lower);
27
+ if (lower.includes('/prd/') || basename === 'prd.md') return 'prd';
28
+ if (lower.includes('/arch/') || basename === 'arch.md') return 'arch';
29
+ if (lower.includes('/roadmap/') || basename === 'roadmap.md') return 'roadmap';
30
+ if (lower.includes('/stack/') || basename === 'stack-decision.md' || basename === 'decision.md') return 'stack';
31
+ if (basename === 'design.md') return 'design';
32
+ if (basename === 'product.md') return 'product';
33
+ if (basename === 'postmortem.md') return 'postmortem';
34
+ if (basename === 'spike.md') return 'spike';
35
+ if (basename === 'migration.md') return 'migration';
36
+ return null;
37
+ }
38
+
39
+ /**
40
+ * Lint a single file. Returns { type, findings, summary }.
41
+ */
42
+ function lintFile(filePath, opts = {}) {
43
+ if (!fs.existsSync(filePath)) {
44
+ throw new Error(`File not found: ${filePath}`);
45
+ }
46
+ const content = fs.readFileSync(filePath, 'utf8');
47
+ const type = detectType(filePath);
48
+ const ctx = {
49
+ projectRoot: opts.projectRoot || process.cwd(),
50
+ docDir: path.dirname(filePath),
51
+ today: opts.today,
52
+ prdContent: opts.prdContent,
53
+ ...opts
54
+ };
55
+
56
+ // For ARCH, auto-load PRD if not provided
57
+ if (type === 'arch' && !ctx.prdContent) {
58
+ const prdPath = path.join(ctx.projectRoot, '.godpowers', 'prd', 'PRD.md');
59
+ if (fs.existsSync(prdPath)) {
60
+ ctx.prdContent = fs.readFileSync(prdPath, 'utf8');
61
+ }
62
+ }
63
+
64
+ const findings = validator.runChecks(content, type, ctx);
65
+ const summary = validator.summarize(findings);
66
+
67
+ return {
68
+ path: filePath,
69
+ type: type || 'unknown',
70
+ findings,
71
+ summary
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Lint all known artifacts in a project.
77
+ */
78
+ function lintAll(projectRoot, opts = {}) {
79
+ const root = projectRoot || process.cwd();
80
+ const candidates = [
81
+ '.godpowers/prd/PRD.md',
82
+ '.godpowers/arch/ARCH.md',
83
+ '.godpowers/roadmap/ROADMAP.md',
84
+ '.godpowers/stack/DECISION.md',
85
+ '.godpowers/design/DESIGN.md',
86
+ 'DESIGN.md',
87
+ 'PRODUCT.md'
88
+ ];
89
+ const results = [];
90
+ for (const rel of candidates) {
91
+ const full = path.join(root, rel);
92
+ if (fs.existsSync(full)) {
93
+ results.push(lintFile(full, { projectRoot: root, ...opts }));
94
+ }
95
+ }
96
+ return results;
97
+ }
98
+
99
+ /**
100
+ * Format findings as a human-readable report string.
101
+ */
102
+ function formatReport(result) {
103
+ const lines = [];
104
+ lines.push(`\n${result.path}`);
105
+ lines.push(` Type: ${result.type}`);
106
+ lines.push(` Errors: ${result.summary.errors}, Warnings: ${result.summary.warnings}, Info: ${result.summary.infos}`);
107
+ if (result.findings.length === 0) {
108
+ lines.push(' Clean: no findings.');
109
+ return lines.join('\n');
110
+ }
111
+ for (const f of result.findings) {
112
+ lines.push(` [${f.code}] ${f.severity.toUpperCase()} line ${f.line}: ${f.message}`);
113
+ if (f.suggestion) {
114
+ lines.push(` -> ${f.suggestion}`);
115
+ }
116
+ }
117
+ return lines.join('\n');
118
+ }
119
+
120
+ /**
121
+ * Aggregate summary across multiple lint results.
122
+ */
123
+ function aggregate(results) {
124
+ const totals = { errors: 0, warnings: 0, infos: 0, byCode: {}, files: results.length };
125
+ for (const r of results) {
126
+ totals.errors += r.summary.errors;
127
+ totals.warnings += r.summary.warnings;
128
+ totals.infos += r.summary.infos;
129
+ for (const code of Object.keys(r.summary.byCode)) {
130
+ totals.byCode[code] = (totals.byCode[code] || 0) + r.summary.byCode[code];
131
+ }
132
+ }
133
+ return totals;
134
+ }
135
+
136
+ module.exports = {
137
+ detectType,
138
+ lintFile,
139
+ lintAll,
140
+ formatReport,
141
+ aggregate
142
+ };
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Awesome DESIGN.md catalog integration
3
+ *
4
+ * Detect when a user's PRD / PRODUCT.md / free-text intent mentions a
5
+ * known site, then offer the corresponding curated DESIGN.md from
6
+ * VoltAgent's awesome-design-md collection
7
+ * (https://github.com/VoltAgent/awesome-design-md, MIT license).
8
+ *
9
+ * Strategy:
10
+ * - Fixed catalog of 71 slugs (matches the repo as of 2026-05-10)
11
+ * - Per-project cache at .godpowers/cache/awesome-design/<slug>.md
12
+ * - Fetch lazily (no upfront vendoring)
13
+ * - Identify mentions via case-insensitive name + display-name match
14
+ *
15
+ * Public API:
16
+ * list() -> [{ slug, displayName, category, url }, ...]
17
+ * lookupSite(name) -> entry or null
18
+ * extractSiteReferences(text) -> [...entries]
19
+ * cachePath(projectRoot, slug) -> string
20
+ * isCached(projectRoot, slug) -> bool
21
+ * fetchDesign(projectRoot, slug, opts) -> { content, cached, error }
22
+ */
23
+
24
+ const fs = require('fs');
25
+ const path = require('path');
26
+ const https = require('https');
27
+
28
+ const RAW_BASE = 'https://raw.githubusercontent.com/VoltAgent/awesome-design-md/main/design-md';
29
+ const PREVIEW_BASE = 'https://getdesign.md';
30
+
31
+ /**
32
+ * Catalog. Each entry has:
33
+ * slug - the URL slug used in the repo (e.g., 'linear.app')
34
+ * displayName - the human-readable name shown in README
35
+ * category - one of: ai-llm, dev-tools, backend-data, productivity,
36
+ * design-tools, fintech, ecommerce, media-consumer, automotive
37
+ * aliases - array of common forms (lowercased, no spaces)
38
+ */
39
+ const CATALOG = [
40
+ // AI & LLM Platforms
41
+ { slug: 'claude', displayName: 'Claude', category: 'ai-llm', aliases: ['claude', 'anthropic'] },
42
+ { slug: 'cohere', displayName: 'Cohere', category: 'ai-llm', aliases: ['cohere'] },
43
+ { slug: 'elevenlabs', displayName: 'ElevenLabs', category: 'ai-llm', aliases: ['elevenlabs', '11labs'] },
44
+ { slug: 'minimax', displayName: 'Minimax', category: 'ai-llm', aliases: ['minimax'] },
45
+ { slug: 'mistral.ai', displayName: 'Mistral AI', category: 'ai-llm', aliases: ['mistral', 'mistralai', 'mistral-ai'] },
46
+ { slug: 'ollama', displayName: 'Ollama', category: 'ai-llm', aliases: ['ollama'] },
47
+ { slug: 'opencode.ai', displayName: 'OpenCode AI', category: 'ai-llm', aliases: ['opencode', 'opencodeai'] },
48
+ { slug: 'replicate', displayName: 'Replicate', category: 'ai-llm', aliases: ['replicate'] },
49
+ { slug: 'runwayml', displayName: 'Runway', category: 'ai-llm', aliases: ['runway', 'runwayml'] },
50
+ { slug: 'together.ai', displayName: 'Together AI', category: 'ai-llm', aliases: ['together', 'togetherai', 'together-ai'] },
51
+ { slug: 'voltagent', displayName: 'VoltAgent', category: 'ai-llm', aliases: ['voltagent'] },
52
+ { slug: 'x.ai', displayName: 'xAI', category: 'ai-llm', aliases: ['xai', 'x-ai', 'x.ai', 'grok'] },
53
+
54
+ // Developer Tools & IDEs
55
+ { slug: 'cursor', displayName: 'Cursor', category: 'dev-tools', aliases: ['cursor'] },
56
+ { slug: 'expo', displayName: 'Expo', category: 'dev-tools', aliases: ['expo'] },
57
+ { slug: 'lovable', displayName: 'Lovable', category: 'dev-tools', aliases: ['lovable'] },
58
+ { slug: 'raycast', displayName: 'Raycast', category: 'dev-tools', aliases: ['raycast'] },
59
+ { slug: 'superhuman', displayName: 'Superhuman', category: 'dev-tools', aliases: ['superhuman'] },
60
+ { slug: 'vercel', displayName: 'Vercel', category: 'dev-tools', aliases: ['vercel'] },
61
+ { slug: 'warp', displayName: 'Warp', category: 'dev-tools', aliases: ['warp'] },
62
+
63
+ // Backend, Database & DevOps
64
+ { slug: 'clickhouse', displayName: 'ClickHouse', category: 'backend-data', aliases: ['clickhouse'] },
65
+ { slug: 'composio', displayName: 'Composio', category: 'backend-data', aliases: ['composio'] },
66
+ { slug: 'hashicorp', displayName: 'HashiCorp', category: 'backend-data', aliases: ['hashicorp'] },
67
+ { slug: 'mongodb', displayName: 'MongoDB', category: 'backend-data', aliases: ['mongodb', 'mongo'] },
68
+ { slug: 'posthog', displayName: 'PostHog', category: 'backend-data', aliases: ['posthog'] },
69
+ { slug: 'sanity', displayName: 'Sanity', category: 'backend-data', aliases: ['sanity'] },
70
+ { slug: 'sentry', displayName: 'Sentry', category: 'backend-data', aliases: ['sentry'] },
71
+ { slug: 'supabase', displayName: 'Supabase', category: 'backend-data', aliases: ['supabase'] },
72
+
73
+ // Productivity & SaaS
74
+ { slug: 'cal', displayName: 'Cal.com', category: 'productivity', aliases: ['cal', 'calcom', 'cal.com'] },
75
+ { slug: 'intercom', displayName: 'Intercom', category: 'productivity', aliases: ['intercom'] },
76
+ { slug: 'linear.app', displayName: 'Linear', category: 'productivity', aliases: ['linear', 'linear.app', 'linearapp'] },
77
+ { slug: 'mintlify', displayName: 'Mintlify', category: 'productivity', aliases: ['mintlify'] },
78
+ { slug: 'notion', displayName: 'Notion', category: 'productivity', aliases: ['notion'] },
79
+ { slug: 'resend', displayName: 'Resend', category: 'productivity', aliases: ['resend'] },
80
+ { slug: 'slack', displayName: 'Slack', category: 'productivity', aliases: ['slack'] },
81
+ { slug: 'zapier', displayName: 'Zapier', category: 'productivity', aliases: ['zapier'] },
82
+
83
+ // Design & Creative Tools
84
+ { slug: 'airtable', displayName: 'Airtable', category: 'design-tools', aliases: ['airtable'] },
85
+ { slug: 'clay', displayName: 'Clay', category: 'design-tools', aliases: ['clay'] },
86
+ { slug: 'figma', displayName: 'Figma', category: 'design-tools', aliases: ['figma'] },
87
+ { slug: 'framer', displayName: 'Framer', category: 'design-tools', aliases: ['framer'] },
88
+ { slug: 'miro', displayName: 'Miro', category: 'design-tools', aliases: ['miro'] },
89
+ { slug: 'webflow', displayName: 'Webflow', category: 'design-tools', aliases: ['webflow'] },
90
+
91
+ // Fintech & Crypto
92
+ { slug: 'binance', displayName: 'Binance', category: 'fintech', aliases: ['binance'] },
93
+ { slug: 'coinbase', displayName: 'Coinbase', category: 'fintech', aliases: ['coinbase'] },
94
+ { slug: 'kraken', displayName: 'Kraken', category: 'fintech', aliases: ['kraken'] },
95
+ { slug: 'mastercard', displayName: 'Mastercard', category: 'fintech', aliases: ['mastercard'] },
96
+ { slug: 'revolut', displayName: 'Revolut', category: 'fintech', aliases: ['revolut'] },
97
+ { slug: 'stripe', displayName: 'Stripe', category: 'fintech', aliases: ['stripe'] },
98
+ { slug: 'wise', displayName: 'Wise', category: 'fintech', aliases: ['wise'] },
99
+
100
+ // E-commerce & Retail
101
+ { slug: 'airbnb', displayName: 'Airbnb', category: 'ecommerce', aliases: ['airbnb'] },
102
+ { slug: 'meta', displayName: 'Meta', category: 'ecommerce', aliases: ['meta'] },
103
+ { slug: 'nike', displayName: 'Nike', category: 'ecommerce', aliases: ['nike'] },
104
+ { slug: 'shopify', displayName: 'Shopify', category: 'ecommerce', aliases: ['shopify'] },
105
+ { slug: 'starbucks', displayName: 'Starbucks', category: 'ecommerce', aliases: ['starbucks'] },
106
+
107
+ // Media & Consumer Tech
108
+ { slug: 'apple', displayName: 'Apple', category: 'media-consumer', aliases: ['apple'] },
109
+ { slug: 'ibm', displayName: 'IBM', category: 'media-consumer', aliases: ['ibm'] },
110
+ { slug: 'nvidia', displayName: 'NVIDIA', category: 'media-consumer', aliases: ['nvidia'] },
111
+ { slug: 'pinterest', displayName: 'Pinterest', category: 'media-consumer', aliases: ['pinterest'] },
112
+ { slug: 'playstation', displayName: 'PlayStation', category: 'media-consumer', aliases: ['playstation', 'ps5', 'sony'] },
113
+ { slug: 'spacex', displayName: 'SpaceX', category: 'media-consumer', aliases: ['spacex'] },
114
+ { slug: 'spotify', displayName: 'Spotify', category: 'media-consumer', aliases: ['spotify'] },
115
+ { slug: 'theverge', displayName: 'The Verge', category: 'media-consumer', aliases: ['theverge', 'verge', 'the verge', 'the-verge'] },
116
+ { slug: 'uber', displayName: 'Uber', category: 'media-consumer', aliases: ['uber'] },
117
+ { slug: 'vodafone', displayName: 'Vodafone', category: 'media-consumer', aliases: ['vodafone'] },
118
+ { slug: 'wired', displayName: 'WIRED', category: 'media-consumer', aliases: ['wired'] },
119
+
120
+ // Automotive
121
+ { slug: 'bmw', displayName: 'BMW', category: 'automotive', aliases: ['bmw'] },
122
+ { slug: 'bmw-m', displayName: 'BMW M', category: 'automotive', aliases: ['bmw m', 'bmwm', 'bmw-m'] },
123
+ { slug: 'bugatti', displayName: 'Bugatti', category: 'automotive', aliases: ['bugatti'] },
124
+ { slug: 'ferrari', displayName: 'Ferrari', category: 'automotive', aliases: ['ferrari'] },
125
+ { slug: 'lamborghini', displayName: 'Lamborghini', category: 'automotive', aliases: ['lamborghini', 'lambo'] },
126
+ { slug: 'renault', displayName: 'Renault', category: 'automotive', aliases: ['renault'] },
127
+ { slug: 'tesla', displayName: 'Tesla', category: 'automotive', aliases: ['tesla'] }
128
+ ];
129
+
130
+ /**
131
+ * Return the full list with URLs.
132
+ */
133
+ function list() {
134
+ return CATALOG.map(entry => ({
135
+ ...entry,
136
+ rawUrl: `${RAW_BASE}/${entry.slug}/DESIGN.md`,
137
+ previewUrl: `${PREVIEW_BASE}/${entry.slug}/design-md`
138
+ }));
139
+ }
140
+
141
+ /**
142
+ * Normalize a name for matching: lowercase, strip whitespace and punctuation.
143
+ */
144
+ function normalize(name) {
145
+ return String(name || '')
146
+ .toLowerCase()
147
+ .replace(/[\s.\-_]+/g, '')
148
+ .trim();
149
+ }
150
+
151
+ /**
152
+ * Look up a site by name. Matches against displayName + aliases (case
153
+ * insensitive, punctuation-insensitive).
154
+ */
155
+ function lookupSite(name) {
156
+ const norm = normalize(name);
157
+ if (!norm) return null;
158
+ for (const entry of CATALOG) {
159
+ if (normalize(entry.displayName) === norm) {
160
+ return { ...entry, matchedOn: 'displayName' };
161
+ }
162
+ if (normalize(entry.slug) === norm) {
163
+ return { ...entry, matchedOn: 'slug' };
164
+ }
165
+ for (const alias of entry.aliases) {
166
+ if (normalize(alias) === norm) {
167
+ return { ...entry, matchedOn: 'alias' };
168
+ }
169
+ }
170
+ }
171
+ return null;
172
+ }
173
+
174
+ /**
175
+ * Scan free text for mentions of known sites. Returns deduplicated entries.
176
+ *
177
+ * Looks for:
178
+ * - Direct mentions of displayName / slug / aliases (word-boundary)
179
+ * - Phrases like "feel like X", "similar to X", "looks like X"
180
+ */
181
+ function extractSiteReferences(text) {
182
+ if (!text) return [];
183
+ const found = new Map();
184
+ const lower = String(text).toLowerCase();
185
+
186
+ for (const entry of CATALOG) {
187
+ const candidates = [entry.displayName, entry.slug, ...entry.aliases];
188
+ for (const candidate of candidates) {
189
+ const normCand = candidate.toLowerCase();
190
+ if (normCand.length < 3) continue; // skip too-short tokens
191
+ // Word-boundary regex (escape special chars)
192
+ const escaped = candidate.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').toLowerCase();
193
+ const regex = new RegExp(`\\b${escaped}\\b`, 'i');
194
+ if (regex.test(lower)) {
195
+ if (!found.has(entry.slug)) {
196
+ found.set(entry.slug, {
197
+ ...entry,
198
+ matchedTerm: candidate,
199
+ rawUrl: `${RAW_BASE}/${entry.slug}/DESIGN.md`,
200
+ previewUrl: `${PREVIEW_BASE}/${entry.slug}/design-md`
201
+ });
202
+ }
203
+ break; // first match per entry is enough
204
+ }
205
+ }
206
+ }
207
+ return [...found.values()];
208
+ }
209
+
210
+ /**
211
+ * Cache file path for a given slug in a project.
212
+ */
213
+ function cachePath(projectRoot, slug) {
214
+ return path.join(projectRoot, '.godpowers', 'cache', 'awesome-design', `${slug}.md`);
215
+ }
216
+
217
+ function isCached(projectRoot, slug) {
218
+ return fs.existsSync(cachePath(projectRoot, slug));
219
+ }
220
+
221
+ /**
222
+ * Fetch a DESIGN.md by slug. Synchronous-style API using callbacks
223
+ * because Node's https is callback-based and we don't want to require
224
+ * Promise wrappers for tests. Returns a Promise for runtime use.
225
+ */
226
+ function fetchDesign(projectRoot, slug, opts = {}) {
227
+ return new Promise((resolve) => {
228
+ const cached = cachePath(projectRoot, slug);
229
+ if (!opts.refresh && fs.existsSync(cached)) {
230
+ try {
231
+ return resolve({
232
+ content: fs.readFileSync(cached, 'utf8'),
233
+ cached: true,
234
+ error: null
235
+ });
236
+ } catch (e) {
237
+ return resolve({ content: '', cached: false, error: e.message });
238
+ }
239
+ }
240
+ const url = `${RAW_BASE}/${slug}/DESIGN.md`;
241
+ https.get(url, (res) => {
242
+ if (res.statusCode !== 200) {
243
+ return resolve({ content: '', cached: false, error: `HTTP ${res.statusCode}` });
244
+ }
245
+ let data = '';
246
+ res.on('data', chunk => { data += chunk; });
247
+ res.on('end', () => {
248
+ try {
249
+ fs.mkdirSync(path.dirname(cached), { recursive: true });
250
+ fs.writeFileSync(cached, data);
251
+ } catch (e) {
252
+ // Cache failure non-fatal; still return content
253
+ }
254
+ resolve({ content: data, cached: false, error: null });
255
+ });
256
+ }).on('error', (err) => {
257
+ resolve({ content: '', cached: false, error: err.message });
258
+ });
259
+ });
260
+ }
261
+
262
+ /**
263
+ * Suggest sites that might fit a brand description (heuristic).
264
+ * E.g., "minimal dark dev tool" -> Linear, Vercel, Cursor.
265
+ */
266
+ function suggestByBrandHints(text) {
267
+ if (!text) return [];
268
+ const lower = String(text).toLowerCase();
269
+ const suggestions = [];
270
+
271
+ const rules = [
272
+ { keywords: ['minimal', 'minimalist', 'dark dev'], slugs: ['linear.app', 'vercel', 'cursor'] },
273
+ { keywords: ['warm', 'editorial', 'serif'], slugs: ['notion', 'wired', 'theverge'] },
274
+ { keywords: ['fintech', 'payment', 'banking'], slugs: ['stripe', 'wise', 'revolut'] },
275
+ { keywords: ['ai assistant', 'llm', 'chat'], slugs: ['claude', 'cohere', 'mistral.ai'] },
276
+ { keywords: ['e-commerce', 'shop', 'retail'], slugs: ['shopify', 'airbnb'] },
277
+ { keywords: ['developer tools', 'devops'], slugs: ['vercel', 'supabase', 'sentry'] },
278
+ { keywords: ['terminal', 'code editor'], slugs: ['warp', 'cursor', 'raycast'] },
279
+ { keywords: ['premium', 'luxury'], slugs: ['apple', 'tesla', 'ferrari'] }
280
+ ];
281
+
282
+ for (const rule of rules) {
283
+ if (rule.keywords.some(k => lower.includes(k))) {
284
+ for (const slug of rule.slugs) {
285
+ const entry = CATALOG.find(e => e.slug === slug);
286
+ if (entry && !suggestions.find(s => s.slug === slug)) {
287
+ suggestions.push({
288
+ ...entry,
289
+ rawUrl: `${RAW_BASE}/${entry.slug}/DESIGN.md`,
290
+ previewUrl: `${PREVIEW_BASE}/${entry.slug}/design-md`,
291
+ reason: `matched keyword "${rule.keywords.find(k => lower.includes(k))}"`
292
+ });
293
+ }
294
+ }
295
+ }
296
+ }
297
+ return suggestions;
298
+ }
299
+
300
+ module.exports = {
301
+ CATALOG,
302
+ RAW_BASE,
303
+ PREVIEW_BASE,
304
+ list,
305
+ lookupSite,
306
+ extractSiteReferences,
307
+ suggestByBrandHints,
308
+ cachePath,
309
+ isCached,
310
+ fetchDesign,
311
+ normalize
312
+ };