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,113 @@
1
+ """Fast dependent lookup for Claude Code integration.
2
+
3
+ This module provides optimized lookup of work items that depend on a given work item.
4
+ Used by /work-delete command to check if deleting a work item will affect others.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import sys
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+
15
+ def get_dependents(work_item_id: str) -> list[dict[str, Any]]:
16
+ """Get list of work items that depend on the given work item.
17
+
18
+ Args:
19
+ work_item_id: ID of the work item to check for dependents
20
+
21
+ Returns:
22
+ List of dependent work items with keys: id, type, title, status
23
+
24
+ Raises:
25
+ FileNotFoundError: If work_items.json doesn't exist
26
+ json.JSONDecodeError: If work_items.json is invalid
27
+ """
28
+ # Find .session directory
29
+ session_dir = _find_session_dir()
30
+ if not session_dir:
31
+ print("Error: Not in an Solokit project (no .session directory found)", file=sys.stderr)
32
+ return []
33
+
34
+ # Load work items
35
+ work_items_file = session_dir / "tracking" / "work_items.json"
36
+ if not work_items_file.exists():
37
+ print(f"Error: Work items file not found: {work_items_file}", file=sys.stderr)
38
+ return []
39
+
40
+ try:
41
+ with open(work_items_file) as f:
42
+ data = json.load(f)
43
+ except json.JSONDecodeError as e:
44
+ print(f"Error: Invalid JSON in {work_items_file}: {e}", file=sys.stderr)
45
+ return []
46
+
47
+ # Extract work_items from the data structure
48
+ work_items = data.get("work_items", {})
49
+ if not work_items:
50
+ print("No work items found", file=sys.stderr)
51
+ return []
52
+
53
+ # Find dependents (work items that have this work_item_id in their dependencies)
54
+ dependents = []
55
+ for item_id, item in work_items.items():
56
+ dependencies = item.get("dependencies", [])
57
+ if work_item_id in dependencies:
58
+ dependents.append(
59
+ {
60
+ "id": item_id,
61
+ "type": item.get("type", "unknown"),
62
+ "title": item.get("title", "Untitled"),
63
+ "status": item.get("status", "unknown"),
64
+ }
65
+ )
66
+
67
+ return dependents
68
+
69
+
70
+ def _find_session_dir() -> Path | None:
71
+ """Find the .session directory by walking up from current directory."""
72
+ current = Path.cwd()
73
+ while current != current.parent:
74
+ session_dir = current / ".session"
75
+ if session_dir.is_dir():
76
+ return session_dir
77
+ current = current.parent
78
+ return None
79
+
80
+
81
+ def main() -> None:
82
+ """CLI entry point for get_dependents script.
83
+
84
+ Usage:
85
+ python -m solokit.work_items.get_dependents <work_item_id>
86
+ """
87
+ import argparse
88
+
89
+ parser = argparse.ArgumentParser(description="Get work items that depend on a given work item")
90
+ parser.add_argument("work_item_id", help="ID of the work item to check for dependents")
91
+
92
+ args = parser.parse_args()
93
+
94
+ # Get dependents
95
+ dependents = get_dependents(args.work_item_id)
96
+
97
+ # Output results
98
+ if not dependents:
99
+ print(f"No work items depend on '{args.work_item_id}'")
100
+ sys.exit(0)
101
+
102
+ print(f"Found {len(dependents)} work item(s) that depend on '{args.work_item_id}':")
103
+ print()
104
+ for dep in dependents:
105
+ print(f"ID: {dep['id']}")
106
+ print(f"Type: {dep['type']}")
107
+ print(f"Title: {dep['title']}")
108
+ print(f"Status: {dep['status']}")
109
+ print()
110
+
111
+
112
+ if __name__ == "__main__":
113
+ main()
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Get work item metadata without loading full spec.
4
+
5
+ Lightweight utility to fetch just the metadata fields for a work item,
6
+ avoiding the overhead of loading and displaying full specifications.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import sys
13
+ from pathlib import Path
14
+
15
+
16
+ def get_work_item_metadata(
17
+ work_item_id: str, include_dependency_details: bool = False
18
+ ) -> dict | None:
19
+ """Get work item metadata without loading spec file.
20
+
21
+ Args:
22
+ work_item_id: ID of the work item
23
+ include_dependency_details: If True, include full details (type, title) for each dependency
24
+
25
+ Returns:
26
+ dict: Work item metadata (id, type, title, status, priority, dependencies, milestone)
27
+ If include_dependency_details=True, also includes 'dependency_details' list
28
+ None: If work item doesn't exist
29
+ """
30
+ # Find work_items.json
31
+ session_dir = Path.cwd() / ".session"
32
+ work_items_file = session_dir / "tracking" / "work_items.json"
33
+
34
+ if not work_items_file.exists():
35
+ return None
36
+
37
+ # Load work items
38
+ with open(work_items_file) as f:
39
+ data = json.load(f)
40
+
41
+ work_items = data.get("work_items", {})
42
+
43
+ if work_item_id not in work_items:
44
+ return None
45
+
46
+ item = work_items[work_item_id]
47
+
48
+ # Build metadata
49
+ metadata = {
50
+ "id": item["id"],
51
+ "type": item["type"],
52
+ "title": item["title"],
53
+ "status": item["status"],
54
+ "priority": item["priority"],
55
+ "dependencies": item.get("dependencies", []),
56
+ "milestone": item.get("milestone", ""),
57
+ }
58
+
59
+ # Optionally include dependency details (fetch all in one pass)
60
+ if include_dependency_details and metadata["dependencies"]:
61
+ dep_details = []
62
+ for dep_id in metadata["dependencies"]:
63
+ if dep_id in work_items:
64
+ dep_item = work_items[dep_id]
65
+ dep_details.append(
66
+ {
67
+ "id": dep_id,
68
+ "type": dep_item["type"],
69
+ "title": dep_item["title"],
70
+ "status": dep_item.get("status", "unknown"),
71
+ }
72
+ )
73
+ metadata["dependency_details"] = dep_details
74
+
75
+ return metadata
76
+
77
+
78
+ def main() -> int:
79
+ """CLI entry point."""
80
+ if len(sys.argv) < 2:
81
+ print(
82
+ "Usage: python -m solokit.work_items.get_metadata <work_item_id> [--with-deps]",
83
+ file=sys.stderr,
84
+ )
85
+ sys.exit(1)
86
+
87
+ work_item_id = sys.argv[1]
88
+ include_deps = "--with-deps" in sys.argv
89
+
90
+ metadata = get_work_item_metadata(work_item_id, include_dependency_details=include_deps)
91
+
92
+ if metadata is None:
93
+ print(f"Error: Work item '{work_item_id}' not found", file=sys.stderr)
94
+ sys.exit(1)
95
+
96
+ # Print in a clean, parseable format
97
+ print(f"ID: {metadata['id']}")
98
+ print(f"Type: {metadata['type']}")
99
+ print(f"Title: {metadata['title']}")
100
+ print(f"Status: {metadata['status']}")
101
+ print(f"Priority: {metadata['priority']}")
102
+ print(f"Milestone: {metadata['milestone'] or '(none)'}")
103
+
104
+ if metadata["dependencies"]:
105
+ if "dependency_details" in metadata:
106
+ # Print with full details
107
+ deps_str = []
108
+ for dep in metadata["dependency_details"]:
109
+ deps_str.append(f"{dep['id']} ([{dep['type']}] {dep['title']} - {dep['status']})")
110
+ print("Dependencies:\n " + "\n ".join(deps_str))
111
+ else:
112
+ # Print just IDs
113
+ print(f"Dependencies: {', '.join(metadata['dependencies'])}")
114
+ else:
115
+ print("Dependencies: (none)")
116
+
117
+ return 0
118
+
119
+
120
+ if __name__ == "__main__":
121
+ sys.exit(main())
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Get next recommended work items for interactive selection.
4
+
5
+ This script returns the top 4 ready-to-start work items based on:
6
+ - Dependencies are satisfied (not blocked)
7
+ - Priority (critical > high > medium > low)
8
+ - Status is not_started
9
+
10
+ Output format (one per line):
11
+ work_item_id | type | title | priority
12
+
13
+ Usage:
14
+ python -m solokit.work_items.get_next_recommendations [--limit N]
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import json
20
+ import sys
21
+ from pathlib import Path
22
+ from typing import Any
23
+
24
+
25
+ def get_ready_work_items(limit: int = 4) -> list[dict[str, Any]]:
26
+ """Get list of ready-to-start work items sorted by priority.
27
+
28
+ Args:
29
+ limit: Maximum number of items to return (default 4)
30
+
31
+ Returns:
32
+ list: Ready work items with id, type, title, priority
33
+ """
34
+ # Find work_items.json
35
+ work_items_file = Path(".session/tracking/work_items.json")
36
+ if not work_items_file.exists():
37
+ print("Error: .session/tracking/work_items.json not found", file=sys.stderr)
38
+ return []
39
+
40
+ # Load work items
41
+ try:
42
+ with open(work_items_file) as f:
43
+ data = json.load(f)
44
+ except json.JSONDecodeError as e:
45
+ print(f"Error: Invalid JSON in {work_items_file}: {e}", file=sys.stderr)
46
+ return []
47
+
48
+ # Extract work_items from data structure
49
+ work_items = data.get("work_items", {})
50
+ if not work_items:
51
+ print("No work items found", file=sys.stderr)
52
+ return []
53
+
54
+ # Filter to not_started items
55
+ not_started = {
56
+ wid: item for wid, item in work_items.items() if item.get("status") == "not_started"
57
+ }
58
+
59
+ if not not_started:
60
+ print("No work items available to start", file=sys.stderr)
61
+ return []
62
+
63
+ # Check dependencies and filter to ready items
64
+ ready_items = []
65
+
66
+ for work_id, item in not_started.items():
67
+ dependencies = item.get("dependencies", [])
68
+
69
+ # Check if all dependencies are completed
70
+ is_ready = True
71
+ if dependencies:
72
+ for dep_id in dependencies:
73
+ dep_item = work_items.get(dep_id)
74
+ if not dep_item or dep_item.get("status") != "completed":
75
+ is_ready = False
76
+ break
77
+
78
+ if is_ready:
79
+ ready_items.append(
80
+ {
81
+ "id": work_id,
82
+ "type": item.get("type", "unknown"),
83
+ "title": item.get("title", "Untitled"),
84
+ "priority": item.get("priority", "medium"),
85
+ }
86
+ )
87
+
88
+ if not ready_items:
89
+ print("No work items ready to start. All have unmet dependencies.", file=sys.stderr)
90
+ return []
91
+
92
+ # Sort by priority (critical > high > medium > low)
93
+ priority_order = {
94
+ "critical": 0,
95
+ "high": 1,
96
+ "medium": 2,
97
+ "low": 3,
98
+ }
99
+ ready_items.sort(key=lambda x: priority_order.get(x["priority"], 99))
100
+
101
+ # Return top N items
102
+ return ready_items[:limit]
103
+
104
+
105
+ def main() -> int:
106
+ """Main entry point for script."""
107
+ import argparse
108
+
109
+ parser = argparse.ArgumentParser(
110
+ description="Get next recommended work items for interactive selection"
111
+ )
112
+ parser.add_argument(
113
+ "--limit",
114
+ type=int,
115
+ default=4,
116
+ help="Maximum number of recommendations to return (default: 4)",
117
+ )
118
+ args = parser.parse_args()
119
+
120
+ ready_items = get_ready_work_items(limit=args.limit)
121
+
122
+ if not ready_items:
123
+ sys.exit(1)
124
+
125
+ # Output format: work_item_id | type | title | priority
126
+ for item in ready_items:
127
+ print(f"{item['id']} | {item['type']} | {item['title']} | {item['priority']}")
128
+
129
+ return 0
130
+
131
+
132
+ if __name__ == "__main__":
133
+ sys.exit(main())
@@ -0,0 +1,235 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Work Item Manager - Main orchestrator for work item operations.
4
+
5
+ Delegates to specialized modules for different concerns:
6
+ - creator: Work item creation and prompts
7
+ - repository: Data access and persistence
8
+ - validator: Validation logic
9
+ - query: Listing, filtering, and display
10
+ - updater: Update operations
11
+ - scheduler: Work queue and next item selection
12
+ - milestones: Milestone management
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ from solokit.core.constants import get_session_dir, get_specs_dir
21
+ from solokit.core.types import Priority, WorkItemType
22
+
23
+ from .creator import WorkItemCreator
24
+ from .milestones import MilestoneManager
25
+ from .query import WorkItemQuery
26
+ from .repository import WorkItemRepository
27
+ from .scheduler import WorkItemScheduler
28
+ from .updater import WorkItemUpdater
29
+ from .validator import WorkItemValidator
30
+
31
+
32
+ class WorkItemManager:
33
+ """Main orchestrator for work item operations"""
34
+
35
+ WORK_ITEM_TYPES = WorkItemType.values()
36
+ PRIORITIES = Priority.values()
37
+
38
+ def __init__(self, project_root: Path | None = None):
39
+ """Initialize manager with dependency injection
40
+
41
+ Args:
42
+ project_root: Optional project root path (defaults to current directory)
43
+ """
44
+ self.project_root = project_root or Path.cwd()
45
+ self.session_dir = get_session_dir(self.project_root)
46
+
47
+ # Initialize components
48
+ self.repository = WorkItemRepository(self.session_dir)
49
+ self.creator = WorkItemCreator(self.repository)
50
+ self.validator = WorkItemValidator()
51
+ self.query = WorkItemQuery(self.repository)
52
+ self.updater = WorkItemUpdater(self.repository, self.validator)
53
+ self.scheduler = WorkItemScheduler(self.repository)
54
+ self.milestones = MilestoneManager(self.repository)
55
+
56
+ # Legacy compatibility - maintain these paths for backward compatibility
57
+ self.work_items_file = self.repository.work_items_file
58
+ self.specs_dir = get_specs_dir(self.project_root)
59
+ self.templates_dir = Path(__file__).parent.parent / "templates"
60
+
61
+ # Delegate creation methods
62
+ def create_work_item_from_args(
63
+ self, work_type: str, title: str, priority: str = "high", dependencies: str = ""
64
+ ) -> str:
65
+ """Create work item from command-line arguments
66
+
67
+ Args:
68
+ work_type: Type of work item (feature, bug, refactor, etc.)
69
+ title: Title of the work item
70
+ priority: Priority level (critical, high, medium, low)
71
+ dependencies: Comma-separated dependency IDs
72
+
73
+ Returns:
74
+ str: The created work item ID
75
+
76
+ Raises:
77
+ ValidationError: If work type is invalid
78
+ WorkItemAlreadyExistsError: If work item with generated ID already exists
79
+ FileOperationError: If spec file creation or tracking update fails
80
+ """
81
+ return self.creator.create_from_args(work_type, title, priority, dependencies)
82
+
83
+ # Delegate query methods
84
+ def list_work_items(
85
+ self,
86
+ status_filter: str | None = None,
87
+ type_filter: str | None = None,
88
+ milestone_filter: str | None = None,
89
+ ) -> dict:
90
+ """List work items with optional filters
91
+
92
+ Args:
93
+ status_filter: Optional status filter
94
+ type_filter: Optional type filter
95
+ milestone_filter: Optional milestone filter
96
+
97
+ Returns:
98
+ dict: Dictionary with 'items' list and 'count'
99
+ """
100
+ return self.query.list_items(status_filter, type_filter, milestone_filter)
101
+
102
+ def show_work_item(self, work_id: str) -> dict[str, Any]:
103
+ """Show detailed information about a work item
104
+
105
+ Args:
106
+ work_id: ID of the work item to display
107
+
108
+ Returns:
109
+ dict: The work item data
110
+
111
+ Raises:
112
+ FileOperationError: If work_items.json doesn't exist
113
+ WorkItemNotFoundError: If work item doesn't exist
114
+ """
115
+ return self.query.show_item(work_id)
116
+
117
+ # Delegate update methods
118
+ def update_work_item(self, work_id: str, **updates: Any) -> None:
119
+ """Update a work item
120
+
121
+ Args:
122
+ work_id: ID of the work item to update
123
+ **updates: Field updates (status, priority, milestone, add_dependency, remove_dependency)
124
+
125
+ Raises:
126
+ FileOperationError: If work_items.json doesn't exist
127
+ WorkItemNotFoundError: If work item doesn't exist
128
+ ValidationError: If invalid status or priority provided
129
+ """
130
+ return self.updater.update(work_id, **updates)
131
+
132
+ # Delegate scheduler methods
133
+ def get_next_work_item(self) -> dict[str, Any] | None:
134
+ """Get next recommended work item based on dependencies and priority
135
+
136
+ Returns:
137
+ dict: Next work item to start, or None if none available
138
+ """
139
+ return self.scheduler.get_next()
140
+
141
+ # Delegate validation methods
142
+ def validate_integration_test(self, work_item: dict) -> None:
143
+ """Validate integration test work item
144
+
145
+ Args:
146
+ work_item: Work item dictionary to validate
147
+
148
+ Raises:
149
+ FileOperationError: If spec file not found
150
+ ValidationError: If spec validation fails (with validation errors in context)
151
+ """
152
+ return self.validator.validate_integration_test(work_item)
153
+
154
+ def validate_deployment(self, work_item: dict) -> None:
155
+ """Validate deployment work item
156
+
157
+ Args:
158
+ work_item: Work item dictionary to validate
159
+
160
+ Raises:
161
+ FileOperationError: If spec file not found
162
+ ValidationError: If spec validation fails (with validation errors in context)
163
+ """
164
+ return self.validator.validate_deployment(work_item)
165
+
166
+ # Delegate milestone methods
167
+ def create_milestone(
168
+ self, name: str, title: str, description: str, target_date: str | None = None
169
+ ) -> None:
170
+ """Create a new milestone
171
+
172
+ Args:
173
+ name: Milestone name (unique identifier)
174
+ title: Milestone title
175
+ description: Milestone description
176
+ target_date: Optional target completion date
177
+
178
+ Raises:
179
+ ValidationError: If milestone with this name already exists
180
+ FileOperationError: If saving milestone fails
181
+ """
182
+ return self.milestones.create(name, title, description, target_date)
183
+
184
+ def get_milestone_progress(self, milestone_name: str) -> dict:
185
+ """Get milestone progress
186
+
187
+ Args:
188
+ milestone_name: Name of the milestone
189
+
190
+ Returns:
191
+ dict: Progress statistics including total, completed, in_progress, not_started, percent
192
+ """
193
+ return self.milestones.get_progress(milestone_name)
194
+
195
+ def list_milestones(self) -> None:
196
+ """List all milestones with progress"""
197
+ return self.milestones.list_all()
198
+
199
+
200
+ def main() -> int:
201
+ """CLI entry point."""
202
+ import argparse
203
+
204
+ parser = argparse.ArgumentParser(description="Work Item Manager")
205
+ parser.add_argument(
206
+ "--type",
207
+ help="Work item type (feature, bug, refactor, security, integration_test, deployment)",
208
+ )
209
+ parser.add_argument("--title", help="Work item title")
210
+ parser.add_argument("--priority", default="high", help="Priority (critical, high, medium, low)")
211
+ parser.add_argument("--dependencies", default="", help="Comma-separated dependency IDs")
212
+
213
+ args = parser.parse_args()
214
+
215
+ manager = WorkItemManager()
216
+
217
+ # Require type and title arguments (no interactive mode)
218
+ if not args.type or not args.title:
219
+ parser.error("Both --type and --title are required")
220
+
221
+ work_id = manager.create_work_item_from_args(
222
+ work_type=args.type,
223
+ title=args.title,
224
+ priority=args.priority,
225
+ dependencies=args.dependencies,
226
+ )
227
+
228
+ if work_id:
229
+ return 0
230
+ else:
231
+ return 1
232
+
233
+
234
+ if __name__ == "__main__":
235
+ exit(main())