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.
- solokit/__init__.py +10 -0
- solokit/__version__.py +3 -0
- solokit/cli.py +374 -0
- solokit/core/__init__.py +1 -0
- solokit/core/cache.py +102 -0
- solokit/core/command_runner.py +278 -0
- solokit/core/config.py +453 -0
- solokit/core/config_validator.py +204 -0
- solokit/core/constants.py +291 -0
- solokit/core/error_formatter.py +279 -0
- solokit/core/error_handlers.py +346 -0
- solokit/core/exceptions.py +1567 -0
- solokit/core/file_ops.py +309 -0
- solokit/core/logging_config.py +166 -0
- solokit/core/output.py +99 -0
- solokit/core/performance.py +57 -0
- solokit/core/protocols.py +141 -0
- solokit/core/types.py +312 -0
- solokit/deployment/__init__.py +1 -0
- solokit/deployment/executor.py +411 -0
- solokit/git/__init__.py +1 -0
- solokit/git/integration.py +619 -0
- solokit/init/__init__.py +41 -0
- solokit/init/claude_commands_installer.py +87 -0
- solokit/init/dependency_installer.py +313 -0
- solokit/init/docs_structure.py +90 -0
- solokit/init/env_generator.py +160 -0
- solokit/init/environment_validator.py +334 -0
- solokit/init/git_hooks_installer.py +71 -0
- solokit/init/git_setup.py +188 -0
- solokit/init/gitignore_updater.py +195 -0
- solokit/init/initial_commit.py +145 -0
- solokit/init/initial_scans.py +109 -0
- solokit/init/orchestrator.py +246 -0
- solokit/init/readme_generator.py +207 -0
- solokit/init/session_structure.py +239 -0
- solokit/init/template_installer.py +424 -0
- solokit/learning/__init__.py +1 -0
- solokit/learning/archiver.py +115 -0
- solokit/learning/categorizer.py +126 -0
- solokit/learning/curator.py +428 -0
- solokit/learning/extractor.py +352 -0
- solokit/learning/reporter.py +351 -0
- solokit/learning/repository.py +254 -0
- solokit/learning/similarity.py +342 -0
- solokit/learning/validator.py +144 -0
- solokit/project/__init__.py +1 -0
- solokit/project/init.py +1162 -0
- solokit/project/stack.py +436 -0
- solokit/project/sync_plugin.py +438 -0
- solokit/project/tree.py +375 -0
- solokit/quality/__init__.py +1 -0
- solokit/quality/api_validator.py +424 -0
- solokit/quality/checkers/__init__.py +25 -0
- solokit/quality/checkers/base.py +114 -0
- solokit/quality/checkers/context7.py +221 -0
- solokit/quality/checkers/custom.py +162 -0
- solokit/quality/checkers/deployment.py +323 -0
- solokit/quality/checkers/documentation.py +179 -0
- solokit/quality/checkers/formatting.py +161 -0
- solokit/quality/checkers/integration.py +394 -0
- solokit/quality/checkers/linting.py +159 -0
- solokit/quality/checkers/security.py +261 -0
- solokit/quality/checkers/spec_completeness.py +127 -0
- solokit/quality/checkers/tests.py +184 -0
- solokit/quality/env_validator.py +306 -0
- solokit/quality/gates.py +655 -0
- solokit/quality/reporters/__init__.py +10 -0
- solokit/quality/reporters/base.py +25 -0
- solokit/quality/reporters/console.py +98 -0
- solokit/quality/reporters/json_reporter.py +34 -0
- solokit/quality/results.py +98 -0
- solokit/session/__init__.py +1 -0
- solokit/session/briefing/__init__.py +245 -0
- solokit/session/briefing/documentation_loader.py +53 -0
- solokit/session/briefing/formatter.py +476 -0
- solokit/session/briefing/git_context.py +282 -0
- solokit/session/briefing/learning_loader.py +212 -0
- solokit/session/briefing/milestone_builder.py +78 -0
- solokit/session/briefing/orchestrator.py +137 -0
- solokit/session/briefing/stack_detector.py +51 -0
- solokit/session/briefing/tree_generator.py +52 -0
- solokit/session/briefing/work_item_loader.py +209 -0
- solokit/session/briefing.py +353 -0
- solokit/session/complete.py +1188 -0
- solokit/session/status.py +246 -0
- solokit/session/validate.py +452 -0
- solokit/templates/.claude/commands/end.md +109 -0
- solokit/templates/.claude/commands/init.md +159 -0
- solokit/templates/.claude/commands/learn-curate.md +88 -0
- solokit/templates/.claude/commands/learn-search.md +62 -0
- solokit/templates/.claude/commands/learn-show.md +69 -0
- solokit/templates/.claude/commands/learn.md +136 -0
- solokit/templates/.claude/commands/start.md +114 -0
- solokit/templates/.claude/commands/status.md +22 -0
- solokit/templates/.claude/commands/validate.md +27 -0
- solokit/templates/.claude/commands/work-delete.md +119 -0
- solokit/templates/.claude/commands/work-graph.md +139 -0
- solokit/templates/.claude/commands/work-list.md +26 -0
- solokit/templates/.claude/commands/work-new.md +114 -0
- solokit/templates/.claude/commands/work-next.md +25 -0
- solokit/templates/.claude/commands/work-show.md +24 -0
- solokit/templates/.claude/commands/work-update.md +141 -0
- solokit/templates/CHANGELOG.md +17 -0
- solokit/templates/WORK_ITEM_TYPES.md +141 -0
- solokit/templates/__init__.py +1 -0
- solokit/templates/bug_spec.md +217 -0
- solokit/templates/config.schema.json +150 -0
- solokit/templates/dashboard_refine/base/.gitignore +36 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/layout.tsx +22 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/page.tsx +68 -0
- solokit/templates/dashboard_refine/base/app/(dashboard)/users/page.tsx +77 -0
- solokit/templates/dashboard_refine/base/app/globals.css +60 -0
- solokit/templates/dashboard_refine/base/app/layout.tsx +23 -0
- solokit/templates/dashboard_refine/base/app/page.tsx +9 -0
- solokit/templates/dashboard_refine/base/components/client-refine-wrapper.tsx +21 -0
- solokit/templates/dashboard_refine/base/components/layout/header.tsx +44 -0
- solokit/templates/dashboard_refine/base/components/layout/sidebar.tsx +82 -0
- solokit/templates/dashboard_refine/base/components/ui/button.tsx +53 -0
- solokit/templates/dashboard_refine/base/components/ui/card.tsx +78 -0
- solokit/templates/dashboard_refine/base/components/ui/table.tsx +116 -0
- solokit/templates/dashboard_refine/base/components.json +16 -0
- solokit/templates/dashboard_refine/base/lib/refine.tsx +65 -0
- solokit/templates/dashboard_refine/base/lib/utils.ts +13 -0
- solokit/templates/dashboard_refine/base/next.config.ts +10 -0
- solokit/templates/dashboard_refine/base/package.json.template +40 -0
- solokit/templates/dashboard_refine/base/postcss.config.mjs +8 -0
- solokit/templates/dashboard_refine/base/providers/refine-provider.tsx +26 -0
- solokit/templates/dashboard_refine/base/tailwind.config.ts +57 -0
- solokit/templates/dashboard_refine/base/tsconfig.json +27 -0
- solokit/templates/dashboard_refine/docker/Dockerfile +57 -0
- solokit/templates/dashboard_refine/docker/docker-compose.prod.yml +31 -0
- solokit/templates/dashboard_refine/docker/docker-compose.yml +21 -0
- solokit/templates/dashboard_refine/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/dashboard_refine/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/dashboard_refine/tier-1-essential/package.json.tier1.template +57 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/setup.ts +26 -0
- solokit/templates/dashboard_refine/tier-1-essential/tests/unit/example.test.tsx +73 -0
- solokit/templates/dashboard_refine/tier-2-standard/package.json.tier2.template +62 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/eslint.config.mjs +22 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/package.json.tier3.template +79 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/stryker.conf.json +38 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/dashboard.spec.ts +88 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/e2e/user-management.spec.ts +102 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/tests/integration/dashboard.test.tsx +90 -0
- solokit/templates/dashboard_refine/tier-3-comprehensive/type-coverage.json +16 -0
- solokit/templates/dashboard_refine/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/dashboard_refine/tier-4-production/k6/dashboard-load-test.js +70 -0
- solokit/templates/dashboard_refine/tier-4-production/next.config.ts +46 -0
- solokit/templates/dashboard_refine/tier-4-production/package.json.tier4.template +89 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/dashboard_refine/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/deployment_spec.md +500 -0
- solokit/templates/feature_spec.md +248 -0
- solokit/templates/fullstack_nextjs/base/.gitignore +36 -0
- solokit/templates/fullstack_nextjs/base/app/api/example/route.ts +65 -0
- solokit/templates/fullstack_nextjs/base/app/globals.css +27 -0
- solokit/templates/fullstack_nextjs/base/app/layout.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/app/page.tsx +32 -0
- solokit/templates/fullstack_nextjs/base/components/example-component.tsx +20 -0
- solokit/templates/fullstack_nextjs/base/lib/prisma.ts +17 -0
- solokit/templates/fullstack_nextjs/base/lib/utils.ts +13 -0
- solokit/templates/fullstack_nextjs/base/lib/validations.ts +20 -0
- solokit/templates/fullstack_nextjs/base/next.config.ts +7 -0
- solokit/templates/fullstack_nextjs/base/package.json.template +32 -0
- solokit/templates/fullstack_nextjs/base/postcss.config.mjs +8 -0
- solokit/templates/fullstack_nextjs/base/prisma/schema.prisma +21 -0
- solokit/templates/fullstack_nextjs/base/tailwind.config.ts +19 -0
- solokit/templates/fullstack_nextjs/base/tsconfig.json +27 -0
- solokit/templates/fullstack_nextjs/docker/Dockerfile +60 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.prod.yml +57 -0
- solokit/templates/fullstack_nextjs/docker/docker-compose.yml +47 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/package.json.tier1.template +48 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/api/example.test.ts +88 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/fullstack_nextjs/tier-1-essential/tests/unit/example.test.tsx +22 -0
- solokit/templates/fullstack_nextjs/tier-2-standard/package.json.tier2.template +52 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/package.json.tier3.template +68 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/stryker.conf.json +33 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/e2e/flow.spec.ts +59 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/tests/integration/api.test.ts +165 -0
- solokit/templates/fullstack_nextjs/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/fullstack_nextjs/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/fullstack_nextjs/tier-4-production/k6/load-test.js +45 -0
- solokit/templates/fullstack_nextjs/tier-4-production/next.config.ts +46 -0
- solokit/templates/fullstack_nextjs/tier-4-production/package.json.tier4.template +77 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/fullstack_nextjs/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/git-hooks/prepare-commit-msg +24 -0
- solokit/templates/integration_test_spec.md +363 -0
- solokit/templates/learnings.json +15 -0
- solokit/templates/ml_ai_fastapi/base/.gitignore +104 -0
- solokit/templates/ml_ai_fastapi/base/alembic/env.py +96 -0
- solokit/templates/ml_ai_fastapi/base/alembic.ini +114 -0
- solokit/templates/ml_ai_fastapi/base/pyproject.toml.template +91 -0
- solokit/templates/ml_ai_fastapi/base/requirements.txt.template +28 -0
- solokit/templates/ml_ai_fastapi/base/src/__init__.py +5 -0
- solokit/templates/ml_ai_fastapi/base/src/api/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/dependencies.py +20 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/example.py +134 -0
- solokit/templates/ml_ai_fastapi/base/src/api/routes/health.py +66 -0
- solokit/templates/ml_ai_fastapi/base/src/core/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/core/config.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/core/database.py +50 -0
- solokit/templates/ml_ai_fastapi/base/src/main.py +64 -0
- solokit/templates/ml_ai_fastapi/base/src/models/__init__.py +7 -0
- solokit/templates/ml_ai_fastapi/base/src/models/example.py +61 -0
- solokit/templates/ml_ai_fastapi/base/src/services/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/base/src/services/example.py +115 -0
- solokit/templates/ml_ai_fastapi/docker/Dockerfile +59 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.prod.yml +112 -0
- solokit/templates/ml_ai_fastapi/docker/docker-compose.yml +77 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyproject.toml.tier1.template +112 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pyrightconfig.json +41 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/pytest.ini +69 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/requirements-dev.txt +17 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/ruff.toml +81 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/conftest.py +72 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/test_main.py +49 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-1-essential/tests/unit/test_example.py +113 -0
- solokit/templates/ml_ai_fastapi/tier-2-standard/pyproject.toml.tier2.template +130 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/locustfile.py +99 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/mutmut_config.py +53 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/pyproject.toml.tier3.template +150 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/conftest.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-3-comprehensive/tests/integration/test_api.py +131 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/pyproject.toml.tier4.template +162 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/requirements-prod.txt +25 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/api/routes/metrics.py +19 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/logging.py +74 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/monitoring.py +68 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/core/sentry.py +66 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/__init__.py +3 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/logging.py +79 -0
- solokit/templates/ml_ai_fastapi/tier-4-production/src/middleware/tracing.py +60 -0
- solokit/templates/refactor_spec.md +287 -0
- solokit/templates/saas_t3/base/.gitignore +36 -0
- solokit/templates/saas_t3/base/app/api/trpc/[trpc]/route.ts +33 -0
- solokit/templates/saas_t3/base/app/globals.css +27 -0
- solokit/templates/saas_t3/base/app/layout.tsx +23 -0
- solokit/templates/saas_t3/base/app/page.tsx +31 -0
- solokit/templates/saas_t3/base/lib/api.tsx +77 -0
- solokit/templates/saas_t3/base/lib/utils.ts +13 -0
- solokit/templates/saas_t3/base/next.config.ts +7 -0
- solokit/templates/saas_t3/base/package.json.template +38 -0
- solokit/templates/saas_t3/base/postcss.config.mjs +8 -0
- solokit/templates/saas_t3/base/prisma/schema.prisma +20 -0
- solokit/templates/saas_t3/base/server/api/root.ts +19 -0
- solokit/templates/saas_t3/base/server/api/routers/example.ts +28 -0
- solokit/templates/saas_t3/base/server/api/trpc.ts +52 -0
- solokit/templates/saas_t3/base/server/db.ts +17 -0
- solokit/templates/saas_t3/base/tailwind.config.ts +19 -0
- solokit/templates/saas_t3/base/tsconfig.json +27 -0
- solokit/templates/saas_t3/docker/Dockerfile +60 -0
- solokit/templates/saas_t3/docker/docker-compose.prod.yml +59 -0
- solokit/templates/saas_t3/docker/docker-compose.yml +49 -0
- solokit/templates/saas_t3/tier-1-essential/.eslintrc.json +7 -0
- solokit/templates/saas_t3/tier-1-essential/jest.config.ts +17 -0
- solokit/templates/saas_t3/tier-1-essential/jest.setup.ts +1 -0
- solokit/templates/saas_t3/tier-1-essential/package.json.tier1.template +54 -0
- solokit/templates/saas_t3/tier-1-essential/tests/setup.ts +22 -0
- solokit/templates/saas_t3/tier-1-essential/tests/unit/example.test.tsx +24 -0
- solokit/templates/saas_t3/tier-2-standard/package.json.tier2.template +58 -0
- solokit/templates/saas_t3/tier-3-comprehensive/eslint.config.mjs +39 -0
- solokit/templates/saas_t3/tier-3-comprehensive/package.json.tier3.template +74 -0
- solokit/templates/saas_t3/tier-3-comprehensive/playwright.config.ts +66 -0
- solokit/templates/saas_t3/tier-3-comprehensive/stryker.conf.json +34 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/e2e/home.spec.ts +41 -0
- solokit/templates/saas_t3/tier-3-comprehensive/tests/integration/api.test.ts +44 -0
- solokit/templates/saas_t3/tier-3-comprehensive/type-coverage.json +12 -0
- solokit/templates/saas_t3/tier-4-production/instrumentation.ts +9 -0
- solokit/templates/saas_t3/tier-4-production/k6/load-test.js +51 -0
- solokit/templates/saas_t3/tier-4-production/next.config.ts +46 -0
- solokit/templates/saas_t3/tier-4-production/package.json.tier4.template +83 -0
- solokit/templates/saas_t3/tier-4-production/sentry.client.config.ts +26 -0
- solokit/templates/saas_t3/tier-4-production/sentry.edge.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/sentry.server.config.ts +11 -0
- solokit/templates/saas_t3/tier-4-production/vercel.json +37 -0
- solokit/templates/security_spec.md +287 -0
- solokit/templates/stack-versions.yaml +617 -0
- solokit/templates/status_update.json +6 -0
- solokit/templates/template-registry.json +257 -0
- solokit/templates/work_items.json +11 -0
- solokit/testing/__init__.py +1 -0
- solokit/testing/integration_runner.py +550 -0
- solokit/testing/performance.py +637 -0
- solokit/visualization/__init__.py +1 -0
- solokit/visualization/dependency_graph.py +788 -0
- solokit/work_items/__init__.py +1 -0
- solokit/work_items/creator.py +217 -0
- solokit/work_items/delete.py +264 -0
- solokit/work_items/get_dependencies.py +185 -0
- solokit/work_items/get_dependents.py +113 -0
- solokit/work_items/get_metadata.py +121 -0
- solokit/work_items/get_next_recommendations.py +133 -0
- solokit/work_items/manager.py +235 -0
- solokit/work_items/milestones.py +137 -0
- solokit/work_items/query.py +376 -0
- solokit/work_items/repository.py +267 -0
- solokit/work_items/scheduler.py +184 -0
- solokit/work_items/spec_parser.py +838 -0
- solokit/work_items/spec_validator.py +493 -0
- solokit/work_items/updater.py +157 -0
- solokit/work_items/validator.py +205 -0
- solokit-0.1.1.dist-info/METADATA +640 -0
- solokit-0.1.1.dist-info/RECORD +323 -0
- solokit-0.1.1.dist-info/WHEEL +5 -0
- solokit-0.1.1.dist-info/entry_points.txt +2 -0
- solokit-0.1.1.dist-info/licenses/LICENSE +21 -0
- solokit-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Gitignore Updater Module
|
|
3
|
+
|
|
4
|
+
Updates .gitignore with Solokit and stack-specific entries.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from solokit.core.exceptions import FileOperationError
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_stack_specific_gitignore_entries(template_id: str) -> list[str]:
|
|
18
|
+
"""
|
|
19
|
+
Get stack-specific .gitignore entries.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
template_id: Template identifier
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
List of gitignore patterns
|
|
26
|
+
"""
|
|
27
|
+
# Common entries for all stacks
|
|
28
|
+
common_entries = [
|
|
29
|
+
".session/briefings/",
|
|
30
|
+
".session/history/",
|
|
31
|
+
"coverage/",
|
|
32
|
+
"coverage.json",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
# Node.js/Next.js stacks
|
|
36
|
+
if template_id in ["saas_t3", "dashboard_refine", "fullstack_nextjs"]:
|
|
37
|
+
return common_entries + [
|
|
38
|
+
"node_modules/",
|
|
39
|
+
".next/",
|
|
40
|
+
"out/",
|
|
41
|
+
"build/",
|
|
42
|
+
"dist/",
|
|
43
|
+
"*.tsbuildinfo",
|
|
44
|
+
".env",
|
|
45
|
+
".env.local",
|
|
46
|
+
".env.*.local",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
# Python stacks
|
|
50
|
+
elif template_id == "ml_ai_fastapi":
|
|
51
|
+
return common_entries + [
|
|
52
|
+
"venv/",
|
|
53
|
+
".venv/",
|
|
54
|
+
"*.pyc",
|
|
55
|
+
"__pycache__/",
|
|
56
|
+
"*.py[cod]",
|
|
57
|
+
"*$py.class",
|
|
58
|
+
".pytest_cache/",
|
|
59
|
+
".coverage",
|
|
60
|
+
"htmlcov/",
|
|
61
|
+
".env",
|
|
62
|
+
".env.local",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
else:
|
|
66
|
+
return common_entries
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_os_specific_gitignore_entries() -> list[str]:
|
|
70
|
+
"""
|
|
71
|
+
Get OS-specific .gitignore entries.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of gitignore patterns with comments
|
|
75
|
+
"""
|
|
76
|
+
return [
|
|
77
|
+
"# OS-specific files",
|
|
78
|
+
".DS_Store # macOS",
|
|
79
|
+
".DS_Store? # macOS",
|
|
80
|
+
"._* # macOS resource forks",
|
|
81
|
+
".Spotlight-V100 # macOS",
|
|
82
|
+
".Trashes # macOS",
|
|
83
|
+
"Thumbs.db # Windows",
|
|
84
|
+
"ehthumbs.db # Windows",
|
|
85
|
+
"Desktop.ini # Windows",
|
|
86
|
+
"$RECYCLE.BIN/ # Windows",
|
|
87
|
+
"*~ # Linux backup files",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def update_gitignore(template_id: str, project_root: Path | None = None) -> Path:
|
|
92
|
+
"""
|
|
93
|
+
Add Solokit and stack-specific patterns to .gitignore.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
template_id: Template identifier
|
|
97
|
+
project_root: Project root directory
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Path to .gitignore file
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
FileOperationError: If .gitignore read/write operations fail.
|
|
104
|
+
"""
|
|
105
|
+
if project_root is None:
|
|
106
|
+
project_root = Path.cwd()
|
|
107
|
+
|
|
108
|
+
gitignore = project_root / ".gitignore"
|
|
109
|
+
|
|
110
|
+
# Get entries to add
|
|
111
|
+
stack_entries = get_stack_specific_gitignore_entries(template_id)
|
|
112
|
+
os_entries = get_os_specific_gitignore_entries()
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
existing_content = gitignore.read_text() if gitignore.exists() else ""
|
|
116
|
+
except Exception as e:
|
|
117
|
+
raise FileOperationError(
|
|
118
|
+
operation="read",
|
|
119
|
+
file_path=str(gitignore),
|
|
120
|
+
details=f"Failed to read .gitignore: {str(e)}",
|
|
121
|
+
cause=e,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Determine which entries need to be added
|
|
125
|
+
entries_to_add = []
|
|
126
|
+
for entry in stack_entries:
|
|
127
|
+
if entry not in existing_content:
|
|
128
|
+
entries_to_add.append(entry)
|
|
129
|
+
|
|
130
|
+
# Check which OS patterns need to be added
|
|
131
|
+
# First, extract existing patterns (lines without comments)
|
|
132
|
+
existing_lines = [line.strip() for line in existing_content.split("\n")]
|
|
133
|
+
existing_patterns = set()
|
|
134
|
+
for line in existing_lines:
|
|
135
|
+
# Extract pattern (part before comment if any)
|
|
136
|
+
pattern = line.split("#")[0].strip()
|
|
137
|
+
if pattern:
|
|
138
|
+
# Normalize pattern - remove trailing ? for comparison
|
|
139
|
+
normalized = pattern.rstrip("?")
|
|
140
|
+
existing_patterns.add(normalized)
|
|
141
|
+
|
|
142
|
+
os_patterns_needed = []
|
|
143
|
+
for entry in os_entries:
|
|
144
|
+
if entry.startswith("#"):
|
|
145
|
+
continue # Skip header in first pass
|
|
146
|
+
# Skip comment-only lines in first pass
|
|
147
|
+
pattern = entry.split("#")[0].strip()
|
|
148
|
+
if pattern:
|
|
149
|
+
# Normalize pattern for comparison
|
|
150
|
+
normalized = pattern.rstrip("?")
|
|
151
|
+
if normalized not in existing_patterns:
|
|
152
|
+
os_patterns_needed.append(entry)
|
|
153
|
+
|
|
154
|
+
# If we need to add any OS patterns, include the header
|
|
155
|
+
os_entries_to_add = []
|
|
156
|
+
if os_patterns_needed:
|
|
157
|
+
# Add the section header first
|
|
158
|
+
if "# OS-specific files" not in existing_content:
|
|
159
|
+
os_entries_to_add.append("# OS-specific files")
|
|
160
|
+
# Then add all the patterns
|
|
161
|
+
os_entries_to_add.extend(os_patterns_needed)
|
|
162
|
+
|
|
163
|
+
# Write updates
|
|
164
|
+
if entries_to_add or os_entries_to_add:
|
|
165
|
+
logger.info("Updating .gitignore...")
|
|
166
|
+
try:
|
|
167
|
+
with open(gitignore, "a") as f:
|
|
168
|
+
if existing_content and not existing_content.endswith("\n"):
|
|
169
|
+
f.write("\n")
|
|
170
|
+
|
|
171
|
+
if entries_to_add:
|
|
172
|
+
f.write("\n# Solokit-related patterns\n")
|
|
173
|
+
for entry in entries_to_add:
|
|
174
|
+
f.write(f"{entry}\n")
|
|
175
|
+
|
|
176
|
+
if os_entries_to_add:
|
|
177
|
+
f.write("\n")
|
|
178
|
+
for entry in os_entries_to_add:
|
|
179
|
+
f.write(f"{entry}\n")
|
|
180
|
+
|
|
181
|
+
total_added = len(entries_to_add) + len(
|
|
182
|
+
[e for e in os_entries_to_add if not e.startswith("#")]
|
|
183
|
+
)
|
|
184
|
+
logger.info(f"Added {total_added} entries to .gitignore")
|
|
185
|
+
except Exception as e:
|
|
186
|
+
raise FileOperationError(
|
|
187
|
+
operation="write",
|
|
188
|
+
file_path=str(gitignore),
|
|
189
|
+
details=f"Failed to update .gitignore: {str(e)}",
|
|
190
|
+
cause=e,
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
logger.info(".gitignore already up to date")
|
|
194
|
+
|
|
195
|
+
return gitignore
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Initial Commit Module
|
|
3
|
+
|
|
4
|
+
Creates initial git commit after template initialization.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from solokit.core.command_runner import CommandRunner
|
|
13
|
+
from solokit.core.constants import GIT_STANDARD_TIMEOUT
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def create_commit_message(
|
|
19
|
+
template_name: str,
|
|
20
|
+
tier: str,
|
|
21
|
+
coverage_target: int,
|
|
22
|
+
additional_options: list[str],
|
|
23
|
+
stack_info: dict[str, str],
|
|
24
|
+
) -> str:
|
|
25
|
+
"""
|
|
26
|
+
Create commit message for initial commit.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
template_name: Template display name
|
|
30
|
+
tier: Quality tier
|
|
31
|
+
coverage_target: Coverage target percentage
|
|
32
|
+
additional_options: List of additional options
|
|
33
|
+
stack_info: Stack information dictionary
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Formatted commit message
|
|
37
|
+
"""
|
|
38
|
+
# Format additional options
|
|
39
|
+
options_str = ", ".join(
|
|
40
|
+
opt.replace("_", " ").title() if isinstance(opt, str) else str(opt)
|
|
41
|
+
for opt in additional_options
|
|
42
|
+
)
|
|
43
|
+
if not options_str:
|
|
44
|
+
options_str = "None"
|
|
45
|
+
|
|
46
|
+
# Format stack info
|
|
47
|
+
stack_lines = []
|
|
48
|
+
for key, value in stack_info.items():
|
|
49
|
+
formatted_key = key.replace("_", " ").title()
|
|
50
|
+
stack_lines.append(f"- {formatted_key}: {value}")
|
|
51
|
+
stack_str = "\n".join(stack_lines)
|
|
52
|
+
|
|
53
|
+
# Format tier name
|
|
54
|
+
tier_name = tier.replace("tier-", "Tier ").replace("-", " ").title()
|
|
55
|
+
|
|
56
|
+
message = f"""chore: Initialize project with Solokit template system
|
|
57
|
+
|
|
58
|
+
Template: {template_name}
|
|
59
|
+
Quality Tier: {tier_name}
|
|
60
|
+
Coverage Target: {coverage_target}%
|
|
61
|
+
Additional Options: {options_str}
|
|
62
|
+
|
|
63
|
+
Stack:
|
|
64
|
+
{stack_str}
|
|
65
|
+
|
|
66
|
+
Generated files:
|
|
67
|
+
- Project configuration and structure
|
|
68
|
+
- Quality gate configs ({tier_name})
|
|
69
|
+
- Session tracking infrastructure
|
|
70
|
+
- Documentation templates
|
|
71
|
+
|
|
72
|
+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
73
|
+
|
|
74
|
+
Co-Authored-By: Claude <noreply@anthropic.com>"""
|
|
75
|
+
|
|
76
|
+
return message
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def create_initial_commit(
|
|
80
|
+
template_name: str,
|
|
81
|
+
tier: str,
|
|
82
|
+
coverage_target: int,
|
|
83
|
+
additional_options: list[str],
|
|
84
|
+
stack_info: dict[str, str],
|
|
85
|
+
project_root: Path | None = None,
|
|
86
|
+
) -> bool:
|
|
87
|
+
"""
|
|
88
|
+
Create initial commit after project initialization.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
template_name: Template display name
|
|
92
|
+
tier: Quality tier
|
|
93
|
+
coverage_target: Coverage target percentage
|
|
94
|
+
additional_options: List of additional options
|
|
95
|
+
stack_info: Stack information dictionary
|
|
96
|
+
project_root: Root directory of the project
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
True if initial commit was created or already exists.
|
|
100
|
+
"""
|
|
101
|
+
if project_root is None:
|
|
102
|
+
project_root = Path.cwd()
|
|
103
|
+
|
|
104
|
+
runner = CommandRunner(default_timeout=GIT_STANDARD_TIMEOUT, working_dir=project_root)
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
# Check if repository has any commits by trying to count them
|
|
108
|
+
# This will fail gracefully if no commits exist yet
|
|
109
|
+
result = runner.run(["git", "rev-list", "--count", "--all"], check=False)
|
|
110
|
+
|
|
111
|
+
if result.success and result.stdout.strip() and int(result.stdout.strip()) > 0:
|
|
112
|
+
logger.info("Git repository already has commits, skipping initial commit")
|
|
113
|
+
return True
|
|
114
|
+
|
|
115
|
+
except Exception:
|
|
116
|
+
# If command fails (e.g., no commits yet), continue to create initial commit
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
# Stage all initialized files
|
|
121
|
+
result = runner.run(["git", "add", "-A"], check=True)
|
|
122
|
+
if not result.success:
|
|
123
|
+
logger.warning(f"Git add failed: {result.stderr}")
|
|
124
|
+
logger.warning("You may need to commit manually before starting sessions")
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
# Create commit message
|
|
128
|
+
commit_message = create_commit_message(
|
|
129
|
+
template_name, tier, coverage_target, additional_options, stack_info
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Create initial commit
|
|
133
|
+
result = runner.run(["git", "commit", "-m", commit_message], check=True)
|
|
134
|
+
if not result.success:
|
|
135
|
+
logger.warning(f"Git commit failed: {result.stderr}")
|
|
136
|
+
logger.warning("You may need to commit manually before starting sessions")
|
|
137
|
+
return False
|
|
138
|
+
|
|
139
|
+
logger.info("Created initial commit on main branch")
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
except Exception as e:
|
|
143
|
+
logger.warning(f"Failed to create initial commit: {e}")
|
|
144
|
+
logger.warning("You may need to commit manually before starting sessions")
|
|
145
|
+
return False
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Initial Scans Module
|
|
3
|
+
|
|
4
|
+
Runs initial stack and tree scans to populate .session/tracking/.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from solokit.core.command_runner import CommandRunner
|
|
13
|
+
from solokit.core.constants import GIT_STANDARD_TIMEOUT
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_stack_scan(project_root: Path | None = None) -> bool:
|
|
19
|
+
"""
|
|
20
|
+
Run stack scan to generate stack.txt.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
project_root: Project root directory
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
True if scan succeeded
|
|
27
|
+
"""
|
|
28
|
+
if project_root is None:
|
|
29
|
+
project_root = Path.cwd()
|
|
30
|
+
|
|
31
|
+
# Get Solokit installation directory
|
|
32
|
+
script_dir = Path(__file__).parent.parent / "project"
|
|
33
|
+
stack_script = script_dir / "stack.py"
|
|
34
|
+
|
|
35
|
+
if not stack_script.exists():
|
|
36
|
+
logger.warning(f"Stack script not found: {stack_script}")
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
runner = CommandRunner(default_timeout=GIT_STANDARD_TIMEOUT, working_dir=project_root)
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
result = runner.run(["python", str(stack_script)], check=True)
|
|
43
|
+
if result.success:
|
|
44
|
+
logger.info("Generated stack.txt")
|
|
45
|
+
return True
|
|
46
|
+
else:
|
|
47
|
+
logger.warning("Could not generate stack.txt")
|
|
48
|
+
if result.stderr:
|
|
49
|
+
logger.warning(f"Error: {result.stderr.strip()}")
|
|
50
|
+
return False
|
|
51
|
+
except Exception as e:
|
|
52
|
+
logger.warning(f"Stack generation failed: {e}")
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def run_tree_scan(project_root: Path | None = None) -> bool:
|
|
57
|
+
"""
|
|
58
|
+
Run tree scan to generate tree.txt.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
project_root: Project root directory
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
True if scan succeeded
|
|
65
|
+
"""
|
|
66
|
+
if project_root is None:
|
|
67
|
+
project_root = Path.cwd()
|
|
68
|
+
|
|
69
|
+
# Get Solokit installation directory
|
|
70
|
+
script_dir = Path(__file__).parent.parent / "project"
|
|
71
|
+
tree_script = script_dir / "tree.py"
|
|
72
|
+
|
|
73
|
+
if not tree_script.exists():
|
|
74
|
+
logger.warning(f"Tree script not found: {tree_script}")
|
|
75
|
+
return False
|
|
76
|
+
|
|
77
|
+
runner = CommandRunner(default_timeout=GIT_STANDARD_TIMEOUT, working_dir=project_root)
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
result = runner.run(["python", str(tree_script)], check=True)
|
|
81
|
+
if result.success:
|
|
82
|
+
logger.info("Generated tree.txt")
|
|
83
|
+
return True
|
|
84
|
+
else:
|
|
85
|
+
logger.warning("Could not generate tree.txt")
|
|
86
|
+
if result.stderr:
|
|
87
|
+
logger.warning(f"Error: {result.stderr.strip()}")
|
|
88
|
+
return False
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.warning(f"Tree generation failed: {e}")
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def run_initial_scans(project_root: Path | None = None) -> dict[str, bool]:
|
|
95
|
+
"""
|
|
96
|
+
Run initial stack and tree scans.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
project_root: Project root directory
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Dictionary with scan results: {"stack": bool, "tree": bool}
|
|
103
|
+
"""
|
|
104
|
+
logger.info("Generating project context...")
|
|
105
|
+
|
|
106
|
+
stack_success = run_stack_scan(project_root)
|
|
107
|
+
tree_success = run_tree_scan(project_root)
|
|
108
|
+
|
|
109
|
+
return {"stack": stack_success, "tree": tree_success}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Template-Based Init Orchestrator
|
|
3
|
+
|
|
4
|
+
Main orchestration logic for template-based project initialization.
|
|
5
|
+
Implements the complete 18-step initialization flow.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Literal, Optional, cast
|
|
13
|
+
|
|
14
|
+
from solokit.init.claude_commands_installer import install_claude_commands
|
|
15
|
+
from solokit.init.dependency_installer import install_dependencies
|
|
16
|
+
from solokit.init.docs_structure import create_docs_structure
|
|
17
|
+
from solokit.init.env_generator import generate_env_files
|
|
18
|
+
from solokit.init.environment_validator import validate_environment
|
|
19
|
+
from solokit.init.git_hooks_installer import install_git_hooks
|
|
20
|
+
from solokit.init.git_setup import check_blank_project_or_exit, check_or_init_git
|
|
21
|
+
from solokit.init.gitignore_updater import update_gitignore
|
|
22
|
+
from solokit.init.initial_commit import create_initial_commit
|
|
23
|
+
from solokit.init.initial_scans import run_initial_scans
|
|
24
|
+
from solokit.init.readme_generator import generate_readme
|
|
25
|
+
from solokit.init.session_structure import create_session_directories, initialize_tracking_files
|
|
26
|
+
from solokit.init.template_installer import get_template_info, install_template
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def run_template_based_init(
|
|
32
|
+
template_id: str,
|
|
33
|
+
tier: str,
|
|
34
|
+
coverage_target: int,
|
|
35
|
+
additional_options: list[str] | None = None,
|
|
36
|
+
project_root: Path | None = None,
|
|
37
|
+
) -> int:
|
|
38
|
+
"""
|
|
39
|
+
Run complete template-based initialization with 18-step flow.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
template_id: Template identifier (e.g., "saas_t3")
|
|
43
|
+
tier: Quality tier (e.g., "tier-2-standard")
|
|
44
|
+
coverage_target: Test coverage target percentage (60, 80, 90)
|
|
45
|
+
additional_options: List of additional options (e.g., ["ci_cd", "docker"])
|
|
46
|
+
project_root: Project root directory (defaults to current directory)
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
0 on success, non-zero on failure
|
|
50
|
+
|
|
51
|
+
Raises:
|
|
52
|
+
Various exceptions from individual init modules on critical failures
|
|
53
|
+
"""
|
|
54
|
+
if additional_options is None:
|
|
55
|
+
additional_options = []
|
|
56
|
+
|
|
57
|
+
if project_root is None:
|
|
58
|
+
project_root = Path.cwd()
|
|
59
|
+
|
|
60
|
+
logger.info("🚀 Initializing Session-Driven Development with Template System...\n")
|
|
61
|
+
|
|
62
|
+
# =========================================================================
|
|
63
|
+
# PHASE 1: PRE-FLIGHT CHECKS & VALIDATION
|
|
64
|
+
# =========================================================================
|
|
65
|
+
|
|
66
|
+
# Step 1-2: Check if already initialized + Check if blank project
|
|
67
|
+
logger.info("Step 1-2: Pre-flight validation...")
|
|
68
|
+
check_blank_project_or_exit(project_root)
|
|
69
|
+
logger.info("✓ Project directory is blank\n")
|
|
70
|
+
|
|
71
|
+
# Step 3: Initialize/verify git repository
|
|
72
|
+
logger.info("Step 3: Git initialization...")
|
|
73
|
+
check_or_init_git(project_root)
|
|
74
|
+
logger.info("")
|
|
75
|
+
|
|
76
|
+
# Step 4: Validate AND auto-update environment
|
|
77
|
+
logger.info(f"Step 4: Environment validation for {template_id}...")
|
|
78
|
+
|
|
79
|
+
# Map template_id to stack_type for environment validation
|
|
80
|
+
template_to_stack_type = {
|
|
81
|
+
"saas_t3": "saas_t3",
|
|
82
|
+
"ml_ai_fastapi": "ml_ai_fastapi",
|
|
83
|
+
"dashboard_refine": "dashboard_refine",
|
|
84
|
+
"fullstack_nextjs": "fullstack_nextjs",
|
|
85
|
+
}
|
|
86
|
+
stack_type = template_to_stack_type.get(template_id)
|
|
87
|
+
|
|
88
|
+
python_binary = None
|
|
89
|
+
if stack_type:
|
|
90
|
+
env_result = validate_environment(
|
|
91
|
+
cast(
|
|
92
|
+
Literal["saas_t3", "ml_ai_fastapi", "dashboard_refine", "fullstack_nextjs"],
|
|
93
|
+
stack_type,
|
|
94
|
+
),
|
|
95
|
+
auto_update=True,
|
|
96
|
+
)
|
|
97
|
+
logger.info(f"✓ Environment validated for {template_id}")
|
|
98
|
+
if env_result.get("node_version"):
|
|
99
|
+
logger.info(f" Node.js: {env_result['node_version']}")
|
|
100
|
+
if env_result.get("python_version"):
|
|
101
|
+
logger.info(f" Python: {env_result['python_version']}")
|
|
102
|
+
python_binary = cast(Optional[str], env_result.get("python_binary"))
|
|
103
|
+
logger.info("")
|
|
104
|
+
|
|
105
|
+
# Get template information
|
|
106
|
+
template_info = get_template_info(template_id)
|
|
107
|
+
|
|
108
|
+
# =========================================================================
|
|
109
|
+
# PHASE 3: INSTALLATION & SETUP (Phase 2 is interactive, done in CLI)
|
|
110
|
+
# =========================================================================
|
|
111
|
+
|
|
112
|
+
# Step 6: Install template files (base + tier + options)
|
|
113
|
+
logger.info("Step 6: Installing template files...")
|
|
114
|
+
install_result = install_template(template_id, tier, additional_options, project_root)
|
|
115
|
+
logger.info(f"✓ Installed {install_result['files_installed']} template files\n")
|
|
116
|
+
|
|
117
|
+
# Step 7: Generate README.md
|
|
118
|
+
logger.info("Step 7: Generating README.md...")
|
|
119
|
+
generate_readme(template_id, tier, coverage_target, additional_options, project_root)
|
|
120
|
+
logger.info("✓ Generated README.md\n")
|
|
121
|
+
|
|
122
|
+
# Step 8: Config files (handled by template installation)
|
|
123
|
+
logger.info("Step 8: Config files installed via template\n")
|
|
124
|
+
|
|
125
|
+
# Step 9: Install dependencies
|
|
126
|
+
logger.info("Step 9: Installing dependencies...")
|
|
127
|
+
logger.info("⏳ This may take several minutes...\n")
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
install_dependencies(
|
|
131
|
+
template_id,
|
|
132
|
+
cast(
|
|
133
|
+
Literal[
|
|
134
|
+
"tier-1-essential",
|
|
135
|
+
"tier-2-standard",
|
|
136
|
+
"tier-3-comprehensive",
|
|
137
|
+
"tier-4-production",
|
|
138
|
+
],
|
|
139
|
+
tier,
|
|
140
|
+
),
|
|
141
|
+
python_binary,
|
|
142
|
+
project_root,
|
|
143
|
+
)
|
|
144
|
+
logger.info("✓ Dependencies installed successfully\n")
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.warning(f"Dependency installation encountered an issue: {e}")
|
|
147
|
+
logger.warning("You can install dependencies manually later\n")
|
|
148
|
+
|
|
149
|
+
# Step 10: Create docs directory structure
|
|
150
|
+
logger.info("Step 10: Creating documentation structure...")
|
|
151
|
+
create_docs_structure(project_root)
|
|
152
|
+
logger.info("✓ Created docs/ structure\n")
|
|
153
|
+
|
|
154
|
+
# Step 11: Starter code (handled by template)
|
|
155
|
+
logger.info("Step 11: Starter code installed via template\n")
|
|
156
|
+
|
|
157
|
+
# Step 12: Smoke tests (handled by template)
|
|
158
|
+
logger.info("Step 12: Smoke tests installed via template\n")
|
|
159
|
+
|
|
160
|
+
# Step 13: Create .env files
|
|
161
|
+
if "env_templates" in additional_options:
|
|
162
|
+
logger.info("Step 13: Generating environment files...")
|
|
163
|
+
generate_env_files(template_id, project_root)
|
|
164
|
+
logger.info("✓ Generated .env.example and .editorconfig\n")
|
|
165
|
+
else:
|
|
166
|
+
logger.info("Step 13: Skipped (environment templates not selected)\n")
|
|
167
|
+
|
|
168
|
+
# Step 14: Create .session structure
|
|
169
|
+
logger.info("Step 14: Creating .session structure...")
|
|
170
|
+
create_session_directories(project_root)
|
|
171
|
+
logger.info("✓ Created .session/ directories\n")
|
|
172
|
+
|
|
173
|
+
# Step 15: Initialize tracking files
|
|
174
|
+
logger.info("Step 15: Initializing tracking files...")
|
|
175
|
+
initialize_tracking_files(tier, coverage_target, project_root)
|
|
176
|
+
logger.info("✓ Initialized tracking files with tier-specific config\n")
|
|
177
|
+
|
|
178
|
+
# Step 16: Run initial scans (stack.txt, tree.txt)
|
|
179
|
+
logger.info("Step 16: Running initial scans...")
|
|
180
|
+
scan_results = run_initial_scans(project_root)
|
|
181
|
+
if scan_results["stack"]:
|
|
182
|
+
logger.info("✓ Generated stack.txt")
|
|
183
|
+
if scan_results["tree"]:
|
|
184
|
+
logger.info("✓ Generated tree.txt")
|
|
185
|
+
logger.info("")
|
|
186
|
+
|
|
187
|
+
# Step 17: Install git hooks
|
|
188
|
+
logger.info("Step 17: Installing git hooks...")
|
|
189
|
+
install_git_hooks(project_root)
|
|
190
|
+
logger.info("✓ Installed git hooks\n")
|
|
191
|
+
|
|
192
|
+
# Step 17.5: Install Claude Code slash commands
|
|
193
|
+
logger.info("Step 17.5: Installing Claude Code slash commands...")
|
|
194
|
+
try:
|
|
195
|
+
installed_commands = install_claude_commands(project_root)
|
|
196
|
+
logger.info(f"✓ Installed {len(installed_commands)} slash commands to .claude/commands/\n")
|
|
197
|
+
except Exception as e:
|
|
198
|
+
logger.warning(f"Claude commands installation failed: {e}")
|
|
199
|
+
logger.warning("Slash commands may not be available. You can install them manually.\n")
|
|
200
|
+
|
|
201
|
+
# Step 18: Update .gitignore
|
|
202
|
+
logger.info("Step 18: Updating .gitignore...")
|
|
203
|
+
update_gitignore(template_id, project_root)
|
|
204
|
+
logger.info("✓ Updated .gitignore\n")
|
|
205
|
+
|
|
206
|
+
# Step 19: Create initial commit
|
|
207
|
+
logger.info("Step 19: Creating initial commit...")
|
|
208
|
+
commit_success = create_initial_commit(
|
|
209
|
+
template_name=template_info["display_name"],
|
|
210
|
+
tier=tier,
|
|
211
|
+
coverage_target=coverage_target,
|
|
212
|
+
additional_options=additional_options,
|
|
213
|
+
stack_info=template_info["stack"],
|
|
214
|
+
project_root=project_root,
|
|
215
|
+
)
|
|
216
|
+
if commit_success:
|
|
217
|
+
logger.info("✓ Created initial commit\n")
|
|
218
|
+
else:
|
|
219
|
+
logger.warning("Initial commit failed (you can commit manually later)\n")
|
|
220
|
+
|
|
221
|
+
# =========================================================================
|
|
222
|
+
# SUCCESS SUMMARY
|
|
223
|
+
# =========================================================================
|
|
224
|
+
|
|
225
|
+
logger.info("=" * 70)
|
|
226
|
+
logger.info("✅ Solokit Template Initialization Complete!")
|
|
227
|
+
logger.info("=" * 70)
|
|
228
|
+
logger.info("")
|
|
229
|
+
logger.info(f"📦 Template: {template_info['display_name']}")
|
|
230
|
+
logger.info(f"🎯 Quality Tier: {tier}")
|
|
231
|
+
logger.info(f"📊 Coverage Target: {coverage_target}%")
|
|
232
|
+
logger.info("")
|
|
233
|
+
logger.info("✓ Project structure created")
|
|
234
|
+
logger.info("✓ Dependencies installed")
|
|
235
|
+
logger.info("✓ Quality gates configured")
|
|
236
|
+
logger.info("✓ Documentation structure created")
|
|
237
|
+
logger.info("✓ Session tracking initialized")
|
|
238
|
+
logger.info("✓ Git repository configured")
|
|
239
|
+
logger.info("")
|
|
240
|
+
logger.info("🚀 Next Steps:")
|
|
241
|
+
logger.info(" 1. Review README.md for getting started guide")
|
|
242
|
+
logger.info(" 2. Create your first work item: /sk:work-new")
|
|
243
|
+
logger.info(" 3. Start working: /sk:start")
|
|
244
|
+
logger.info("")
|
|
245
|
+
|
|
246
|
+
return 0
|