solokit 0.1.1__py3-none-any.whl

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 (323) hide show
  1. solokit/__init__.py +10 -0
  2. solokit/__version__.py +3 -0
  3. solokit/cli.py +374 -0
  4. solokit/core/__init__.py +1 -0
  5. solokit/core/cache.py +102 -0
  6. solokit/core/command_runner.py +278 -0
  7. solokit/core/config.py +453 -0
  8. solokit/core/config_validator.py +204 -0
  9. solokit/core/constants.py +291 -0
  10. solokit/core/error_formatter.py +279 -0
  11. solokit/core/error_handlers.py +346 -0
  12. solokit/core/exceptions.py +1567 -0
  13. solokit/core/file_ops.py +309 -0
  14. solokit/core/logging_config.py +166 -0
  15. solokit/core/output.py +99 -0
  16. solokit/core/performance.py +57 -0
  17. solokit/core/protocols.py +141 -0
  18. solokit/core/types.py +312 -0
  19. solokit/deployment/__init__.py +1 -0
  20. solokit/deployment/executor.py +411 -0
  21. solokit/git/__init__.py +1 -0
  22. solokit/git/integration.py +619 -0
  23. solokit/init/__init__.py +41 -0
  24. solokit/init/claude_commands_installer.py +87 -0
  25. solokit/init/dependency_installer.py +313 -0
  26. solokit/init/docs_structure.py +90 -0
  27. solokit/init/env_generator.py +160 -0
  28. solokit/init/environment_validator.py +334 -0
  29. solokit/init/git_hooks_installer.py +71 -0
  30. solokit/init/git_setup.py +188 -0
  31. solokit/init/gitignore_updater.py +195 -0
  32. solokit/init/initial_commit.py +145 -0
  33. solokit/init/initial_scans.py +109 -0
  34. solokit/init/orchestrator.py +246 -0
  35. solokit/init/readme_generator.py +207 -0
  36. solokit/init/session_structure.py +239 -0
  37. solokit/init/template_installer.py +424 -0
  38. solokit/learning/__init__.py +1 -0
  39. solokit/learning/archiver.py +115 -0
  40. solokit/learning/categorizer.py +126 -0
  41. solokit/learning/curator.py +428 -0
  42. solokit/learning/extractor.py +352 -0
  43. solokit/learning/reporter.py +351 -0
  44. solokit/learning/repository.py +254 -0
  45. solokit/learning/similarity.py +342 -0
  46. solokit/learning/validator.py +144 -0
  47. solokit/project/__init__.py +1 -0
  48. solokit/project/init.py +1162 -0
  49. solokit/project/stack.py +436 -0
  50. solokit/project/sync_plugin.py +438 -0
  51. solokit/project/tree.py +375 -0
  52. solokit/quality/__init__.py +1 -0
  53. solokit/quality/api_validator.py +424 -0
  54. solokit/quality/checkers/__init__.py +25 -0
  55. solokit/quality/checkers/base.py +114 -0
  56. solokit/quality/checkers/context7.py +221 -0
  57. solokit/quality/checkers/custom.py +162 -0
  58. solokit/quality/checkers/deployment.py +323 -0
  59. solokit/quality/checkers/documentation.py +179 -0
  60. solokit/quality/checkers/formatting.py +161 -0
  61. solokit/quality/checkers/integration.py +394 -0
  62. solokit/quality/checkers/linting.py +159 -0
  63. solokit/quality/checkers/security.py +261 -0
  64. solokit/quality/checkers/spec_completeness.py +127 -0
  65. solokit/quality/checkers/tests.py +184 -0
  66. solokit/quality/env_validator.py +306 -0
  67. solokit/quality/gates.py +655 -0
  68. solokit/quality/reporters/__init__.py +10 -0
  69. solokit/quality/reporters/base.py +25 -0
  70. solokit/quality/reporters/console.py +98 -0
  71. solokit/quality/reporters/json_reporter.py +34 -0
  72. solokit/quality/results.py +98 -0
  73. solokit/session/__init__.py +1 -0
  74. solokit/session/briefing/__init__.py +245 -0
  75. solokit/session/briefing/documentation_loader.py +53 -0
  76. solokit/session/briefing/formatter.py +476 -0
  77. solokit/session/briefing/git_context.py +282 -0
  78. solokit/session/briefing/learning_loader.py +212 -0
  79. solokit/session/briefing/milestone_builder.py +78 -0
  80. solokit/session/briefing/orchestrator.py +137 -0
  81. solokit/session/briefing/stack_detector.py +51 -0
  82. solokit/session/briefing/tree_generator.py +52 -0
  83. solokit/session/briefing/work_item_loader.py +209 -0
  84. solokit/session/briefing.py +353 -0
  85. solokit/session/complete.py +1188 -0
  86. solokit/session/status.py +246 -0
  87. solokit/session/validate.py +452 -0
  88. solokit/templates/.claude/commands/end.md +109 -0
  89. solokit/templates/.claude/commands/init.md +159 -0
  90. solokit/templates/.claude/commands/learn-curate.md +88 -0
  91. solokit/templates/.claude/commands/learn-search.md +62 -0
  92. solokit/templates/.claude/commands/learn-show.md +69 -0
  93. solokit/templates/.claude/commands/learn.md +136 -0
  94. solokit/templates/.claude/commands/start.md +114 -0
  95. solokit/templates/.claude/commands/status.md +22 -0
  96. solokit/templates/.claude/commands/validate.md +27 -0
  97. solokit/templates/.claude/commands/work-delete.md +119 -0
  98. solokit/templates/.claude/commands/work-graph.md +139 -0
  99. solokit/templates/.claude/commands/work-list.md +26 -0
  100. solokit/templates/.claude/commands/work-new.md +114 -0
  101. solokit/templates/.claude/commands/work-next.md +25 -0
  102. solokit/templates/.claude/commands/work-show.md +24 -0
  103. solokit/templates/.claude/commands/work-update.md +141 -0
  104. solokit/templates/CHANGELOG.md +17 -0
  105. solokit/templates/WORK_ITEM_TYPES.md +141 -0
  106. solokit/templates/__init__.py +1 -0
  107. solokit/templates/bug_spec.md +217 -0
  108. solokit/templates/config.schema.json +150 -0
  109. solokit/templates/dashboard_refine/base/.gitignore +36 -0
  110. solokit/templates/dashboard_refine/base/app/(dashboard)/layout.tsx +22 -0
  111. solokit/templates/dashboard_refine/base/app/(dashboard)/page.tsx +68 -0
  112. solokit/templates/dashboard_refine/base/app/(dashboard)/users/page.tsx +77 -0
  113. solokit/templates/dashboard_refine/base/app/globals.css +60 -0
  114. solokit/templates/dashboard_refine/base/app/layout.tsx +23 -0
  115. solokit/templates/dashboard_refine/base/app/page.tsx +9 -0
  116. solokit/templates/dashboard_refine/base/components/client-refine-wrapper.tsx +21 -0
  117. solokit/templates/dashboard_refine/base/components/layout/header.tsx +44 -0
  118. solokit/templates/dashboard_refine/base/components/layout/sidebar.tsx +82 -0
  119. solokit/templates/dashboard_refine/base/components/ui/button.tsx +53 -0
  120. solokit/templates/dashboard_refine/base/components/ui/card.tsx +78 -0
  121. solokit/templates/dashboard_refine/base/components/ui/table.tsx +116 -0
  122. solokit/templates/dashboard_refine/base/components.json +16 -0
  123. solokit/templates/dashboard_refine/base/lib/refine.tsx +65 -0
  124. solokit/templates/dashboard_refine/base/lib/utils.ts +13 -0
  125. solokit/templates/dashboard_refine/base/next.config.ts +10 -0
  126. solokit/templates/dashboard_refine/base/package.json.template +40 -0
  127. solokit/templates/dashboard_refine/base/postcss.config.mjs +8 -0
  128. solokit/templates/dashboard_refine/base/providers/refine-provider.tsx +26 -0
  129. solokit/templates/dashboard_refine/base/tailwind.config.ts +57 -0
  130. solokit/templates/dashboard_refine/base/tsconfig.json +27 -0
  131. solokit/templates/dashboard_refine/docker/Dockerfile +57 -0
  132. solokit/templates/dashboard_refine/docker/docker-compose.prod.yml +31 -0
  133. solokit/templates/dashboard_refine/docker/docker-compose.yml +21 -0
  134. solokit/templates/dashboard_refine/tier-1-essential/.eslintrc.json +7 -0
  135. solokit/templates/dashboard_refine/tier-1-essential/jest.config.ts +17 -0
  136. solokit/templates/dashboard_refine/tier-1-essential/jest.setup.ts +1 -0
  137. solokit/templates/dashboard_refine/tier-1-essential/package.json.tier1.template +57 -0
  138. solokit/templates/dashboard_refine/tier-1-essential/tests/setup.ts +26 -0
  139. solokit/templates/dashboard_refine/tier-1-essential/tests/unit/example.test.tsx +73 -0
  140. solokit/templates/dashboard_refine/tier-2-standard/package.json.tier2.template +62 -0
  141. solokit/templates/dashboard_refine/tier-3-comprehensive/eslint.config.mjs +22 -0
  142. solokit/templates/dashboard_refine/tier-3-comprehensive/package.json.tier3.template +79 -0
  143. solokit/templates/dashboard_refine/tier-3-comprehensive/playwright.config.ts +66 -0
  144. solokit/templates/dashboard_refine/tier-3-comprehensive/stryker.conf.json +38 -0
  145. solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/dashboard.spec.ts +88 -0
  146. solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/user-management.spec.ts +102 -0
  147. solokit/templates/dashboard_refine/tier-3-comprehensive/tests/integration/dashboard.test.tsx +90 -0
  148. solokit/templates/dashboard_refine/tier-3-comprehensive/type-coverage.json +16 -0
  149. solokit/templates/dashboard_refine/tier-4-production/instrumentation.ts +9 -0
  150. solokit/templates/dashboard_refine/tier-4-production/k6/dashboard-load-test.js +70 -0
  151. solokit/templates/dashboard_refine/tier-4-production/next.config.ts +46 -0
  152. solokit/templates/dashboard_refine/tier-4-production/package.json.tier4.template +89 -0
  153. solokit/templates/dashboard_refine/tier-4-production/sentry.client.config.ts +26 -0
  154. solokit/templates/dashboard_refine/tier-4-production/sentry.edge.config.ts +11 -0
  155. solokit/templates/dashboard_refine/tier-4-production/sentry.server.config.ts +11 -0
  156. solokit/templates/deployment_spec.md +500 -0
  157. solokit/templates/feature_spec.md +248 -0
  158. solokit/templates/fullstack_nextjs/base/.gitignore +36 -0
  159. solokit/templates/fullstack_nextjs/base/app/api/example/route.ts +65 -0
  160. solokit/templates/fullstack_nextjs/base/app/globals.css +27 -0
  161. solokit/templates/fullstack_nextjs/base/app/layout.tsx +20 -0
  162. solokit/templates/fullstack_nextjs/base/app/page.tsx +32 -0
  163. solokit/templates/fullstack_nextjs/base/components/example-component.tsx +20 -0
  164. solokit/templates/fullstack_nextjs/base/lib/prisma.ts +17 -0
  165. solokit/templates/fullstack_nextjs/base/lib/utils.ts +13 -0
  166. solokit/templates/fullstack_nextjs/base/lib/validations.ts +20 -0
  167. solokit/templates/fullstack_nextjs/base/next.config.ts +7 -0
  168. solokit/templates/fullstack_nextjs/base/package.json.template +32 -0
  169. solokit/templates/fullstack_nextjs/base/postcss.config.mjs +8 -0
  170. solokit/templates/fullstack_nextjs/base/prisma/schema.prisma +21 -0
  171. solokit/templates/fullstack_nextjs/base/tailwind.config.ts +19 -0
  172. solokit/templates/fullstack_nextjs/base/tsconfig.json +27 -0
  173. solokit/templates/fullstack_nextjs/docker/Dockerfile +60 -0
  174. solokit/templates/fullstack_nextjs/docker/docker-compose.prod.yml +57 -0
  175. solokit/templates/fullstack_nextjs/docker/docker-compose.yml +47 -0
  176. solokit/templates/fullstack_nextjs/tier-1-essential/.eslintrc.json +7 -0
  177. solokit/templates/fullstack_nextjs/tier-1-essential/jest.config.ts +17 -0
  178. solokit/templates/fullstack_nextjs/tier-1-essential/jest.setup.ts +1 -0
  179. solokit/templates/fullstack_nextjs/tier-1-essential/package.json.tier1.template +48 -0
  180. solokit/templates/fullstack_nextjs/tier-1-essential/tests/api/example.test.ts +88 -0
  181. solokit/templates/fullstack_nextjs/tier-1-essential/tests/setup.ts +22 -0
  182. solokit/templates/fullstack_nextjs/tier-1-essential/tests/unit/example.test.tsx +22 -0
  183. solokit/templates/fullstack_nextjs/tier-2-standard/package.json.tier2.template +52 -0
  184. solokit/templates/fullstack_nextjs/tier-3-comprehensive/eslint.config.mjs +39 -0
  185. solokit/templates/fullstack_nextjs/tier-3-comprehensive/package.json.tier3.template +68 -0
  186. solokit/templates/fullstack_nextjs/tier-3-comprehensive/playwright.config.ts +66 -0
  187. solokit/templates/fullstack_nextjs/tier-3-comprehensive/stryker.conf.json +33 -0
  188. solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/e2e/flow.spec.ts +59 -0
  189. solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/integration/api.test.ts +165 -0
  190. solokit/templates/fullstack_nextjs/tier-3-comprehensive/type-coverage.json +12 -0
  191. solokit/templates/fullstack_nextjs/tier-4-production/instrumentation.ts +9 -0
  192. solokit/templates/fullstack_nextjs/tier-4-production/k6/load-test.js +45 -0
  193. solokit/templates/fullstack_nextjs/tier-4-production/next.config.ts +46 -0
  194. solokit/templates/fullstack_nextjs/tier-4-production/package.json.tier4.template +77 -0
  195. solokit/templates/fullstack_nextjs/tier-4-production/sentry.client.config.ts +26 -0
  196. solokit/templates/fullstack_nextjs/tier-4-production/sentry.edge.config.ts +11 -0
  197. solokit/templates/fullstack_nextjs/tier-4-production/sentry.server.config.ts +11 -0
  198. solokit/templates/git-hooks/prepare-commit-msg +24 -0
  199. solokit/templates/integration_test_spec.md +363 -0
  200. solokit/templates/learnings.json +15 -0
  201. solokit/templates/ml_ai_fastapi/base/.gitignore +104 -0
  202. solokit/templates/ml_ai_fastapi/base/alembic/env.py +96 -0
  203. solokit/templates/ml_ai_fastapi/base/alembic.ini +114 -0
  204. solokit/templates/ml_ai_fastapi/base/pyproject.toml.template +91 -0
  205. solokit/templates/ml_ai_fastapi/base/requirements.txt.template +28 -0
  206. solokit/templates/ml_ai_fastapi/base/src/__init__.py +5 -0
  207. solokit/templates/ml_ai_fastapi/base/src/api/__init__.py +3 -0
  208. solokit/templates/ml_ai_fastapi/base/src/api/dependencies.py +20 -0
  209. solokit/templates/ml_ai_fastapi/base/src/api/routes/__init__.py +3 -0
  210. solokit/templates/ml_ai_fastapi/base/src/api/routes/example.py +134 -0
  211. solokit/templates/ml_ai_fastapi/base/src/api/routes/health.py +66 -0
  212. solokit/templates/ml_ai_fastapi/base/src/core/__init__.py +3 -0
  213. solokit/templates/ml_ai_fastapi/base/src/core/config.py +64 -0
  214. solokit/templates/ml_ai_fastapi/base/src/core/database.py +50 -0
  215. solokit/templates/ml_ai_fastapi/base/src/main.py +64 -0
  216. solokit/templates/ml_ai_fastapi/base/src/models/__init__.py +7 -0
  217. solokit/templates/ml_ai_fastapi/base/src/models/example.py +61 -0
  218. solokit/templates/ml_ai_fastapi/base/src/services/__init__.py +3 -0
  219. solokit/templates/ml_ai_fastapi/base/src/services/example.py +115 -0
  220. solokit/templates/ml_ai_fastapi/docker/Dockerfile +59 -0
  221. solokit/templates/ml_ai_fastapi/docker/docker-compose.prod.yml +112 -0
  222. solokit/templates/ml_ai_fastapi/docker/docker-compose.yml +77 -0
  223. solokit/templates/ml_ai_fastapi/tier-1-essential/pyproject.toml.tier1.template +112 -0
  224. solokit/templates/ml_ai_fastapi/tier-1-essential/pyrightconfig.json +41 -0
  225. solokit/templates/ml_ai_fastapi/tier-1-essential/pytest.ini +69 -0
  226. solokit/templates/ml_ai_fastapi/tier-1-essential/requirements-dev.txt +17 -0
  227. solokit/templates/ml_ai_fastapi/tier-1-essential/ruff.toml +81 -0
  228. solokit/templates/ml_ai_fastapi/tier-1-essential/tests/__init__.py +3 -0
  229. solokit/templates/ml_ai_fastapi/tier-1-essential/tests/conftest.py +72 -0
  230. solokit/templates/ml_ai_fastapi/tier-1-essential/tests/test_main.py +49 -0
  231. solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/__init__.py +3 -0
  232. solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/test_example.py +113 -0
  233. solokit/templates/ml_ai_fastapi/tier-2-standard/pyproject.toml.tier2.template +130 -0
  234. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/locustfile.py +99 -0
  235. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/mutmut_config.py +53 -0
  236. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/pyproject.toml.tier3.template +150 -0
  237. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/__init__.py +3 -0
  238. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/conftest.py +74 -0
  239. solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/test_api.py +131 -0
  240. solokit/templates/ml_ai_fastapi/tier-4-production/pyproject.toml.tier4.template +162 -0
  241. solokit/templates/ml_ai_fastapi/tier-4-production/requirements-prod.txt +25 -0
  242. solokit/templates/ml_ai_fastapi/tier-4-production/src/api/routes/metrics.py +19 -0
  243. solokit/templates/ml_ai_fastapi/tier-4-production/src/core/logging.py +74 -0
  244. solokit/templates/ml_ai_fastapi/tier-4-production/src/core/monitoring.py +68 -0
  245. solokit/templates/ml_ai_fastapi/tier-4-production/src/core/sentry.py +66 -0
  246. solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/__init__.py +3 -0
  247. solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/logging.py +79 -0
  248. solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/tracing.py +60 -0
  249. solokit/templates/refactor_spec.md +287 -0
  250. solokit/templates/saas_t3/base/.gitignore +36 -0
  251. solokit/templates/saas_t3/base/app/api/trpc/[trpc]/route.ts +33 -0
  252. solokit/templates/saas_t3/base/app/globals.css +27 -0
  253. solokit/templates/saas_t3/base/app/layout.tsx +23 -0
  254. solokit/templates/saas_t3/base/app/page.tsx +31 -0
  255. solokit/templates/saas_t3/base/lib/api.tsx +77 -0
  256. solokit/templates/saas_t3/base/lib/utils.ts +13 -0
  257. solokit/templates/saas_t3/base/next.config.ts +7 -0
  258. solokit/templates/saas_t3/base/package.json.template +38 -0
  259. solokit/templates/saas_t3/base/postcss.config.mjs +8 -0
  260. solokit/templates/saas_t3/base/prisma/schema.prisma +20 -0
  261. solokit/templates/saas_t3/base/server/api/root.ts +19 -0
  262. solokit/templates/saas_t3/base/server/api/routers/example.ts +28 -0
  263. solokit/templates/saas_t3/base/server/api/trpc.ts +52 -0
  264. solokit/templates/saas_t3/base/server/db.ts +17 -0
  265. solokit/templates/saas_t3/base/tailwind.config.ts +19 -0
  266. solokit/templates/saas_t3/base/tsconfig.json +27 -0
  267. solokit/templates/saas_t3/docker/Dockerfile +60 -0
  268. solokit/templates/saas_t3/docker/docker-compose.prod.yml +59 -0
  269. solokit/templates/saas_t3/docker/docker-compose.yml +49 -0
  270. solokit/templates/saas_t3/tier-1-essential/.eslintrc.json +7 -0
  271. solokit/templates/saas_t3/tier-1-essential/jest.config.ts +17 -0
  272. solokit/templates/saas_t3/tier-1-essential/jest.setup.ts +1 -0
  273. solokit/templates/saas_t3/tier-1-essential/package.json.tier1.template +54 -0
  274. solokit/templates/saas_t3/tier-1-essential/tests/setup.ts +22 -0
  275. solokit/templates/saas_t3/tier-1-essential/tests/unit/example.test.tsx +24 -0
  276. solokit/templates/saas_t3/tier-2-standard/package.json.tier2.template +58 -0
  277. solokit/templates/saas_t3/tier-3-comprehensive/eslint.config.mjs +39 -0
  278. solokit/templates/saas_t3/tier-3-comprehensive/package.json.tier3.template +74 -0
  279. solokit/templates/saas_t3/tier-3-comprehensive/playwright.config.ts +66 -0
  280. solokit/templates/saas_t3/tier-3-comprehensive/stryker.conf.json +34 -0
  281. solokit/templates/saas_t3/tier-3-comprehensive/tests/e2e/home.spec.ts +41 -0
  282. solokit/templates/saas_t3/tier-3-comprehensive/tests/integration/api.test.ts +44 -0
  283. solokit/templates/saas_t3/tier-3-comprehensive/type-coverage.json +12 -0
  284. solokit/templates/saas_t3/tier-4-production/instrumentation.ts +9 -0
  285. solokit/templates/saas_t3/tier-4-production/k6/load-test.js +51 -0
  286. solokit/templates/saas_t3/tier-4-production/next.config.ts +46 -0
  287. solokit/templates/saas_t3/tier-4-production/package.json.tier4.template +83 -0
  288. solokit/templates/saas_t3/tier-4-production/sentry.client.config.ts +26 -0
  289. solokit/templates/saas_t3/tier-4-production/sentry.edge.config.ts +11 -0
  290. solokit/templates/saas_t3/tier-4-production/sentry.server.config.ts +11 -0
  291. solokit/templates/saas_t3/tier-4-production/vercel.json +37 -0
  292. solokit/templates/security_spec.md +287 -0
  293. solokit/templates/stack-versions.yaml +617 -0
  294. solokit/templates/status_update.json +6 -0
  295. solokit/templates/template-registry.json +257 -0
  296. solokit/templates/work_items.json +11 -0
  297. solokit/testing/__init__.py +1 -0
  298. solokit/testing/integration_runner.py +550 -0
  299. solokit/testing/performance.py +637 -0
  300. solokit/visualization/__init__.py +1 -0
  301. solokit/visualization/dependency_graph.py +788 -0
  302. solokit/work_items/__init__.py +1 -0
  303. solokit/work_items/creator.py +217 -0
  304. solokit/work_items/delete.py +264 -0
  305. solokit/work_items/get_dependencies.py +185 -0
  306. solokit/work_items/get_dependents.py +113 -0
  307. solokit/work_items/get_metadata.py +121 -0
  308. solokit/work_items/get_next_recommendations.py +133 -0
  309. solokit/work_items/manager.py +235 -0
  310. solokit/work_items/milestones.py +137 -0
  311. solokit/work_items/query.py +376 -0
  312. solokit/work_items/repository.py +267 -0
  313. solokit/work_items/scheduler.py +184 -0
  314. solokit/work_items/spec_parser.py +838 -0
  315. solokit/work_items/spec_validator.py +493 -0
  316. solokit/work_items/updater.py +157 -0
  317. solokit/work_items/validator.py +205 -0
  318. solokit-0.1.1.dist-info/METADATA +640 -0
  319. solokit-0.1.1.dist-info/RECORD +323 -0
  320. solokit-0.1.1.dist-info/WHEEL +5 -0
  321. solokit-0.1.1.dist-info/entry_points.txt +2 -0
  322. solokit-0.1.1.dist-info/licenses/LICENSE +21 -0
  323. solokit-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,411 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deployment execution framework.
