@synapta/skills 0.1.1 → 0.2.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 (354) hide show
  1. package/dist/index.js +11 -4
  2. package/package.json +3 -4
  3. package/skills/ATTRIBUTION.md +80 -0
  4. package/skills/accessibility-audit/SKILL.md +325 -0
  5. package/skills/accessibility-audit/reference/wcag-checklist.md +103 -0
  6. package/skills/apns-notifier/SKILL.md +86 -0
  7. package/skills/approval-policy-enforcer/SKILL.md +66 -0
  8. package/skills/apps-sdk-builder/LICENSE.txt +201 -0
  9. package/skills/apps-sdk-builder/SKILL.md +328 -0
  10. package/skills/apps-sdk-builder/agents/openai.yaml +13 -0
  11. package/skills/apps-sdk-builder/references/app-archetypes.md +132 -0
  12. package/skills/apps-sdk-builder/references/apps-sdk-docs-workflow.md +135 -0
  13. package/skills/apps-sdk-builder/references/interactive-state-sync-patterns.md +113 -0
  14. package/skills/apps-sdk-builder/references/repo-contract-and-validation.md +93 -0
  15. package/skills/apps-sdk-builder/references/search-fetch-standard.md +67 -0
  16. package/skills/apps-sdk-builder/references/upstream-example-workflow.md +79 -0
  17. package/skills/apps-sdk-builder/references/window-openai-patterns.md +79 -0
  18. package/skills/apps-sdk-builder/scripts/scaffold_node_ext_apps.mjs +606 -0
  19. package/skills/architecture-selector/SKILL.md +64 -0
  20. package/skills/backlog-planner/SKILL.md +68 -0
  21. package/skills/carplay-entitlement-checker/SKILL.md +82 -0
  22. package/skills/concept-deepener/SKILL.md +86 -0
  23. package/skills/concept-discovery/SKILL.md +517 -0
  24. package/skills/concept-discovery/assets/sample-analysis.json +81 -0
  25. package/skills/concept-discovery/expected_outputs/sample-enum-dictionary.md +25 -0
  26. package/skills/concept-discovery/expected_outputs/sample-page-user-list.md +83 -0
  27. package/skills/concept-discovery/expected_outputs/sample-prd-readme.md +43 -0
  28. package/skills/concept-discovery/references/framework-patterns.md +228 -0
  29. package/skills/concept-discovery/references/prd-quality-checklist.md +65 -0
  30. package/skills/concept-discovery/scripts/codebase_analyzer.py +732 -0
  31. package/skills/concept-discovery/scripts/prd_scaffolder.py +435 -0
  32. package/skills/dast-zap/SKILL.md +453 -0
  33. package/skills/dast-zap/assets/.gitkeep +9 -0
  34. package/skills/dast-zap/assets/github_action.yml +207 -0
  35. package/skills/dast-zap/assets/gitlab_ci.yml +226 -0
  36. package/skills/dast-zap/assets/zap_automation.yaml +196 -0
  37. package/skills/dast-zap/assets/zap_context.xml +192 -0
  38. package/skills/dast-zap/references/EXAMPLE.md +40 -0
  39. package/skills/dast-zap/references/api_testing_guide.md +475 -0
  40. package/skills/dast-zap/references/authentication_guide.md +431 -0
  41. package/skills/dast-zap/references/false_positive_handling.md +427 -0
  42. package/skills/dast-zap/references/owasp_mapping.md +255 -0
  43. package/skills/dep-sbom-scan/SKILL.md +466 -0
  44. package/skills/deploy-cloudflare/SKILL.md +930 -0
  45. package/skills/deploy-docker/SKILL.md +55 -0
  46. package/skills/deploy-fly/SKILL.md +228 -0
  47. package/skills/deploy-k8s/SKILL.md +108 -0
  48. package/skills/deploy-k8s/assets/logo.png +0 -0
  49. package/skills/deploy-k8s/docs/README.md +29 -0
  50. package/skills/deploy-k8s/docs/SUMMARY.md +56 -0
  51. package/skills/deploy-k8s/docs/advanced/token-efficiency.md +61 -0
  52. package/skills/deploy-k8s/docs/architecture/multi-tenancy.md +96 -0
  53. package/skills/deploy-k8s/docs/architecture/storage-and-state.md +102 -0
  54. package/skills/deploy-k8s/docs/architecture/workload-patterns.md +87 -0
  55. package/skills/deploy-k8s/docs/book.json +16 -0
  56. package/skills/deploy-k8s/docs/community/changelog.md +34 -0
  57. package/skills/deploy-k8s/docs/community/contributing.md +67 -0
  58. package/skills/deploy-k8s/docs/core-concepts/failure-modes.md +153 -0
  59. package/skills/deploy-k8s/docs/core-concepts/philosophy.md +83 -0
  60. package/skills/deploy-k8s/docs/core-concepts/workflow.md +124 -0
  61. package/skills/deploy-k8s/docs/examples/bad-patterns.md +47 -0
  62. package/skills/deploy-k8s/docs/examples/do-dont-checklist.md +37 -0
  63. package/skills/deploy-k8s/docs/examples/good-patterns.md +49 -0
  64. package/skills/deploy-k8s/docs/failure-modes/api-drift.md +104 -0
  65. package/skills/deploy-k8s/docs/failure-modes/fragile-rollouts.md +99 -0
  66. package/skills/deploy-k8s/docs/failure-modes/insecure-workload-defaults.md +80 -0
  67. package/skills/deploy-k8s/docs/failure-modes/network-exposure.md +98 -0
  68. package/skills/deploy-k8s/docs/failure-modes/privilege-sprawl.md +91 -0
  69. package/skills/deploy-k8s/docs/failure-modes/resource-starvation.md +85 -0
  70. package/skills/deploy-k8s/docs/getting-started/installation.md +152 -0
  71. package/skills/deploy-k8s/docs/getting-started/quick-start.md +115 -0
  72. package/skills/deploy-k8s/docs/guides/helm-patterns.md +71 -0
  73. package/skills/deploy-k8s/docs/guides/kustomize-patterns.md +65 -0
  74. package/skills/deploy-k8s/docs/guides/observability.md +67 -0
  75. package/skills/deploy-k8s/docs/guides/security-hardening.md +59 -0
  76. package/skills/deploy-k8s/docs/guides/validation-and-policy.md +66 -0
  77. package/skills/deploy-k8s/docs/integrations/mcp-integration.md +52 -0
  78. package/skills/deploy-k8s/docs/package-lock.json +2892 -0
  79. package/skills/deploy-k8s/docs/package.json +13 -0
  80. package/skills/deploy-k8s/references/api-drift.md +298 -0
  81. package/skills/deploy-k8s/references/conditional/aks-patterns.md +70 -0
  82. package/skills/deploy-k8s/references/conditional/eks-patterns.md +79 -0
  83. package/skills/deploy-k8s/references/conditional/gitops-controllers.md +71 -0
  84. package/skills/deploy-k8s/references/conditional/gke-patterns.md +74 -0
  85. package/skills/deploy-k8s/references/conditional/observability-stacks.md +80 -0
  86. package/skills/deploy-k8s/references/conditional/openshift-patterns.md +67 -0
  87. package/skills/deploy-k8s/references/daemonset-operator-patterns.md +155 -0
  88. package/skills/deploy-k8s/references/deployment-patterns.md +146 -0
  89. package/skills/deploy-k8s/references/do-dont-patterns.md +87 -0
  90. package/skills/deploy-k8s/references/examples-bad.md +282 -0
  91. package/skills/deploy-k8s/references/examples-good.md +440 -0
  92. package/skills/deploy-k8s/references/fragile-rollouts.md +303 -0
  93. package/skills/deploy-k8s/references/helm-patterns.md +203 -0
  94. package/skills/deploy-k8s/references/insecure-workload-defaults.md +300 -0
  95. package/skills/deploy-k8s/references/job-patterns.md +120 -0
  96. package/skills/deploy-k8s/references/kustomize-patterns.md +239 -0
  97. package/skills/deploy-k8s/references/multi-tenancy.md +343 -0
  98. package/skills/deploy-k8s/references/network-exposure.md +481 -0
  99. package/skills/deploy-k8s/references/observability.md +302 -0
  100. package/skills/deploy-k8s/references/privilege-sprawl.md +273 -0
  101. package/skills/deploy-k8s/references/resource-starvation.md +374 -0
  102. package/skills/deploy-k8s/references/security-hardening.md +209 -0
  103. package/skills/deploy-k8s/references/stateful-patterns.md +130 -0
  104. package/skills/deploy-k8s/references/storage-and-state.md +330 -0
  105. package/skills/deploy-k8s/references/validation-and-policy.md +242 -0
  106. package/skills/deploy-railway/SKILL.md +235 -0
  107. package/skills/deploy-railway/references/analyze-db-mongo.md +84 -0
  108. package/skills/deploy-railway/references/analyze-db-mysql.md +254 -0
  109. package/skills/deploy-railway/references/analyze-db-postgres.md +479 -0
  110. package/skills/deploy-railway/references/analyze-db-redis.md +208 -0
  111. package/skills/deploy-railway/references/analyze-db.md +344 -0
  112. package/skills/deploy-railway/references/configure.md +309 -0
  113. package/skills/deploy-railway/references/deploy.md +195 -0
  114. package/skills/deploy-railway/references/operate.md +214 -0
  115. package/skills/deploy-railway/references/request.md +248 -0
  116. package/skills/deploy-railway/references/setup.md +312 -0
  117. package/skills/deploy-railway/scripts/analyze-mongo.py +1549 -0
  118. package/skills/deploy-railway/scripts/analyze-mysql.py +1195 -0
  119. package/skills/deploy-railway/scripts/analyze-postgres.py +3058 -0
  120. package/skills/deploy-railway/scripts/analyze-redis.py +1090 -0
  121. package/skills/deploy-railway/scripts/dal.py +671 -0
  122. package/skills/deploy-railway/scripts/enable-pg-stats.py +170 -0
  123. package/skills/deploy-railway/scripts/pg-extensions.py +370 -0
  124. package/skills/deploy-railway/scripts/railway-api.sh +52 -0
  125. package/skills/deploy-ssh/SKILL.md +91 -0
  126. package/skills/deploy-vercel/SKILL.md +304 -0
  127. package/skills/deploy-vercel/resources/deploy-codex.sh +301 -0
  128. package/skills/deploy-vercel/resources/deploy.sh +301 -0
  129. package/skills/docs-runbooks/SKILL.md +399 -0
  130. package/skills/drive-status-renderer/SKILL.md +62 -0
  131. package/skills/iac-scan/SKILL.md +680 -0
  132. package/skills/iac-scan/assets/.gitkeep +9 -0
  133. package/skills/iac-scan/assets/checkov_config.yaml +94 -0
  134. package/skills/iac-scan/assets/github_actions.yml +199 -0
  135. package/skills/iac-scan/assets/gitlab_ci.yml +218 -0
  136. package/skills/iac-scan/assets/pre_commit_config.yaml +92 -0
  137. package/skills/iac-scan/references/EXAMPLE.md +40 -0
  138. package/skills/iac-scan/references/compliance_mapping.md +237 -0
  139. package/skills/iac-scan/references/custom_policies.md +460 -0
  140. package/skills/iac-scan/references/suppression_guide.md +431 -0
  141. package/skills/incident-briefing/SKILL.md +66 -0
  142. package/skills/incident-triage/SKILL.md +481 -0
  143. package/{LICENSE → skills/mcp-builder/LICENSE.txt} +15 -14
  144. package/skills/mcp-builder/SKILL.md +244 -0
  145. package/skills/mcp-builder/reference/evaluation.md +602 -0
  146. package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  147. package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
  148. package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
  149. package/skills/mcp-builder/scripts/connections.py +151 -0
  150. package/skills/mcp-builder/scripts/evaluation.py +373 -0
  151. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  152. package/skills/mcp-builder/scripts/requirements.txt +2 -0
  153. package/skills/mobile-pairing/SKILL.md +52 -0
  154. package/skills/ops-sre/SKILL.md +297 -0
  155. package/skills/playwright-qa/LICENSE.txt +201 -0
  156. package/skills/playwright-qa/NOTICE.txt +14 -0
  157. package/skills/playwright-qa/SKILL.md +156 -0
  158. package/skills/playwright-qa/agents/openai.yaml +6 -0
  159. package/skills/playwright-qa/assets/playwright-small.svg +3 -0
  160. package/skills/playwright-qa/assets/playwright.png +0 -0
  161. package/skills/playwright-qa/references/cli.md +116 -0
  162. package/skills/playwright-qa/references/workflows.md +95 -0
  163. package/skills/playwright-qa/scripts/playwright_cli.sh +25 -0
  164. package/skills/release-publish/SKILL.md +85 -0
  165. package/skills/repo-bootstrap/SKILL.md +92 -0
  166. package/skills/repo-bootstrap/assets/example-workflows/validate-agents.yml +89 -0
  167. package/skills/repo-bootstrap/assets/root-thin.md +141 -0
  168. package/skills/repo-bootstrap/assets/root-verbose.md +149 -0
  169. package/skills/repo-bootstrap/assets/scoped/backend-go.md +107 -0
  170. package/skills/repo-bootstrap/assets/scoped/backend-php.md +94 -0
  171. package/skills/repo-bootstrap/assets/scoped/backend-python.md +84 -0
  172. package/skills/repo-bootstrap/assets/scoped/backend-typescript.md +89 -0
  173. package/skills/repo-bootstrap/assets/scoped/claude-code-skill.md +101 -0
  174. package/skills/repo-bootstrap/assets/scoped/cli.md +83 -0
  175. package/skills/repo-bootstrap/assets/scoped/concourse.md +196 -0
  176. package/skills/repo-bootstrap/assets/scoped/ddev.md +68 -0
  177. package/skills/repo-bootstrap/assets/scoped/docker.md +160 -0
  178. package/skills/repo-bootstrap/assets/scoped/documentation.md +98 -0
  179. package/skills/repo-bootstrap/assets/scoped/examples.md +96 -0
  180. package/skills/repo-bootstrap/assets/scoped/frontend-typescript.md +88 -0
  181. package/skills/repo-bootstrap/assets/scoped/github-actions.md +174 -0
  182. package/skills/repo-bootstrap/assets/scoped/gitlab-ci.md +174 -0
  183. package/skills/repo-bootstrap/assets/scoped/oro-bundle.md +209 -0
  184. package/skills/repo-bootstrap/assets/scoped/oro-project.md +170 -0
  185. package/skills/repo-bootstrap/assets/scoped/python-modern.md +170 -0
  186. package/skills/repo-bootstrap/assets/scoped/resources.md +96 -0
  187. package/skills/repo-bootstrap/assets/scoped/skill-repo.md +139 -0
  188. package/skills/repo-bootstrap/assets/scoped/symfony.md +168 -0
  189. package/skills/repo-bootstrap/assets/scoped/testing.md +87 -0
  190. package/skills/repo-bootstrap/assets/scoped/typo3-docs.md +103 -0
  191. package/skills/repo-bootstrap/assets/scoped/typo3-extension.md +133 -0
  192. package/skills/repo-bootstrap/assets/scoped/typo3-project.md +137 -0
  193. package/skills/repo-bootstrap/assets/scoped/typo3-testing.md +80 -0
  194. package/skills/repo-bootstrap/checkpoints.yaml +279 -0
  195. package/skills/repo-bootstrap/evals/evals.json +385 -0
  196. package/skills/repo-bootstrap/references/ai-contribution-guidelines.md +63 -0
  197. package/skills/repo-bootstrap/references/ai-tool-compatibility.md +223 -0
  198. package/skills/repo-bootstrap/references/directory-coverage.md +82 -0
  199. package/skills/repo-bootstrap/references/examples/coding-agent-cli/AGENTS.md +70 -0
  200. package/skills/repo-bootstrap/references/examples/coding-agent-cli/go.mod +3 -0
  201. package/skills/repo-bootstrap/references/examples/coding-agent-cli/scripts-AGENTS.md +389 -0
  202. package/skills/repo-bootstrap/references/examples/express-api-ts/.env.example +13 -0
  203. package/skills/repo-bootstrap/references/examples/express-api-ts/AGENTS.md +91 -0
  204. package/skills/repo-bootstrap/references/examples/express-api-ts/package.json +33 -0
  205. package/skills/repo-bootstrap/references/examples/express-api-ts/pnpm-lock.yaml +3 -0
  206. package/skills/repo-bootstrap/references/examples/express-api-ts/src/AGENTS.md +91 -0
  207. package/skills/repo-bootstrap/references/examples/express-api-ts/src/config.ts +28 -0
  208. package/skills/repo-bootstrap/references/examples/express-api-ts/src/controllers/userController.ts +74 -0
  209. package/skills/repo-bootstrap/references/examples/express-api-ts/src/index.ts +26 -0
  210. package/skills/repo-bootstrap/references/examples/express-api-ts/src/middleware/errorHandler.ts +45 -0
  211. package/skills/repo-bootstrap/references/examples/express-api-ts/src/middleware/requestLogger.ts +18 -0
  212. package/skills/repo-bootstrap/references/examples/express-api-ts/src/routes/health.ts +18 -0
  213. package/skills/repo-bootstrap/references/examples/express-api-ts/src/routes/users.ts +13 -0
  214. package/skills/repo-bootstrap/references/examples/express-api-ts/src/utils/errors.ts +40 -0
  215. package/skills/repo-bootstrap/references/examples/express-api-ts/src/utils/logger.ts +14 -0
  216. package/skills/repo-bootstrap/references/examples/express-api-ts/tsconfig.json +24 -0
  217. package/skills/repo-bootstrap/references/examples/fastapi-app/.env.example +19 -0
  218. package/skills/repo-bootstrap/references/examples/fastapi-app/AGENTS.md +92 -0
  219. package/skills/repo-bootstrap/references/examples/fastapi-app/pyproject.toml +88 -0
  220. package/skills/repo-bootstrap/references/examples/fastapi-app/src/AGENTS.md +85 -0
  221. package/skills/repo-bootstrap/references/examples/fastapi-app/src/__init__.py +3 -0
  222. package/skills/repo-bootstrap/references/examples/fastapi-app/src/config.py +49 -0
  223. package/skills/repo-bootstrap/references/examples/fastapi-app/src/main.py +66 -0
  224. package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/__init__.py +13 -0
  225. package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/item.py +43 -0
  226. package/skills/repo-bootstrap/references/examples/fastapi-app/src/models/user.py +40 -0
  227. package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/__init__.py +5 -0
  228. package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/health.py +20 -0
  229. package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/items.py +61 -0
  230. package/skills/repo-bootstrap/references/examples/fastapi-app/src/routes/users.py +55 -0
  231. package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/__init__.py +6 -0
  232. package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/item_service.py +77 -0
  233. package/skills/repo-bootstrap/references/examples/fastapi-app/src/services/user_service.py +69 -0
  234. package/skills/repo-bootstrap/references/examples/fastapi-app/uv.lock +4 -0
  235. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/.scopes +3 -0
  236. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/AGENTS.md +86 -0
  237. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/admin/package.json +20 -0
  238. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/admin/src/App.tsx +5 -0
  239. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/cmd/api/main.go +7 -0
  240. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/go.mod +2 -0
  241. package/skills/repo-bootstrap/references/examples/go-api-with-react-admin/main.go +7 -0
  242. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/.scopes +3 -0
  243. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/AGENTS.md +89 -0
  244. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/go.mod +2 -0
  245. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/AGENTS.md +90 -0
  246. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/package.json +17 -0
  247. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/App.tsx +1 -0
  248. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Button.tsx +1 -0
  249. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Footer.tsx +1 -0
  250. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Header.tsx +1 -0
  251. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/internal/web/src/Sidebar.tsx +1 -0
  252. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/main.go +7 -0
  253. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/package-lock.json +0 -0
  254. package/skills/repo-bootstrap/references/examples/go-with-internal-web-tsx/package.json +12 -0
  255. package/skills/repo-bootstrap/references/examples/ldap-selfservice/AGENTS.md +70 -0
  256. package/skills/repo-bootstrap/references/examples/ldap-selfservice/go.mod +3 -0
  257. package/skills/repo-bootstrap/references/examples/ldap-selfservice/internal-AGENTS.md +371 -0
  258. package/skills/repo-bootstrap/references/examples/ldap-selfservice/internal-web-AGENTS.md +448 -0
  259. package/skills/repo-bootstrap/references/examples/php-with-frontend/.scopes +3 -0
  260. package/skills/repo-bootstrap/references/examples/php-with-frontend/AGENTS.md +91 -0
  261. package/skills/repo-bootstrap/references/examples/php-with-frontend/composer.json +8 -0
  262. package/skills/repo-bootstrap/references/examples/php-with-frontend/package.json +15 -0
  263. package/skills/repo-bootstrap/references/examples/php-with-frontend/pnpm-lock.yaml +0 -0
  264. package/skills/repo-bootstrap/references/examples/php-with-frontend/src/Controller.php +3 -0
  265. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/AGENTS.md +92 -0
  266. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/package.json +26 -0
  267. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/App.tsx +3 -0
  268. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Button.tsx +10 -0
  269. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Footer.tsx +9 -0
  270. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/Header.tsx +9 -0
  271. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/src/main.tsx +3 -0
  272. package/skills/repo-bootstrap/references/examples/php-with-frontend/web/tsconfig.json +13 -0
  273. package/skills/repo-bootstrap/references/examples/pnpm-workspace/AGENTS.md +75 -0
  274. package/skills/repo-bootstrap/references/examples/pnpm-workspace/package.json +7 -0
  275. package/skills/repo-bootstrap/references/examples/pnpm-workspace/packages/web/package.json +11 -0
  276. package/skills/repo-bootstrap/references/examples/pnpm-workspace/packages/web/src/index.ts +11 -0
  277. package/skills/repo-bootstrap/references/examples/pnpm-workspace/pnpm-lock.yaml +42 -0
  278. package/skills/repo-bootstrap/references/examples/pnpm-workspace/pnpm-workspace.yaml +2 -0
  279. package/skills/repo-bootstrap/references/examples/simple-ldap-go/AGENTS.md +70 -0
  280. package/skills/repo-bootstrap/references/examples/simple-ldap-go/examples-AGENTS.md +45 -0
  281. package/skills/repo-bootstrap/references/examples/simple-ldap-go/go.mod +3 -0
  282. package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/AGENTS.md +70 -0
  283. package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/Classes-AGENTS.md +392 -0
  284. package/skills/repo-bootstrap/references/examples/t3x-rte-ckeditor-image/composer.json +8 -0
  285. package/skills/repo-bootstrap/references/feedback-memory-schema.md +135 -0
  286. package/skills/repo-bootstrap/references/git-hooks-setup.md +79 -0
  287. package/skills/repo-bootstrap/references/output-structure.md +124 -0
  288. package/skills/repo-bootstrap/references/scripts-guide.md +175 -0
  289. package/skills/repo-bootstrap/references/verification-guide.md +137 -0
  290. package/skills/repo-bootstrap/scripts/analyze-git-history.sh +315 -0
  291. package/skills/repo-bootstrap/scripts/check-freshness.sh +230 -0
  292. package/skills/repo-bootstrap/scripts/detect-golden-samples.sh +161 -0
  293. package/skills/repo-bootstrap/scripts/detect-heuristics.sh +93 -0
  294. package/skills/repo-bootstrap/scripts/detect-project.sh +486 -0
  295. package/skills/repo-bootstrap/scripts/detect-scopes.sh +330 -0
  296. package/skills/repo-bootstrap/scripts/detect-utilities.sh +133 -0
  297. package/skills/repo-bootstrap/scripts/extract-adrs.sh +194 -0
  298. package/skills/repo-bootstrap/scripts/extract-agent-configs.sh +331 -0
  299. package/skills/repo-bootstrap/scripts/extract-architecture-rules.sh +522 -0
  300. package/skills/repo-bootstrap/scripts/extract-ci-commands.sh +385 -0
  301. package/skills/repo-bootstrap/scripts/extract-ci-rules.sh +384 -0
  302. package/skills/repo-bootstrap/scripts/extract-commands.sh +358 -0
  303. package/skills/repo-bootstrap/scripts/extract-documentation.sh +308 -0
  304. package/skills/repo-bootstrap/scripts/extract-github-rulesets.sh +96 -0
  305. package/skills/repo-bootstrap/scripts/extract-github-settings.sh +88 -0
  306. package/skills/repo-bootstrap/scripts/extract-ide-settings.sh +228 -0
  307. package/skills/repo-bootstrap/scripts/extract-platform-files.sh +290 -0
  308. package/skills/repo-bootstrap/scripts/extract-quality-configs.sh +442 -0
  309. package/skills/repo-bootstrap/scripts/generate-agents.sh +2424 -0
  310. package/skills/repo-bootstrap/scripts/generate-file-map.sh +153 -0
  311. package/skills/repo-bootstrap/scripts/lib/config-root.sh +211 -0
  312. package/skills/repo-bootstrap/scripts/lib/summary.sh +244 -0
  313. package/skills/repo-bootstrap/scripts/lib/template.sh +397 -0
  314. package/skills/repo-bootstrap/scripts/validate-structure.sh +324 -0
  315. package/skills/repo-bootstrap/scripts/verify-commands.sh +615 -0
  316. package/skills/repo-bootstrap/scripts/verify-content.sh +302 -0
  317. package/skills/schema-api-contracts/SKILL.md +56 -0
  318. package/skills/secret-hygiene/SKILL.md +511 -0
  319. package/skills/secret-hygiene/assets/.gitkeep +9 -0
  320. package/skills/secret-hygiene/assets/config-balanced.toml +81 -0
  321. package/skills/secret-hygiene/assets/config-custom.toml +178 -0
  322. package/skills/secret-hygiene/assets/config-strict.toml +48 -0
  323. package/skills/secret-hygiene/assets/github-action.yml +181 -0
  324. package/skills/secret-hygiene/assets/gitlab-ci.yml +257 -0
  325. package/skills/secret-hygiene/assets/precommit-config.yaml +70 -0
  326. package/skills/secret-hygiene/references/EXAMPLE.md +40 -0
  327. package/skills/secret-hygiene/references/compliance_mapping.md +538 -0
  328. package/skills/secret-hygiene/references/detection_rules.md +276 -0
  329. package/skills/secret-hygiene/references/false_positives.md +598 -0
  330. package/skills/secret-hygiene/references/remediation_guide.md +530 -0
  331. package/skills/stack-selector/SKILL.md +56 -0
  332. package/skills/telegram-control/SKILL.md +110 -0
  333. package/skills/telegram-control/references/architecture.md +184 -0
  334. package/skills/telegram-control/references/convex.md +173 -0
  335. package/skills/telegram-control/references/error_handling.md +212 -0
  336. package/skills/telegram-control/references/initial_setup.md +165 -0
  337. package/skills/telegram-control/references/telegram_api.md +156 -0
  338. package/skills/telegram-control/scripts/cancel_message.ts +53 -0
  339. package/skills/telegram-control/scripts/list_scheduled.ts +103 -0
  340. package/skills/telegram-control/scripts/logger.ts +121 -0
  341. package/skills/telegram-control/scripts/proxy-util.ts +11 -0
  342. package/skills/telegram-control/scripts/schedule_message.ts +216 -0
  343. package/skills/telegram-control/scripts/send_message.ts +115 -0
  344. package/skills/telegram-control/scripts/setup.ts +185 -0
  345. package/skills/telegram-control/scripts/types.ts +75 -0
  346. package/skills/telegram-control/scripts/view_history.ts +74 -0
  347. package/skills/test-strategy/SKILL.md +352 -0
  348. package/skills/threat-model/SKILL.md +303 -0
  349. package/skills/threat-model/examples/example-output.md +196 -0
  350. package/skills/threat-model/template.md +96 -0
  351. package/skills/ts-lint/SKILL.md +80 -0
  352. package/skills/ui-flow/SKILL.md +668 -0
  353. package/skills/voice-command-router/SKILL.md +51 -0
  354. package/skills/widget-live-activity-sync/SKILL.md +66 -0
