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,619 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Git workflow integration for Session-Driven Development.
4
+
5
+ Handles:
6
+ - Branch creation for work items
7
+ - Branch continuation for multi-session work
8
+ - Commit generation
9
+ - Push to remote
10
+ - Branch merging (local or PR-based)
11
+ - PR creation and management
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import logging
18
+ from datetime import datetime
19
+ from pathlib import Path
20
+
21
+ from solokit.core.command_runner import CommandRunner
22
+ from solokit.core.config import get_config_manager
23
+ from solokit.core.constants import (
24
+ GIT_LONG_TIMEOUT,
25
+ GIT_QUICK_TIMEOUT,
26
+ GIT_STANDARD_TIMEOUT,
27
+ get_config_file,
28
+ get_work_items_file,
29
+ )
30
+ from solokit.core.error_handlers import convert_subprocess_errors
31
+ from solokit.core.exceptions import (
32
+ CommandExecutionError,
33
+ ErrorCode,
34
+ FileOperationError,
35
+ GitError,
36
+ NotAGitRepoError,
37
+ WorkingDirNotCleanError,
38
+ )
39
+ from solokit.core.types import GitStatus, WorkItemStatus, WorkItemType
40
+
41
+ logger = logging.getLogger(__name__)
42
+
43
+
44
+ class GitWorkflow:
45
+ """Manage git workflow for sessions."""
46
+
47
+ def __init__(self, project_root: Path | None = None) -> None:
48
+ """Initialize GitWorkflow with project root path."""
49
+ self.project_root = project_root or Path.cwd()
50
+ self.work_items_file = get_work_items_file(self.project_root)
51
+ self.config_file = get_config_file(self.project_root)
52
+
53
+ # Use ConfigManager for centralized config management
54
+ config_manager = get_config_manager()
55
+ config_manager.load_config(self.config_file)
56
+ self.config = config_manager.git_workflow
57
+
58
+ # Initialize command runner
59
+ self.runner = CommandRunner(default_timeout=GIT_LONG_TIMEOUT, working_dir=self.project_root)
60
+
61
+ @convert_subprocess_errors
62
+ def check_git_status(self) -> None:
63
+ """Check if working directory is clean.
64
+
65
+ Raises:
66
+ NotAGitRepoError: If not in a git repository
67
+ WorkingDirNotCleanError: If working directory has uncommitted changes
68
+ CommandExecutionError: If git command times out or fails
69
+ """
70
+ result = self.runner.run(["git", "status", "--porcelain"], timeout=GIT_QUICK_TIMEOUT)
71
+
72
+ if not result.success:
73
+ if result.timed_out:
74
+ raise CommandExecutionError("git status", -1, "Command timed out")
75
+ raise NotAGitRepoError("Not a git repository")
76
+
77
+ if result.stdout.strip():
78
+ changes = result.stdout.strip().split("\n")
79
+ raise WorkingDirNotCleanError(changes=changes)
80
+
81
+ def get_current_branch(self) -> str | None:
82
+ """Get current git branch name."""
83
+ result = self.runner.run(["git", "branch", "--show-current"], timeout=GIT_QUICK_TIMEOUT)
84
+ return result.stdout.strip() if result.success else None
85
+
86
+ @convert_subprocess_errors
87
+ def create_branch(self, work_item_id: str, session_num: int) -> tuple[str, str | None]:
88
+ """Create a new branch for work item.
89
+
90
+ Args:
91
+ work_item_id: ID of the work item
92
+ session_num: Session number
93
+
94
+ Returns:
95
+ Tuple of (branch_name, parent_branch)
96
+
97
+ Raises:
98
+ GitError: If branch creation fails
99
+ CommandExecutionError: If git command fails
100
+ """
101
+ # Capture parent branch BEFORE creating new branch
102
+ parent_branch = self.get_current_branch()
103
+ branch_name = work_item_id
104
+
105
+ # Create and checkout branch
106
+ result = self.runner.run(["git", "checkout", "-b", branch_name], timeout=GIT_QUICK_TIMEOUT)
107
+
108
+ if not result.success:
109
+ raise GitError(
110
+ f"Failed to create branch: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED
111
+ )
112
+
113
+ return branch_name, parent_branch
114
+
115
+ @convert_subprocess_errors
116
+ def checkout_branch(self, branch_name: str) -> None:
117
+ """Checkout existing branch.
118
+
119
+ Args:
120
+ branch_name: Name of the branch to checkout
121
+
122
+ Raises:
123
+ GitError: If checkout fails
124
+ CommandExecutionError: If git command fails
125
+ """
126
+ result = self.runner.run(["git", "checkout", branch_name], timeout=GIT_QUICK_TIMEOUT)
127
+
128
+ if not result.success:
129
+ raise GitError(
130
+ f"Failed to checkout branch: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED
131
+ )
132
+
133
+ @convert_subprocess_errors
134
+ def commit_changes(self, message: str) -> str:
135
+ """Stage all changes and commit.
136
+
137
+ Args:
138
+ message: Commit message
139
+
140
+ Returns:
141
+ Short commit SHA (7 characters)
142
+
143
+ Raises:
144
+ GitError: If staging or commit fails
145
+ CommandExecutionError: If git command fails
146
+ """
147
+ # Stage all changes
148
+ stage_result = self.runner.run(["git", "add", "."], timeout=GIT_STANDARD_TIMEOUT)
149
+ if not stage_result.success:
150
+ raise GitError(f"Staging failed: {stage_result.stderr}", ErrorCode.GIT_COMMAND_FAILED)
151
+
152
+ # Commit
153
+ result = self.runner.run(["git", "commit", "-m", message], timeout=GIT_STANDARD_TIMEOUT)
154
+
155
+ if not result.success:
156
+ raise GitError(f"Commit failed: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED)
157
+
158
+ # Get commit SHA
159
+ sha_result = self.runner.run(["git", "rev-parse", "HEAD"], timeout=GIT_QUICK_TIMEOUT)
160
+ commit_sha = sha_result.stdout.strip()[:7] if sha_result.success else "unknown"
161
+ return commit_sha
162
+
163
+ @convert_subprocess_errors
164
+ def push_branch(self, branch_name: str) -> None:
165
+ """Push branch to remote.
166
+
167
+ Args:
168
+ branch_name: Name of the branch to push
169
+
170
+ Raises:
171
+ GitError: If push fails (ignores no remote/upstream errors)
172
+ CommandExecutionError: If git command fails
173
+ """
174
+ result = self.runner.run(
175
+ ["git", "push", "-u", "origin", branch_name], timeout=GIT_LONG_TIMEOUT
176
+ )
177
+
178
+ if not result.success:
179
+ # Check if it's just "no upstream" error - not a real error
180
+ if "no upstream" in result.stderr.lower() or "no remote" in result.stderr.lower():
181
+ logger.info("No remote configured (local only)")
182
+ return
183
+ raise GitError(f"Push failed: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED)
184
+
185
+ @convert_subprocess_errors
186
+ def delete_remote_branch(self, branch_name: str) -> None:
187
+ """Delete branch from remote.
188
+
189
+ Args:
190
+ branch_name: Name of the remote branch to delete
191
+
192
+ Raises:
193
+ GitError: If deletion fails (ignores already deleted branches)
194
+ CommandExecutionError: If git command fails
195
+ """
196
+ result = self.runner.run(
197
+ ["git", "push", "origin", "--delete", branch_name], timeout=GIT_STANDARD_TIMEOUT
198
+ )
199
+
200
+ if not result.success:
201
+ # Not an error if branch doesn't exist on remote
202
+ if "remote ref does not exist" in result.stderr.lower():
203
+ logger.info(f"Remote branch {branch_name} doesn't exist (already deleted)")
204
+ return
205
+ raise GitError(
206
+ f"Failed to delete remote branch: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED
207
+ )
208
+
209
+ @convert_subprocess_errors
210
+ def push_main_to_remote(self, branch_name: str = "main") -> None:
211
+ """Push main (or other parent branch) to remote after local merge.
212
+
213
+ Args:
214
+ branch_name: Name of the branch to push (default: main)
215
+
216
+ Raises:
217
+ GitError: If push fails
218
+ CommandExecutionError: If git command fails
219
+ """
220
+ result = self.runner.run(["git", "push", "origin", branch_name], timeout=GIT_LONG_TIMEOUT)
221
+
222
+ if not result.success:
223
+ raise GitError(
224
+ f"Failed to push {branch_name}: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED
225
+ )
226
+
227
+ @convert_subprocess_errors
228
+ def create_pull_request(
229
+ self, work_item_id: str, branch_name: str, work_item: dict, session_num: int
230
+ ) -> str:
231
+ """Create a pull request using gh CLI.
232
+
233
+ Args:
234
+ work_item_id: ID of the work item
235
+ branch_name: Name of the branch
236
+ work_item: Work item data
237
+ session_num: Session number
238
+
239
+ Returns:
240
+ PR URL
241
+
242
+ Raises:
243
+ GitError: If PR creation fails or gh CLI not installed
244
+ CommandExecutionError: If gh command fails
245
+ """
246
+ # Check if gh CLI is available
247
+ check_gh = self.runner.run(["gh", "--version"], timeout=GIT_QUICK_TIMEOUT)
248
+
249
+ if not check_gh.success:
250
+ raise GitError(
251
+ "gh CLI not installed. Install from: https://cli.github.com/",
252
+ ErrorCode.GIT_COMMAND_FAILED,
253
+ )
254
+
255
+ # Generate PR title and body from templates
256
+ title = self._format_pr_title(work_item, session_num)
257
+ body = self._format_pr_body(work_item, work_item_id, session_num)
258
+
259
+ # Create PR using gh CLI
260
+ result = self.runner.run(
261
+ ["gh", "pr", "create", "--title", title, "--body", body], timeout=GIT_LONG_TIMEOUT
262
+ )
263
+
264
+ if not result.success:
265
+ raise GitError(f"Failed to create PR: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED)
266
+
267
+ return result.stdout.strip()
268
+
269
+ def _format_pr_title(self, work_item: dict, session_num: int) -> str:
270
+ """Format PR title from template."""
271
+ template = self.config.pr_title_template
272
+ return template.format(
273
+ type=work_item.get("type", WorkItemType.FEATURE.value).title(),
274
+ title=work_item.get("title", "Work Item"),
275
+ work_item_id=work_item.get("id", "unknown"),
276
+ session_num=session_num,
277
+ )
278
+
279
+ def _format_pr_body(self, work_item: dict, work_item_id: str, session_num: int) -> str:
280
+ """Format PR body from template."""
281
+ template = self.config.pr_body_template
282
+
283
+ # Get recent commits for this work item
284
+ commit_messages = ""
285
+ if "git" in work_item and "commits" in work_item["git"]:
286
+ commits = work_item["git"]["commits"]
287
+ if commits:
288
+ commit_messages = "\n".join([f"- {c}" for c in commits])
289
+
290
+ return template.format(
291
+ work_item_id=work_item_id,
292
+ type=work_item.get("type", WorkItemType.FEATURE.value),
293
+ title=work_item.get("title", ""),
294
+ description=work_item.get("description", ""),
295
+ session_num=session_num,
296
+ commit_messages=commit_messages if commit_messages else "See commits for details",
297
+ )
298
+
299
+ @convert_subprocess_errors
300
+ def merge_to_parent(self, branch_name: str, parent_branch: str = "main") -> None:
301
+ """Merge branch to parent branch and delete branch.
302
+
303
+ Args:
304
+ branch_name: Name of the branch to merge
305
+ parent_branch: Name of the parent branch to merge into (default: main)
306
+
307
+ Raises:
308
+ GitError: If checkout, merge, or delete fails
309
+ CommandExecutionError: If git command fails
310
+ """
311
+ # Checkout parent branch (not hardcoded main)
312
+ checkout_result = self.runner.run(
313
+ ["git", "checkout", parent_branch], timeout=GIT_QUICK_TIMEOUT
314
+ )
315
+ if not checkout_result.success:
316
+ raise GitError(
317
+ f"Failed to checkout {parent_branch}: {checkout_result.stderr}",
318
+ ErrorCode.GIT_COMMAND_FAILED,
319
+ )
320
+
321
+ # Merge
322
+ result = self.runner.run(
323
+ ["git", "merge", "--no-ff", branch_name], timeout=GIT_STANDARD_TIMEOUT
324
+ )
325
+
326
+ if not result.success:
327
+ raise GitError(f"Merge failed: {result.stderr}", ErrorCode.GIT_COMMAND_FAILED)
328
+
329
+ # Delete branch
330
+ self.runner.run(["git", "branch", "-d", branch_name], timeout=GIT_QUICK_TIMEOUT)
331
+
332
+ def start_work_item(self, work_item_id: str, session_num: int) -> dict:
333
+ """Start working on a work item (create or resume branch).
334
+
335
+ Args:
336
+ work_item_id: ID of the work item
337
+ session_num: Session number
338
+
339
+ Returns:
340
+ Dictionary with action, branch, success, and message
341
+
342
+ Raises:
343
+ FileOperationError: If work items file cannot be read/written
344
+ GitError: If branch operations fail
345
+ """
346
+ # Load work items
347
+ try:
348
+ with open(self.work_items_file) as f:
349
+ data = json.load(f)
350
+ except (OSError, json.JSONDecodeError) as e:
351
+ raise FileOperationError(
352
+ operation="read",
353
+ file_path=str(self.work_items_file),
354
+ details=f"Failed to load work items: {e}",
355
+ cause=e,
356
+ ) from e
357
+
358
+ work_item = data["work_items"][work_item_id]
359
+
360
+ # Check if work item already has a branch
361
+ if "git" in work_item and work_item["git"].get("status") == GitStatus.IN_PROGRESS.value:
362
+ # Resume existing branch
363
+ branch_name = work_item["git"]["branch"]
364
+ try:
365
+ self.checkout_branch(branch_name)
366
+ return {
367
+ "action": "resumed",
368
+ "branch": branch_name,
369
+ "success": True,
370
+ "message": f"Switched to branch {branch_name}",
371
+ }
372
+ except GitError as e:
373
+ return {
374
+ "action": "resumed",
375
+ "branch": branch_name,
376
+ "success": False,
377
+ "message": str(e),
378
+ }
379
+ else:
380
+ # Create new branch
381
+ try:
382
+ branch_name, parent_branch = self.create_branch(work_item_id, session_num)
383
+
384
+ # Update work item with git info (including parent branch)
385
+ work_item["git"] = {
386
+ "branch": branch_name,
387
+ "parent_branch": parent_branch, # Store parent for merging
388
+ "created_at": datetime.now().isoformat(),
389
+ "status": GitStatus.IN_PROGRESS.value,
390
+ "commits": [],
391
+ }
392
+
393
+ # Save updated work items
394
+ try:
395
+ with open(self.work_items_file, "w") as f:
396
+ json.dump(data, f, indent=2)
397
+ except OSError as e:
398
+ raise FileOperationError(
399
+ operation="write",
400
+ file_path=str(self.work_items_file),
401
+ details=f"Failed to save work items: {e}",
402
+ cause=e,
403
+ ) from e
404
+
405
+ return {
406
+ "action": "created",
407
+ "branch": branch_name,
408
+ "success": True,
409
+ "message": branch_name,
410
+ }
411
+ except GitError as e:
412
+ return {
413
+ "action": "created",
414
+ "branch": "",
415
+ "success": False,
416
+ "message": str(e),
417
+ }
418
+
419
+ def complete_work_item(
420
+ self, work_item_id: str, commit_message: str, merge: bool = False, session_num: int = 1
421
+ ) -> dict:
422
+ """Complete work on a work item (commit, push, optionally merge or create PR).
423
+
424
+ Behavior depends on git_workflow.mode config:
425
+ - "pr": Commit, push, create pull request (no local merge)
426
+ - "local": Commit, push, merge locally, push main, delete remote branch
427
+
428
+ Args:
429
+ work_item_id: ID of the work item
430
+ commit_message: Commit message
431
+ merge: Whether to merge/create PR
432
+ session_num: Session number
433
+
434
+ Returns:
435
+ Dictionary with success, commit, pushed, and message
436
+
437
+ Raises:
438
+ FileOperationError: If work items file cannot be read/written
439
+ """
440
+ # Load work items
441
+ try:
442
+ with open(self.work_items_file) as f:
443
+ data = json.load(f)
444
+ except (OSError, json.JSONDecodeError) as e:
445
+ raise FileOperationError(
446
+ operation="read",
447
+ file_path=str(self.work_items_file),
448
+ details=f"Failed to load work items: {e}",
449
+ cause=e,
450
+ ) from e
451
+
452
+ work_item = data["work_items"][work_item_id]
453
+
454
+ if "git" not in work_item:
455
+ return {
456
+ "success": False,
457
+ "message": "Work item has no git tracking (may be single-session item)",
458
+ }
459
+
460
+ branch_name = work_item["git"]["branch"]
461
+ workflow_mode = self.config.mode
462
+
463
+ # Step 1: Commit changes (if there are any)
464
+ try:
465
+ commit_sha = self.commit_changes(commit_message)
466
+ # Update work item commits with the new commit
467
+ if commit_sha not in work_item["git"]["commits"]:
468
+ work_item["git"]["commits"].append(commit_sha)
469
+ except GitError as e:
470
+ # If commit fails because there's nothing to commit, extract existing commits
471
+ if "nothing to commit" in str(e).lower():
472
+ # No new changes to commit - extract existing commits from git log
473
+ result = self.runner.run(
474
+ [
475
+ "git",
476
+ "log",
477
+ "--format=%h",
478
+ branch_name,
479
+ f"^{work_item['git'].get('parent_branch', 'main')}",
480
+ ],
481
+ timeout=GIT_STANDARD_TIMEOUT,
482
+ )
483
+
484
+ if result.success and result.stdout.strip():
485
+ existing_commits = result.stdout.strip().split("\n")
486
+ # Update commits array with any new commits not already tracked
487
+ for commit in reversed(existing_commits): # Oldest to newest
488
+ if commit not in work_item["git"]["commits"]:
489
+ work_item["git"]["commits"].append(commit)
490
+
491
+ # If we found commits, treat this as success
492
+ if existing_commits:
493
+ commit_sha = f"Found {len(existing_commits)} existing commit(s)"
494
+ else:
495
+ return {"success": False, "message": "No commits found for this work item"}
496
+ else:
497
+ return {
498
+ "success": False,
499
+ "message": f"Failed to retrieve commits: {str(e)}",
500
+ }
501
+ else:
502
+ return {"success": False, "message": f"Commit failed: {str(e)}"}
503
+
504
+ # Step 2: Push to remote (if enabled)
505
+ push_success = True
506
+ try:
507
+ self.push_branch(branch_name)
508
+ except GitError as e:
509
+ push_success = False
510
+ logger.warning(f"Push failed: {e}")
511
+
512
+ # Step 3: Handle completion based on workflow mode
513
+ if merge and work_item["status"] == WorkItemStatus.COMPLETED.value:
514
+ if workflow_mode == "pr":
515
+ # PR Mode: Create pull request (no local merge)
516
+ pr_success = False
517
+ pr_msg = "PR creation skipped (auto_create_pr disabled)"
518
+
519
+ if self.config.auto_create_pr:
520
+ try:
521
+ pr_url = self.create_pull_request(
522
+ work_item_id, branch_name, work_item, session_num
523
+ )
524
+ pr_success = True
525
+ pr_msg = f"PR created: {pr_url}"
526
+ except GitError as e:
527
+ pr_msg = str(e)
528
+
529
+ if pr_success:
530
+ work_item["git"]["status"] = GitStatus.PR_CREATED.value
531
+ work_item["git"]["pr_url"] = pr_msg.split(": ")[-1] if ": " in pr_msg else ""
532
+ else:
533
+ work_item["git"]["status"] = GitStatus.READY_FOR_PR.value
534
+
535
+ message = f"Committed {commit_sha}, Pushed to remote. {pr_msg}"
536
+
537
+ else:
538
+ # Local Mode: Merge locally, push main, delete remote branch
539
+ parent_branch = work_item["git"].get("parent_branch", "main")
540
+
541
+ # Merge locally
542
+ try:
543
+ self.merge_to_parent(branch_name, parent_branch)
544
+ merge_success = True
545
+ merge_msg = f"Merged to {parent_branch} and branch deleted"
546
+ except GitError as e:
547
+ merge_success = False
548
+ merge_msg = str(e)
549
+
550
+ if merge_success:
551
+ # Push merged main to remote
552
+ try:
553
+ self.push_main_to_remote(parent_branch)
554
+ push_main_msg = f"Pushed {parent_branch} to remote"
555
+ except GitError as e:
556
+ push_main_msg = f"Failed to push {parent_branch}: {e}"
557
+
558
+ # Delete remote branch if configured
559
+ if self.config.delete_branch_after_merge:
560
+ try:
561
+ self.delete_remote_branch(branch_name)
562
+ delete_msg = f"Deleted remote branch {branch_name}"
563
+ except GitError as e:
564
+ delete_msg = f"Failed to delete remote branch: {e}"
565
+ else:
566
+ delete_msg = "Remote branch kept (delete_branch_after_merge disabled)"
567
+
568
+ work_item["git"]["status"] = GitStatus.MERGED.value
569
+ message = f"Committed {commit_sha}, {merge_msg}, {push_main_msg}, {delete_msg}"
570
+ else:
571
+ work_item["git"]["status"] = GitStatus.READY_TO_MERGE.value
572
+ message = f"Committed {commit_sha}, {merge_msg} - Manual merge required"
573
+ else:
574
+ # Work not complete or merge not requested
575
+ work_item["git"]["status"] = (
576
+ GitStatus.READY_TO_MERGE.value
577
+ if work_item["status"] == WorkItemStatus.COMPLETED.value
578
+ else GitStatus.IN_PROGRESS.value
579
+ )
580
+ push_msg = "Pushed to remote" if push_success else "Push failed"
581
+ message = f"Committed {commit_sha}, {push_msg}"
582
+
583
+ # Save updated work items
584
+ try:
585
+ with open(self.work_items_file, "w") as f:
586
+ json.dump(data, f, indent=2)
587
+ except OSError as e:
588
+ raise FileOperationError(
589
+ operation="write",
590
+ file_path=str(self.work_items_file),
591
+ details=f"Failed to save work items: {e}",
592
+ cause=e,
593
+ ) from e
594
+
595
+ return {
596
+ "success": True,
597
+ "commit": commit_sha,
598
+ "pushed": push_success,
599
+ "message": message,
600
+ }
601
+
602
+
603
+ def main() -> None:
604
+ """CLI entry point for testing."""
605
+ workflow = GitWorkflow()
606
+
607
+ # Check status
608
+ try:
609
+ workflow.check_git_status()
610
+ logger.info("Git status: Clean")
611
+ except (NotAGitRepoError, WorkingDirNotCleanError, CommandExecutionError) as e:
612
+ logger.error(f"Git status: {e}")
613
+
614
+ current_branch = workflow.get_current_branch()
615
+ logger.info(f"Current branch: {current_branch}")
616
+
617
+
618
+ if __name__ == "__main__":
619
+ main()
@@ -0,0 +1,41 @@
1
+ """
2
+ Solokit Init Module
3
+
4
+ This module contains deterministic scripts for template-based project initialization.
5
+ Each script handles a specific phase of the initialization process.
6
+
7
+ Module Organization:
8
+ - git_setup.py: Git initialization and verification
9
+ - environment_validator.py: Environment validation with auto-update (pyenv, nvm)
10
+ - template_installer.py: Template file copying and installation
11
+ - readme_generator.py: README.md generation
12
+ - config_generator.py: Config file generation (.eslintrc, .prettierrc, etc.)
13
+ - dependency_installer.py: Dependency installation (npm/pip)
14
+ - docs_structure.py: Documentation directory creation
15
+ - code_generator.py: Minimal code generation
16
+ - test_generator.py: Smoke test generation
17
+ - env_generator.py: Environment file generation (.env.example)
18
+ - session_structure.py: Session structure initialization
19
+ - initial_scans.py: Initial scans (stack.txt, tree.txt)
20
+ - git_hooks.py: Git hooks installation
21
+ - gitignore_updater.py: .gitignore updates
22
+ - initial_commit.py: Initial commit creation
23
+ """
24
+
25
+ __all__ = [
26
+ "git_setup",
27
+ "environment_validator",
28
+ "template_installer",
29
+ "readme_generator",
30
+ "config_generator",
31
+ "dependency_installer",
32
+ "docs_structure",
33
+ "code_generator",
34
+ "test_generator",
35
+ "env_generator",
36
+ "session_structure",
37
+ "initial_scans",
38
+ "git_hooks",
39
+ "gitignore_updater",
40
+ "initial_commit",
41
+ ]