4
+
5
+ Provides automated deployment execution with:
6
+ - Pre-deployment validation
7
+ - Deployment execution with comprehensive logging
8
+ - Smoke test execution
9
+ - Rollback automation on failure
10
+ - Deployment state tracking
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ from datetime import datetime
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ from solokit.core.error_handlers import convert_file_errors, log_errors
21
+ from solokit.core.exceptions import (
22
+ DeploymentStepError,
23
+ ErrorCode,
24
+ FileOperationError,
25
+ PreDeploymentCheckError,
26
+ RollbackError,
27
+ SmokeTestError,
28
+ )
29
+ from solokit.core.output import get_output
30
+
31
+ output = get_output()
32
+
33
+
34
+ class DeploymentExecutor:
35
+ """Deployment execution and validation."""
36
+
37
+ def __init__(self, work_item: dict[str, Any], config_path: Path | None = None) -> None:
38
+ """Initialize deployment executor."""
39
+ if config_path is None:
40
+ config_path = Path(".session/config.json")
41
+ self.work_item = work_item
42
+ self.config = self._load_config(config_path)
43
+ self.deployment_log: list[dict[str, Any]] = []
44
+
45
+ @convert_file_errors
46
+ def _load_config(self, config_path: Path) -> dict[str, Any]:
47
+ """
48
+ Load deployment configuration.
49
+
50
+ Args:
51
+ config_path: Path to configuration file
52
+
53
+ Returns:
54
+ dict: Deployment configuration
55
+
56
+ Raises:
57
+ FileOperationError: If config file cannot be read or parsed
58
+ """
59
+ if not config_path.exists():
60
+ return self._default_config()
61
+
62
+ try:
63
+ with open(config_path) as f:
64
+ config = json.load(f)
65
+ except json.JSONDecodeError as e:
66
+ raise FileOperationError(
67
+ operation="parse", file_path=str(config_path), details=f"Invalid JSON: {e}", cause=e
68
+ ) from e
69
+
70
+ deployment_config = config.get("deployment", self._default_config())
71
+ return deployment_config # type: ignore[no-any-return]
72
+
73
+ def _default_config(self) -> dict[str, Any]:
74
+ """Default deployment configuration."""
75
+ return {
76
+ "pre_deployment_checks": {
77
+ "integration_tests": True,
78
+ "security_scans": True,
79
+ "environment_validation": True,
80
+ },
81
+ "smoke_tests": {"enabled": True, "timeout": 300, "retry_count": 3},
82
+ "rollback": {
83
+ "automatic": True,
84
+ "on_smoke_test_failure": True,
85
+ "on_error_threshold": True,
86
+ "error_threshold_percent": 5,
87
+ },
88
+ "environments": {
89
+ "staging": {"auto_deploy": True, "require_approval": False},
90
+ "production": {"auto_deploy": False, "require_approval": True},
91
+ },
92
+ }
93
+
94
+ @log_errors()
95
+ def pre_deployment_validation(self) -> dict[str, Any]:
96
+ """
97
+ Run pre-deployment validation checks.
98
+
99
+ Returns:
100
+ dict: Validation results with checks and status
101
+
102
+ Raises:
103
+ PreDeploymentCheckError: If any validation check fails
104
+ """
105
+ results: dict[str, Any] = {"checks": [], "passed": True}
106
+ failed_checks: list[str] = []
107
+
108
+ # Check integration tests
109
+ if self.config["pre_deployment_checks"].get("integration_tests"):
110
+ tests_passed = self._check_integration_tests()
111
+ results["checks"].append({"name": "Integration Tests", "passed": tests_passed})
112
+ if not tests_passed:
113
+ results["passed"] = False
114
+ failed_checks.append("Integration Tests")
115
+
116
+ # Check security scans
117
+ if self.config["pre_deployment_checks"].get("security_scans"):
118
+ scans_passed = self._check_security_scans()
119
+ results["checks"].append({"name": "Security Scans", "passed": scans_passed})
120
+ if not scans_passed:
121
+ results["passed"] = False
122
+ failed_checks.append("Security Scans")
123
+
124
+ # Check environment readiness
125
+ if self.config["pre_deployment_checks"].get("environment_validation"):
126
+ env_ready = self._check_environment_readiness()
127
+ results["checks"].append({"name": "Environment Readiness", "passed": env_ready})
128
+ if not env_ready:
129
+ results["passed"] = False
130
+ failed_checks.append("Environment Readiness")
131
+
132
+ self._log("Pre-deployment validation", results)
133
+
134
+ # Raise exception if any checks failed
135
+ if not results["passed"]:
136
+ raise PreDeploymentCheckError(
137
+ check_name=", ".join(failed_checks),
138
+ details=f"{len(failed_checks)} check(s) failed",
139
+ context={"results": results, "failed_checks": failed_checks},
140
+ )
141
+
142
+ return results
143
+
144
+ @log_errors()
145
+ def execute_deployment(self, dry_run: bool = False) -> dict[str, Any]:
146
+ """
147
+ Execute deployment procedure.
148
+
149
+ Args:
150
+ dry_run: If True, simulate deployment without actual execution
151
+
152
+ Returns:
153
+ dict: Deployment results with steps and timestamps
154
+
155
+ Raises:
156
+ DeploymentStepError: If any deployment step fails
157
+ """
158
+ results: dict[str, Any] = {
159
+ "started_at": datetime.now().isoformat(),
160
+ "steps": [],
161
+ "success": True,
162
+ }
163
+
164
+ self._log("Deployment started", {"dry_run": dry_run})
165
+
166
+ # Parse deployment steps from work item
167
+ deployment_steps = self._parse_deployment_steps()
168
+
169
+ for i, step in enumerate(deployment_steps, 1):
170
+ self._log(f"Executing step {i}", {"step": step})
171
+
172
+ if not dry_run:
173
+ step_success = self._execute_deployment_step(step)
174
+ else:
175
+ step_success = True # Simulate success in dry run
176
+
177
+ results["steps"].append({"number": i, "description": step, "success": step_success})
178
+
179
+ if not step_success:
180
+ results["success"] = False
181
+ results["failed_at_step"] = i
182
+ self._log("Deployment failed", {"step": i, "description": step})
183
+ raise DeploymentStepError(
184
+ step_number=i, step_description=step, context={"results": results}
185
+ )
186
+
187
+ results["completed_at"] = datetime.now().isoformat()
188
+ return results
189
+
190
+ @log_errors()
191
+ def run_smoke_tests(self) -> dict[str, Any]:
192
+ """
193
+ Run smoke tests to verify deployment.
194
+
195
+ Returns:
196
+ dict: Test results with status
197
+
198
+ Raises:
199
+ SmokeTestError: If any smoke test fails
200
+ """
201
+ config = self.config["smoke_tests"]
202
+ results: dict[str, Any] = {"tests": [], "passed": True}
203
+
204
+ if not config.get("enabled"):
205
+ return {"status": "skipped"}
206
+
207
+ self._log("Running smoke tests", config)
208
+
209
+ # Parse smoke tests from work item
210
+ smoke_tests = self._parse_smoke_tests()
211
+ failed_tests = []
212
+
213
+ for test in smoke_tests:
214
+ test_passed = self._execute_smoke_test(
215
+ test,
216
+ timeout=config.get("timeout", 300),
217
+ retry_count=config.get("retry_count", 3),
218
+ )
219
+
220
+ test_name = test.get("name", "unknown")
221
+ results["tests"].append({"name": test_name, "passed": test_passed})
222
+
223
+ if not test_passed:
224
+ results["passed"] = False
225
+ failed_tests.append(test_name)
226
+
227
+ self._log("Smoke tests completed", results)
228
+
229
+ # Raise exception if any tests failed
230
+ if not results["passed"]:
231
+ raise SmokeTestError(
232
+ test_name=", ".join(failed_tests),
233
+ details=f"{len(failed_tests)} test(s) failed",
234
+ context={"results": results, "failed_tests": failed_tests},
235
+ )
236
+
237
+ return results
238
+
239
+ @log_errors()
240
+ def rollback(self) -> dict[str, Any]:
241
+ """
242
+ Execute rollback procedure.
243
+
244
+ Returns:
245
+ dict: Rollback results with steps and timestamps
246
+
247
+ Raises:
248
+ RollbackError: If any rollback step fails
249
+ """
250
+ results: dict[str, Any] = {
251
+ "started_at": datetime.now().isoformat(),
252
+ "steps": [],
253
+ "success": True,
254
+ }
255
+
256
+ self._log("Rollback started", {})
257
+
258
+ # Parse rollback steps from work item
259
+ rollback_steps = self._parse_rollback_steps()
260
+
261
+ for i, step in enumerate(rollback_steps, 1):
262
+ self._log(f"Executing rollback step {i}", {"step": step})
263
+
264
+ step_success = self._execute_rollback_step(step)
265
+
266
+ results["steps"].append({"number": i, "description": step, "success": step_success})
267
+
268
+ if not step_success:
269
+ results["success"] = False
270
+ results["failed_at_step"] = i
271
+ raise RollbackError(
272
+ step=step,
273
+ details=f"Rollback failed at step {i}",
274
+ context={"results": results, "step_number": i},
275
+ )
276
+
277
+ results["completed_at"] = datetime.now().isoformat()
278
+ self._log("Rollback completed", results)
279
+
280
+ return results
281
+
282
+ def _check_integration_tests(self) -> bool:
283
+ """Check if integration tests passed."""
284
+ # NOTE: Framework stub - Integrate with quality_gates.py for actual test execution
285
+ # In production, this should call QualityGates.run_tests() and check results
286
+ return True
287
+
288
+ def _check_security_scans(self) -> bool:
289
+ """Check if security scans passed."""
290
+ # NOTE: Framework stub - Integrate with quality_gates.py for actual security scanning
291
+ # In production, this should call QualityGates.run_security_gate() and check results
292
+ return True
293
+
294
+ def _check_environment_readiness(self) -> bool:
295
+ """Check if environment is ready."""
296
+ # NOTE: Framework stub - Integrate with environment_validator.py for actual validation
297
+ # In production, this should instantiate EnvironmentValidator and call validate_all()
298
+ return True
299
+
300
+ def _parse_deployment_steps(self) -> list[str]:
301
+ """Parse deployment steps from work item specification."""
302
+ # NOTE: Framework stub - Parse deployment steps from spec file
303
+ # Use spec_parser.py to extract "## Deployment Steps" section
304
+ # and convert to structured list of commands/actions
305
+ return []
306
+
307
+ def _execute_deployment_step(self, step: str) -> bool:
308
+ """Execute a single deployment step."""
309
+ # NOTE: Framework stub - Implement project-specific deployment step execution
310
+ # Step types might include: shell commands, API calls, file operations, etc.
311
+ # Should handle errors, logging, and timeouts appropriately
312
+ return True
313
+
314
+ def _parse_smoke_tests(self) -> list[dict]:
315
+ """Parse smoke tests from work item specification."""
316
+ # NOTE: Framework stub - Parse smoke test definitions from spec file
317
+ # Use spec_parser.py to extract "## Smoke Tests" section
318
+ # and convert to list of {name, command, expected_result} dicts
319
+ return []
320
+
321
+ def _execute_smoke_test(self, test: dict, timeout: int, retry_count: int) -> bool:
322
+ """Execute a single smoke test with retries."""
323
+ # NOTE: Framework stub - Implement project-specific smoke test execution
324
+ # Should execute test command, check result, handle retries and timeouts
325
+ # Common tests: HTTP endpoint checks, database queries, cache reads
326
+ return True
327
+
328
+ def _parse_rollback_steps(self) -> list[str]:
329
+ """Parse rollback steps from work item specification."""
330
+ # NOTE: Framework stub - Parse rollback procedure from spec file
331
+ # Use spec_parser.py to extract "## Rollback Procedure" section
332
+ # and convert to ordered list of rollback commands/actions
333
+ return []
334
+
335
+ def _execute_rollback_step(self, step: str) -> bool:
336
+ """Execute a single rollback step."""
337
+ # NOTE: Framework stub - Implement project-specific rollback step execution
338
+ # Must be highly reliable since this runs during failure scenarios
339
+ # Should handle partial rollbacks and verification of rollback success
340
+ return True
341
+
342
+ def _log(self, event: str, data: dict[str, Any]) -> None:
343
+ """Log deployment event."""
344
+ log_entry = {
345
+ "timestamp": datetime.now().isoformat(),
346
+ "event": event,
347
+ "data": data,
348
+ }
349
+ self.deployment_log.append(log_entry)
350
+
351
+ def get_deployment_log(self) -> list[dict[str, Any]]:
352
+ """Get deployment log."""
353
+ return self.deployment_log
354
+
355
+
356
+ def main() -> None:
357
+ """
358
+ CLI entry point.
359
+
360
+ Raises:
361
+ ValidationError: If no work item ID provided
362
+ PreDeploymentCheckError: If pre-deployment checks fail
363
+ DeploymentStepError: If deployment fails
364
+ SmokeTestError: If smoke tests fail
365
+ RollbackError: If rollback fails
366
+ """
367
+ import sys
368
+
369
+ from solokit.core.exceptions import ValidationError
370
+
371
+ if len(sys.argv) < 2:
372
+ raise ValidationError(
373
+ message="Missing required argument: work_item_id",
374
+ code=ErrorCode.INVALID_COMMAND,
375
+ remediation="Usage: deployment_executor.py <work_item_id>",
376
+ )
377
+
378
+ # Load work item
379
+ # NOTE: Framework stub - Should load work item by ID from work_items.json
380
+ # Use work_item_manager.WorkItemManager to load actual work item data
381
+
382
+ executor = DeploymentExecutor(work_item={})
383
+
384
+ try:
385
+ # Pre-deployment validation
386
+ executor.pre_deployment_validation()
387
+
388
+ # Execute deployment
389
+ executor.execute_deployment()
390
+
391
+ # Run smoke tests
392
+ executor.run_smoke_tests()
393
+
394
+ output.info("Deployment successful!")
395
+
396
+ except (DeploymentStepError, SmokeTestError) as e:
397
+ # Attempt rollback on deployment or smoke test failure
398
+ output.info(f"Error: {e.message}")
399
+ output.info("Initiating rollback...")
400
+ try:
401
+ executor.rollback()
402
+ output.info("Rollback completed successfully")
403
+ except RollbackError as rollback_err:
404
+ output.info(f"Rollback failed: {rollback_err.message}")
405
+ raise
406
+ # Re-raise original error after successful rollback
407
+ raise
408
+
409
+
410
+ if __name__ == "__main__":
411
+ main()
@@ -0,0 +1 @@
1
+ """Git integration for branch management and status tracking."""