@@ -0,0 +1,732 @@
1
+ #!/usr/bin/env python3
2
+ """Analyze any codebase (frontend, backend, or fullstack) and extract routes, APIs, models, and structure.
3
+
4
+ Supports: React, Vue, Angular, Svelte, Next.js, Nuxt, NestJS, Express, Django, FastAPI, Flask.
5
+ Stdlib only — no third-party dependencies. Outputs JSON for downstream PRD generation.
6
+
7
+ Usage:
8
+ python3 codebase_analyzer.py /path/to/project
9
+ python3 codebase_analyzer.py /path/to/project --output prd-analysis.json
10
+ python3 codebase_analyzer.py /path/to/project --format markdown
11
+ """
12
+
13
+ import argparse
14
+ import json
15
+ import os
16
+ import re
17
+ from collections import defaultdict
18
+ from pathlib import Path
19
+ from typing import Any, Dict, List, Optional, Set, Tuple
20
+
21
+ IGNORED_DIRS = {
22
+ ".git", "node_modules", ".next", "dist", "build", "coverage",
23
+ "venv", ".venv", "__pycache__", ".nuxt", ".output", ".cache",
24
+ ".turbo", ".vercel", "out", "storybook-static",
25
+ ".tox", ".mypy_cache", ".pytest_cache", "htmlcov", "staticfiles",
26
+ "media", "migrations", "egg-info",
27
+ }
28
+
29
+ FRAMEWORK_SIGNALS = {
30
+ "react": ["react", "react-dom"],
31
+ "next": ["next"],
32
+ "vue": ["vue"],
33
+ "nuxt": ["nuxt"],
34
+ "angular": ["@angular/core"],
35
+ "svelte": ["svelte"],
36
+ "sveltekit": ["@sveltejs/kit"],
37
+ "solid": ["solid-js"],
38
+ "astro": ["astro"],
39
+ "remix": ["@remix-run/react"],
40
+ "nestjs": ["@nestjs/core"],
41
+ "express": ["express"],
42
+ "fastify": ["fastify"],
43
+ }
44
+
45
+ # Python backend frameworks detected via project files (no package.json)
46
+ PYTHON_FRAMEWORK_FILES = {
47
+ "django": ["manage.py", "settings.py"],
48
+ "fastapi": ["main.py"], # confirmed via imports
49
+ "flask": ["app.py"], # confirmed via imports
50
+ }
51
+
52
+ ROUTE_FILE_PATTERNS = [
53
+ "**/router.{ts,tsx,js,jsx}",
54
+ "**/routes.{ts,tsx,js,jsx}",
55
+ "**/routing.{ts,tsx,js,jsx}",
56
+ "**/app-routing*.{ts,tsx,js,jsx}",
57
+ ]
58
+
59
+ ROUTE_DIR_PATTERNS = [
60
+ "pages", "views", "routes", "app",
61
+ "src/pages", "src/views", "src/routes", "src/app",
62
+ ]
63
+
64
+ API_DIR_PATTERNS = [
65
+ "api", "services", "requests", "endpoints", "client",
66
+ "src/api", "src/services", "src/requests",
67
+ ]
68
+
69
+ STATE_DIR_PATTERNS = [
70
+ "store", "stores", "models", "context", "state",
71
+ "src/store", "src/stores", "src/models", "src/context",
72
+ ]
73
+
74
+ I18N_DIR_PATTERNS = [
75
+ "locales", "i18n", "lang", "translations", "messages",
76
+ "src/locales", "src/i18n", "src/lang",
77
+ ]
78
+
79
+ # Backend-specific directory patterns
80
+ CONTROLLER_DIR_PATTERNS = [
81
+ "controllers", "src/controllers", "src/modules",
82
+ ]
83
+
84
+ MODEL_DIR_PATTERNS = [
85
+ "models", "entities", "src/entities", "src/models",
86
+ ]
87
+
88
+ DTO_DIR_PATTERNS = [
89
+ "dto", "dtos", "src/dto", "serializers",
90
+ ]
91
+
92
+ MOCK_SIGNALS = [
93
+ r"setTimeout\s*\(.*\breturn\b",
94
+ r"Promise\.resolve\s*\(",
95
+ r"\.mock\.",
96
+ r"__mocks__",
97
+ r"mockData",
98
+ r"mock[A-Z]",
99
+ r"faker\.",
100
+ r"fixtures?/",
101
+ ]
102
+
103
+ REAL_API_SIGNALS = [
104
+ r"\baxios\b",
105
+ r"\bfetch\s*\(",
106
+ r"httpGet|httpPost|httpPut|httpDelete|httpPatch",
107
+ r"\.get\s*\(\s*['\"`/]",
108
+ r"\.post\s*\(\s*['\"`/]",
109
+ r"\.put\s*\(\s*['\"`/]",
110
+ r"\.delete\s*\(\s*['\"`/]",
111
+ r"\.patch\s*\(\s*['\"`/]",
112
+ r"useSWR|useQuery|useMutation",
113
+ r"\$http\.",
114
+ r"this\.http\.",
115
+ ]
116
+
117
+ ROUTE_PATTERNS = [
118
+ # React Router
119
+ r'<Route\s+[^>]*path\s*=\s*["\']([^"\']+)["\']',
120
+ r'path\s*:\s*["\']([^"\']+)["\']',
121
+ # Vue Router
122
+ r'path\s*:\s*["\']([^"\']+)["\']',
123
+ # Angular
124
+ r'path\s*:\s*["\']([^"\']+)["\']',
125
+ ]
126
+
127
+ API_PATH_PATTERNS = [
128
+ r'["\'](?:GET|POST|PUT|DELETE|PATCH)["\'].*?["\'](/[a-zA-Z0-9/_\-:{}]+)["\']',
129
+ r'(?:get|post|put|delete|patch)\s*\(\s*["\'](/[a-zA-Z0-9/_\-:{}]+)["\']',
130
+ r'(?:url|path|endpoint|baseURL)\s*[:=]\s*["\'](/[a-zA-Z0-9/_\-:{}]+)["\']',
131
+ r'fetch\s*\(\s*[`"\'](?:https?://[^/]+)?(/[a-zA-Z0-9/_\-:{}]+)',
132
+ ]
133
+
134
+ COMPONENT_EXTENSIONS = {".tsx", ".jsx", ".vue", ".svelte", ".astro"}
135
+ CODE_EXTENSIONS = {".ts", ".tsx", ".js", ".jsx", ".vue", ".svelte", ".astro", ".py"}
136
+
137
+ # NestJS decorator patterns
138
+ NEST_ROUTE_PATTERNS = [
139
+ r"@(?:Get|Post|Put|Delete|Patch|Head|Options|All)\s*\(\s*['\"]([^'\"]*)['\"]",
140
+ r"@Controller\s*\(\s*['\"]([^'\"]*)['\"]",
141
+ ]
142
+
143
+ # Django URL patterns
144
+ DJANGO_ROUTE_PATTERNS = [
145
+ r"path\s*\(\s*['\"]([^'\"]+)['\"]",
146
+ r"url\s*\(\s*r?['\"]([^'\"]+)['\"]",
147
+ r"register\s*\(\s*r?['\"]([^'\"]+)['\"]",
148
+ ]
149
+
150
+ # Django/Python model patterns
151
+ PYTHON_MODEL_PATTERNS = [
152
+ r"class\s+(\w+)\s*\(.*?models\.Model\)",
153
+ r"class\s+(\w+)\s*\(.*?BaseModel\)", # Pydantic
154
+ ]
155
+
156
+ # NestJS entity/DTO patterns
157
+ NEST_MODEL_PATTERNS = [
158
+ r"@Entity\s*\(.*?\)\s*(?:export\s+)?class\s+(\w+)",
159
+ r"class\s+(\w+(?:Dto|DTO|Entity|Schema))\b",
160
+ ]
161
+
162
+
163
+ def detect_framework(project_root: Path) -> Dict[str, Any]:
164
+ """Detect framework from package.json (Node.js) or project files (Python)."""
165
+ detected = []
166
+ all_deps = {}
167
+ pkg_name = ""
168
+ pkg_version = ""
169
+
170
+ # Node.js detection via package.json
171
+ pkg_path = project_root / "package.json"
172
+ if pkg_path.exists():
173
+ try:
174
+ with open(pkg_path) as f:
175
+ pkg = json.load(f)
176
+ pkg_name = pkg.get("name", "")
177
+ pkg_version = pkg.get("version", "")
178
+ for key in ("dependencies", "devDependencies", "peerDependencies"):
179
+ all_deps.update(pkg.get(key, {}))
180
+ for framework, signals in FRAMEWORK_SIGNALS.items():
181
+ if any(s in all_deps for s in signals):
182
+ detected.append(framework)
183
+ except (json.JSONDecodeError, IOError):
184
+ pass
185
+
186
+ # Python backend detection via project files and imports
187
+ if (project_root / "manage.py").exists():
188
+ detected.append("django")
189
+ if (project_root / "requirements.txt").exists() or (project_root / "pyproject.toml").exists():
190
+ for req_file in ["requirements.txt", "pyproject.toml", "setup.py", "Pipfile"]:
191
+ req_path = project_root / req_file
192
+ if req_path.exists():
193
+ try:
194
+ content = req_path.read_text(errors="replace").lower()
195
+ if "django" in content and "django" not in detected:
196
+ detected.append("django")
197
+ if "fastapi" in content:
198
+ detected.append("fastapi")
199
+ if "flask" in content and "flask" not in detected:
200
+ detected.append("flask")
201
+ except IOError:
202
+ pass
203
+
204
+ # Prefer specific over generic
205
+ priority = [
206
+ "sveltekit", "next", "nuxt", "remix", "astro", # fullstack JS
207
+ "nestjs", "express", "fastify", # backend JS
208
+ "django", "fastapi", "flask", # backend Python
209
+ "angular", "svelte", "vue", "react", "solid", # frontend JS
210
+ ]
211
+ framework = "unknown"
212
+ for fw in priority:
213
+ if fw in detected:
214
+ framework = fw
215
+ break
216
+
217
+ return {
218
+ "framework": framework,
219
+ "name": pkg_name or project_root.name,
220
+ "version": pkg_version,
221
+ "detected_frameworks": detected,
222
+ "dependency_count": len(all_deps),
223
+ "key_deps": {k: v for k, v in all_deps.items()
224
+ if any(s in k for s in ["router", "redux", "vuex", "pinia", "zustand",
225
+ "mobx", "recoil", "jotai", "tanstack", "swr",
226
+ "axios", "tailwind", "material", "ant",
227
+ "chakra", "shadcn", "i18n", "intl",
228
+ "typeorm", "prisma", "sequelize", "mongoose",
229
+ "passport", "jwt", "class-validator"])},
230
+ }
231
+
232
+
233
+ def find_dirs(root: Path, patterns: List[str]) -> List[Path]:
234
+ """Find directories matching common patterns."""
235
+ found = []
236
+ for pattern in patterns:
237
+ candidate = root / pattern
238
+ if candidate.is_dir():
239
+ found.append(candidate)
240
+ return found
241
+
242
+
243
+ def walk_files(root: Path, extensions: Set[str] = CODE_EXTENSIONS) -> List[Path]:
244
+ """Walk project tree, skip ignored dirs, return files matching extensions."""
245
+ results = []
246
+ for dirpath, dirnames, filenames in os.walk(root):
247
+ dirnames[:] = [d for d in dirnames if d not in IGNORED_DIRS]
248
+ for fname in filenames:
249
+ if Path(fname).suffix in extensions:
250
+ results.append(Path(dirpath) / fname)
251
+ return results
252
+
253
+
254
+ def extract_routes_from_file(filepath: Path) -> List[Dict[str, str]]:
255
+ """Extract route definitions from a file."""
256
+ routes = []
257
+ try:
258
+ content = filepath.read_text(errors="replace")
259
+ except IOError:
260
+ return routes
261
+
262
+ for pattern in ROUTE_PATTERNS:
263
+ for match in re.finditer(pattern, content):
264
+ path = match.group(1)
265
+ if path and not path.startswith("http") and len(path) < 200:
266
+ routes.append({
267
+ "path": path,
268
+ "source": str(filepath),
269
+ "line": content[:match.start()].count("\n") + 1,
270
+ })
271
+ return routes
272
+
273
+
274
+ def extract_routes_from_filesystem(pages_dir: Path, root: Path) -> List[Dict[str, str]]:
275
+ """Infer routes from file-system routing (Next.js, Nuxt, SvelteKit)."""
276
+ routes = []
277
+ for filepath in sorted(pages_dir.rglob("*")):
278
+ if filepath.is_file() and filepath.suffix in CODE_EXTENSIONS:
279
+ rel = filepath.relative_to(pages_dir)
280
+ route = "/" + str(rel.with_suffix("")).replace("\\", "/")
281
+ # Normalize index routes
282
+ route = re.sub(r"/index$", "", route) or "/"
283
+ # Convert [param] to :param
284
+ route = re.sub(r"\[\.\.\.(\w+)\]", r"*\1", route)
285
+ route = re.sub(r"\[(\w+)\]", r":\1", route)
286
+ routes.append({
287
+ "path": route,
288
+ "source": str(filepath),
289
+ "filesystem": True,
290
+ })
291
+ return routes
292
+
293
+
294
+ def extract_apis_from_file(filepath: Path) -> List[Dict[str, Any]]:
295
+ """Extract API calls from a file."""
296
+ apis = []
297
+ try:
298
+ content = filepath.read_text(errors="replace")
299
+ except IOError:
300
+ return apis
301
+
302
+ is_mock = any(re.search(p, content) for p in MOCK_SIGNALS)
303
+ is_real = any(re.search(p, content) for p in REAL_API_SIGNALS)
304
+
305
+ for pattern in API_PATH_PATTERNS:
306
+ for match in re.finditer(pattern, content):
307
+ path = match.group(1) if match.lastindex else match.group(0)
308
+ if path and len(path) < 200:
309
+ # Try to detect HTTP method
310
+ context = content[max(0, match.start() - 100):match.end()]
311
+ method = "UNKNOWN"
312
+ for m in ["GET", "POST", "PUT", "DELETE", "PATCH"]:
313
+ if m.lower() in context.lower():
314
+ method = m
315
+ break
316
+
317
+ apis.append({
318
+ "path": path,
319
+ "method": method,
320
+ "source": str(filepath),
321
+ "line": content[:match.start()].count("\n") + 1,
322
+ "integrated": is_real and not is_mock,
323
+ "mock_detected": is_mock,
324
+ })
325
+ return apis
326
+
327
+
328
+ def extract_enums(filepath: Path) -> List[Dict[str, Any]]:
329
+ """Extract enum/constant definitions."""
330
+ enums = []
331
+ try:
332
+ content = filepath.read_text(errors="replace")
333
+ except IOError:
334
+ return enums
335
+
336
+ # TypeScript enums
337
+ for match in re.finditer(r"enum\s+(\w+)\s*\{([^}]+)\}", content):
338
+ name = match.group(1)
339
+ body = match.group(2)
340
+ values = re.findall(r"(\w+)\s*=\s*['\"]?([^,'\"\n]+)", body)
341
+ enums.append({
342
+ "name": name,
343
+ "type": "enum",
344
+ "values": {k.strip(): v.strip().rstrip(",") for k, v in values},
345
+ "source": str(filepath),
346
+ })
347
+
348
+ # Object constant maps (const STATUS_MAP = { ... })
349
+ for match in re.finditer(
350
+ r"(?:const|export\s+const)\s+(\w*(?:MAP|STATUS|TYPE|ENUM|OPTION|ROLE|STATE)\w*)\s*[:=]\s*\{([^}]+)\}",
351
+ content, re.IGNORECASE
352
+ ):
353
+ name = match.group(1)
354
+ body = match.group(2)
355
+ values = re.findall(r"['\"]?(\w+)['\"]?\s*:\s*['\"]([^'\"]+)['\"]", body)
356
+ if values:
357
+ enums.append({
358
+ "name": name,
359
+ "type": "constant_map",
360
+ "values": dict(values),
361
+ "source": str(filepath),
362
+ })
363
+
364
+ return enums
365
+
366
+
367
+ def extract_backend_routes(filepath: Path, framework: str) -> List[Dict[str, str]]:
368
+ """Extract route definitions from NestJS controllers or Django url configs."""
369
+ routes = []
370
+ try:
371
+ content = filepath.read_text(errors="replace")
372
+ except IOError:
373
+ return routes
374
+
375
+ patterns = []
376
+ if framework in ("nestjs", "express", "fastify"):
377
+ patterns = NEST_ROUTE_PATTERNS
378
+ elif framework == "django":
379
+ patterns = DJANGO_ROUTE_PATTERNS
380
+
381
+ # For NestJS, also grab the controller prefix
382
+ controller_prefix = ""
383
+ if framework == "nestjs":
384
+ m = re.search(r"@Controller\s*\(\s*['\"]([^'\"]*)['\"]", content)
385
+ if m:
386
+ controller_prefix = "/" + m.group(1).strip("/")
387
+
388
+ for pattern in patterns:
389
+ for match in re.finditer(pattern, content):
390
+ path = match.group(1)
391
+ if not path or path.startswith("http") or len(path) > 200:
392
+ continue
393
+ # For NestJS method decorators, prepend controller prefix
394
+ if framework == "nestjs" and not path.startswith("/"):
395
+ full_path = f"{controller_prefix}/{path}".replace("//", "/")
396
+ else:
397
+ full_path = path if path.startswith("/") else f"/{path}"
398
+
399
+ # Detect HTTP method from decorator name
400
+ method = "UNKNOWN"
401
+ ctx = content[max(0, match.start() - 30):match.start()]
402
+ for m_name in ["Get", "Post", "Put", "Delete", "Patch"]:
403
+ if f"@{m_name}" in ctx or f"@{m_name.lower()}" in ctx:
404
+ method = m_name.upper()
405
+ break
406
+
407
+ routes.append({
408
+ "path": full_path,
409
+ "method": method,
410
+ "source": str(filepath),
411
+ "line": content[:match.start()].count("\n") + 1,
412
+ "type": "backend",
413
+ })
414
+ return routes
415
+
416
+
417
+ def extract_models(filepath: Path, framework: str) -> List[Dict[str, Any]]:
418
+ """Extract model/entity definitions from backend code."""
419
+ models = []
420
+ try:
421
+ content = filepath.read_text(errors="replace")
422
+ except IOError:
423
+ return models
424
+
425
+ patterns = PYTHON_MODEL_PATTERNS if framework in ("django", "fastapi", "flask") else NEST_MODEL_PATTERNS
426
+ for pattern in patterns:
427
+ for match in re.finditer(pattern, content):
428
+ name = match.group(1)
429
+ # Try to extract fields
430
+ fields = []
431
+ # For Django models: field_name = models.FieldType(...)
432
+ if framework == "django":
433
+ block_start = match.end()
434
+ block = content[block_start:block_start + 2000]
435
+ for fm in re.finditer(
436
+ r"(\w+)\s*=\s*models\.(\w+)\s*\(([^)]*)\)", block
437
+ ):
438
+ fields.append({
439
+ "name": fm.group(1),
440
+ "type": fm.group(2),
441
+ "args": fm.group(3).strip()[:100],
442
+ })
443
+ models.append({
444
+ "name": name,
445
+ "source": str(filepath),
446
+ "framework": framework,
447
+ "fields": fields,
448
+ })
449
+ return models
450
+
451
+
452
+ def count_components(files: List[Path]) -> Dict[str, int]:
453
+ """Count components by type."""
454
+ counts: Dict[str, int] = defaultdict(int)
455
+ for f in files:
456
+ if f.suffix in COMPONENT_EXTENSIONS:
457
+ counts["components"] += 1
458
+ elif f.suffix in {".ts", ".js"}:
459
+ counts["modules"] += 1
460
+ return dict(counts)
461
+
462
+
463
+ def analyze_project(project_root: Path) -> Dict[str, Any]:
464
+ """Run full analysis on a frontend project."""
465
+ root = Path(project_root).resolve()
466
+ if not root.is_dir():
467
+ return {"error": f"Not a directory: {root}"}
468
+
469
+ # 1. Framework detection
470
+ framework_info = detect_framework(root)
471
+
472
+ # 2. File inventory
473
+ all_files = walk_files(root)
474
+ component_counts = count_components(all_files)
475
+
476
+ # 3. Directory structure
477
+ route_dirs = find_dirs(root, ROUTE_DIR_PATTERNS)
478
+ api_dirs = find_dirs(root, API_DIR_PATTERNS)
479
+ state_dirs = find_dirs(root, STATE_DIR_PATTERNS)
480
+ i18n_dirs = find_dirs(root, I18N_DIR_PATTERNS)
481
+
482
+ # 4. Routes (frontend + backend)
483
+ routes = []
484
+ fw = framework_info["framework"]
485
+
486
+ # Frontend: config-based routes
487
+ for f in all_files:
488
+ if any(p in f.name.lower() for p in ["router", "routes", "routing"]):
489
+ routes.extend(extract_routes_from_file(f))
490
+
491
+ # Frontend: file-system routes (Next.js, Nuxt, SvelteKit)
492
+ if fw in ("next", "nuxt", "sveltekit", "remix", "astro"):
493
+ for d in route_dirs:
494
+ routes.extend(extract_routes_from_filesystem(d, root))
495
+
496
+ # Backend: NestJS controllers, Django urls
497
+ if fw in ("nestjs", "express", "fastify", "django"):
498
+ for f in all_files:
499
+ if fw == "django" and "urls.py" in f.name:
500
+ routes.extend(extract_backend_routes(f, fw))
501
+ elif fw in ("nestjs", "express", "fastify") and ".controller." in f.name:
502
+ routes.extend(extract_backend_routes(f, fw))
503
+
504
+ # Deduplicate routes by path (+ method for backend)
505
+ seen_paths: Set[str] = set()
506
+ unique_routes = []
507
+ for r in routes:
508
+ key = r["path"] if r.get("type") != "backend" else f"{r.get('method', '')}:{r['path']}"
509
+ if key not in seen_paths:
510
+ seen_paths.add(key)
511
+ unique_routes.append(r)
512
+ routes = sorted(unique_routes, key=lambda r: r["path"])
513
+
514
+ # 5. API calls
515
+ apis = []
516
+ for f in all_files:
517
+ apis.extend(extract_apis_from_file(f))
518
+
519
+ # Deduplicate APIs by path+method
520
+ seen_apis: Set[Tuple[str, str]] = set()
521
+ unique_apis = []
522
+ for a in apis:
523
+ key = (a["path"], a["method"])
524
+ if key not in seen_apis:
525
+ seen_apis.add(key)
526
+ unique_apis.append(a)
527
+ apis = sorted(unique_apis, key=lambda a: a["path"])
528
+
529
+ # 6. Enums
530
+ enums = []
531
+ for f in all_files:
532
+ enums.extend(extract_enums(f))
533
+
534
+ # 7. Models/entities (backend)
535
+ models = []
536
+ if fw in ("django", "fastapi", "flask", "nestjs"):
537
+ for f in all_files:
538
+ if fw == "django" and "models.py" in f.name:
539
+ models.extend(extract_models(f, fw))
540
+ elif fw == "nestjs" and (".entity." in f.name or ".dto." in f.name):
541
+ models.extend(extract_models(f, fw))
542
+
543
+ # Deduplicate models by name
544
+ seen_models: Set[str] = set()
545
+ unique_models = []
546
+ for m in models:
547
+ if m["name"] not in seen_models:
548
+ seen_models.add(m["name"])
549
+ unique_models.append(m)
550
+ models = sorted(unique_models, key=lambda m: m["name"])
551
+
552
+ # Backend-specific directories
553
+ controller_dirs = find_dirs(root, CONTROLLER_DIR_PATTERNS)
554
+ model_dirs = find_dirs(root, MODEL_DIR_PATTERNS)
555
+ dto_dirs = find_dirs(root, DTO_DIR_PATTERNS)
556
+
557
+ # 8. Summary
558
+ mock_count = sum(1 for a in apis if a.get("mock_detected"))
559
+ real_count = sum(1 for a in apis if a.get("integrated"))
560
+ backend_routes = [r for r in routes if r.get("type") == "backend"]
561
+ frontend_routes = [r for r in routes if r.get("type") != "backend"]
562
+
563
+ analysis = {
564
+ "project": {
565
+ "root": str(root),
566
+ "name": framework_info.get("name", root.name),
567
+ "framework": framework_info["framework"],
568
+ "detected_frameworks": framework_info.get("detected_frameworks", []),
569
+ "key_dependencies": framework_info.get("key_deps", {}),
570
+ "stack_type": "backend" if fw in ("django", "fastapi", "flask", "nestjs", "express", "fastify") and not frontend_routes else
571
+ "fullstack" if backend_routes and frontend_routes else "frontend",
572
+ },
573
+ "structure": {
574
+ "total_files": len(all_files),
575
+ "components": component_counts,
576
+ "route_dirs": [str(d) for d in route_dirs],
577
+ "api_dirs": [str(d) for d in api_dirs],
578
+ "state_dirs": [str(d) for d in state_dirs],
579
+ "i18n_dirs": [str(d) for d in i18n_dirs],
580
+ "controller_dirs": [str(d) for d in controller_dirs],
581
+ "model_dirs": [str(d) for d in model_dirs],
582
+ "dto_dirs": [str(d) for d in dto_dirs],
583
+ },
584
+ "routes": {
585
+ "count": len(routes),
586
+ "frontend_pages": frontend_routes,
587
+ "backend_endpoints": backend_routes,
588
+ "pages": routes, # backward compat
589
+ },
590
+ "apis": {
591
+ "total": len(apis),
592
+ "integrated": real_count,
593
+ "mock": mock_count,
594
+ "endpoints": apis,
595
+ },
596
+ "enums": {
597
+ "count": len(enums),
598
+ "definitions": enums,
599
+ },
600
+ "models": {
601
+ "count": len(models),
602
+ "definitions": models,
603
+ },
604
+ "summary": {
605
+ "pages": len(frontend_routes),
606
+ "backend_endpoints": len(backend_routes),
607
+ "api_endpoints": len(apis),
608
+ "api_integrated": real_count,
609
+ "api_mock": mock_count,
610
+ "enums": len(enums),
611
+ "models": len(models),
612
+ "has_i18n": len(i18n_dirs) > 0,
613
+ "has_state_management": len(state_dirs) > 0,
614
+ "stack_type": "backend" if fw in ("django", "fastapi", "flask", "nestjs", "express", "fastify") and not frontend_routes else
615
+ "fullstack" if backend_routes and frontend_routes else "frontend",
616
+ },
617
+ }
618
+
619
+ return analysis
620
+
621
+
622
+ def format_markdown(analysis: Dict[str, Any]) -> str:
623
+ """Format analysis as markdown summary."""
624
+ lines = []
625
+ proj = analysis["project"]
626
+ summary = analysis["summary"]
627
+ stack = summary.get("stack_type", "frontend")
628
+
629
+ lines.append(f"# Codebase Analysis: {proj['name'] or 'Project'}")
630
+ lines.append("")
631
+ lines.append(f"**Framework:** {proj['framework']}")
632
+ lines.append(f"**Stack type:** {stack}")
633
+ lines.append(f"**Total files:** {analysis['structure']['total_files']}")
634
+ if summary.get("pages"):
635
+ lines.append(f"**Frontend pages:** {summary['pages']}")
636
+ if summary.get("backend_endpoints"):
637
+ lines.append(f"**Backend endpoints:** {summary['backend_endpoints']}")
638
+ lines.append(f"**API calls detected:** {summary['api_endpoints']} "
639
+ f"({summary['api_integrated']} integrated, {summary['api_mock']} mock)")
640
+ lines.append(f"**Enums:** {summary['enums']}")
641
+ if summary.get("models"):
642
+ lines.append(f"**Models/entities:** {summary['models']}")
643
+ lines.append(f"**i18n:** {'Yes' if summary['has_i18n'] else 'No'}")
644
+ lines.append(f"**State management:** {'Yes' if summary['has_state_management'] else 'No'}")
645
+ lines.append("")
646
+
647
+ if analysis["routes"]["pages"]:
648
+ lines.append("## Pages / Routes")
649
+ lines.append("")
650
+ lines.append("| # | Route | Source |")
651
+ lines.append("|---|-------|--------|")
652
+ for i, r in enumerate(analysis["routes"]["pages"], 1):
653
+ src = r.get("source", "").split("/")[-1]
654
+ fs = " (fs)" if r.get("filesystem") else ""
655
+ lines.append(f"| {i} | `{r['path']}` | {src}{fs} |")
656
+ lines.append("")
657
+
658
+ if analysis["apis"]["endpoints"]:
659
+ lines.append("## API Endpoints")
660
+ lines.append("")
661
+ lines.append("| Method | Path | Integrated | Source |")
662
+ lines.append("|--------|------|-----------|--------|")
663
+ for a in analysis["apis"]["endpoints"]:
664
+ src = a.get("source", "").split("/")[-1]
665
+ status = "✅" if a.get("integrated") else "⚠️ Mock"
666
+ lines.append(f"| {a['method']} | `{a['path']}` | {status} | {src} |")
667
+ lines.append("")
668
+
669
+ if analysis["enums"]["definitions"]:
670
+ lines.append("## Enums & Constants")
671
+ lines.append("")
672
+ for e in analysis["enums"]["definitions"]:
673
+ lines.append(f"### {e['name']} ({e['type']})")
674
+ if e["values"]:
675
+ lines.append("| Key | Value |")
676
+ lines.append("|-----|-------|")
677
+ for k, v in e["values"].items():
678
+ lines.append(f"| {k} | {v} |")
679
+ lines.append("")
680
+
681
+ if analysis.get("models", {}).get("definitions"):
682
+ lines.append("## Models / Entities")
683
+ lines.append("")
684
+ for m in analysis["models"]["definitions"]:
685
+ lines.append(f"### {m['name']} ({m.get('framework', '')})")
686
+ if m.get("fields"):
687
+ lines.append("| Field | Type | Args |")
688
+ lines.append("|-------|------|------|")
689
+ for fld in m["fields"]:
690
+ lines.append(f"| {fld['name']} | {fld['type']} | {fld.get('args', '')} |")
691
+ lines.append("")
692
+
693
+ if proj.get("key_dependencies"):
694
+ lines.append("## Key Dependencies")
695
+ lines.append("")
696
+ for dep, ver in sorted(proj["key_dependencies"].items()):
697
+ lines.append(f"- `{dep}`: {ver}")
698
+ lines.append("")
699
+
700
+ return "\n".join(lines)
701
+
702
+
703
+ def main():
704
+ parser = argparse.ArgumentParser(
705
+ description="Analyze any codebase (frontend, backend, fullstack) for PRD generation"
706
+ )
707
+ parser.add_argument("project", help="Path to project root")
708
+ parser.add_argument("-o", "--output", help="Output file (default: stdout)")
709
+ parser.add_argument(
710
+ "-f", "--format",
711
+ choices=["json", "markdown"],
712
+ default="json",
713
+ help="Output format (default: json)",
714
+ )
715
+ args = parser.parse_args()
716
+
717
+ analysis = analyze_project(Path(args.project))
718
+
719
+ if args.format == "markdown":
720
+ output = format_markdown(analysis)
721
+ else:
722
+ output = json.dumps(analysis, indent=2, ensure_ascii=False)
723
+
724
+ if args.output:
725
+ Path(args.output).write_text(output)
726
+ print(f"Written to {args.output}")
727
+ else:
728
+ print(output)
729
+
730
+
731
+ if __name__ == "__main__":
732
+ main()