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,98 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Console reporter for quality gate results.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from solokit.quality.reporters.base import Reporter
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ConsoleReporter(Reporter):
|
|
14
|
+
"""Generates human-readable console reports."""
|
|
15
|
+
|
|
16
|
+
def generate(self, aggregated_results: dict[str, Any]) -> str:
|
|
17
|
+
"""Generate a console-friendly report.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
aggregated_results: Aggregated results from ResultAggregator
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Formatted console report
|
|
24
|
+
"""
|
|
25
|
+
report = []
|
|
26
|
+
report.append("=" * 60)
|
|
27
|
+
report.append("QUALITY GATE RESULTS")
|
|
28
|
+
report.append("=" * 60)
|
|
29
|
+
|
|
30
|
+
# Overall summary
|
|
31
|
+
if aggregated_results["overall_passed"]:
|
|
32
|
+
report.append("\n✓ ALL CHECKS PASSED")
|
|
33
|
+
else:
|
|
34
|
+
report.append("\n✗ SOME CHECKS FAILED")
|
|
35
|
+
|
|
36
|
+
report.append(f"\nTotal Checks: {aggregated_results['total_checks']}")
|
|
37
|
+
report.append(f"Passed: {aggregated_results['passed_checks']}")
|
|
38
|
+
report.append(f"Failed: {aggregated_results['failed_checks']}")
|
|
39
|
+
report.append(f"Skipped: {aggregated_results['skipped_checks']}")
|
|
40
|
+
report.append(f"Execution Time: {aggregated_results['total_execution_time']:.2f}s")
|
|
41
|
+
|
|
42
|
+
# Individual checker results
|
|
43
|
+
report.append("\n" + "-" * 60)
|
|
44
|
+
report.append("INDIVIDUAL CHECKER RESULTS")
|
|
45
|
+
report.append("-" * 60)
|
|
46
|
+
|
|
47
|
+
for checker_name, result in aggregated_results["by_checker"].items():
|
|
48
|
+
status = result["status"]
|
|
49
|
+
if status == "passed":
|
|
50
|
+
status_symbol = "✓"
|
|
51
|
+
elif status == "skipped":
|
|
52
|
+
status_symbol = "⊘"
|
|
53
|
+
else:
|
|
54
|
+
status_symbol = "✗"
|
|
55
|
+
|
|
56
|
+
report.append(f"\n{status_symbol} {checker_name.upper()}: {status.upper()}")
|
|
57
|
+
|
|
58
|
+
# Add execution time
|
|
59
|
+
if result.get("execution_time", 0) > 0:
|
|
60
|
+
report.append(f" Execution time: {result['execution_time']:.2f}s")
|
|
61
|
+
|
|
62
|
+
# Show errors
|
|
63
|
+
if result.get("errors"):
|
|
64
|
+
report.append(" Errors:")
|
|
65
|
+
for error in result["errors"][:5]: # Limit to first 5
|
|
66
|
+
if isinstance(error, dict):
|
|
67
|
+
error_msg = error.get("message", str(error))
|
|
68
|
+
else:
|
|
69
|
+
error_msg = str(error)
|
|
70
|
+
report.append(f" - {error_msg}")
|
|
71
|
+
if len(result["errors"]) > 5:
|
|
72
|
+
report.append(f" ... and {len(result['errors']) - 5} more")
|
|
73
|
+
|
|
74
|
+
# Show warnings
|
|
75
|
+
if result.get("warnings"):
|
|
76
|
+
report.append(" Warnings:")
|
|
77
|
+
for warning in result["warnings"][:3]: # Limit to first 3
|
|
78
|
+
if isinstance(warning, dict):
|
|
79
|
+
warning_msg = warning.get("message", str(warning))
|
|
80
|
+
else:
|
|
81
|
+
warning_msg = str(warning)
|
|
82
|
+
report.append(f" - {warning_msg}")
|
|
83
|
+
if len(result["warnings"]) > 3:
|
|
84
|
+
report.append(f" ... and {len(result['warnings']) - 3} more")
|
|
85
|
+
|
|
86
|
+
# Show key info
|
|
87
|
+
if result.get("info"):
|
|
88
|
+
info = result["info"]
|
|
89
|
+
# Show coverage if present
|
|
90
|
+
if "coverage" in info:
|
|
91
|
+
report.append(f" Coverage: {info['coverage']}%")
|
|
92
|
+
# Show reason for skipped
|
|
93
|
+
if "reason" in info and status == "skipped":
|
|
94
|
+
report.append(f" Reason: {info['reason']}")
|
|
95
|
+
|
|
96
|
+
report.append("\n" + "=" * 60)
|
|
97
|
+
|
|
98
|
+
return "\n".join(report)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
JSON reporter for quality gate results.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from solokit.quality.reporters.base import Reporter
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class JSONReporter(Reporter):
|
|
15
|
+
"""Generates JSON-formatted reports."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, indent: int = 2):
|
|
18
|
+
"""Initialize the JSON reporter.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
indent: Number of spaces for JSON indentation (default: 2)
|
|
22
|
+
"""
|
|
23
|
+
self.indent = indent
|
|
24
|
+
|
|
25
|
+
def generate(self, aggregated_results: dict[str, Any]) -> str:
|
|
26
|
+
"""Generate a JSON report.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
aggregated_results: Aggregated results from ResultAggregator
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
JSON-formatted report string
|
|
33
|
+
"""
|
|
34
|
+
return json.dumps(aggregated_results, indent=self.indent)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Result aggregation for quality gates.
|
|
4
|
+
|
|
5
|
+
Combines results from multiple checkers into a comprehensive report.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from solokit.quality.checkers.base import CheckResult
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ResultAggregator:
|
|
16
|
+
"""Aggregates results from multiple quality checkers."""
|
|
17
|
+
|
|
18
|
+
def aggregate(self, results: list[CheckResult]) -> dict[str, Any]:
|
|
19
|
+
"""Aggregate multiple check results into a summary.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
results: List of CheckResult objects from various checkers
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Dictionary containing aggregated results with:
|
|
26
|
+
- overall_passed: Whether all checks passed
|
|
27
|
+
- total_checks: Number of checks run
|
|
28
|
+
- passed_checks: Number of checks that passed
|
|
29
|
+
- failed_checks: Number of checks that failed
|
|
30
|
+
- skipped_checks: Number of checks that were skipped
|
|
31
|
+
- by_checker: Results organized by checker name
|
|
32
|
+
- failed_checkers: List of checker names that failed
|
|
33
|
+
"""
|
|
34
|
+
aggregated: dict[str, Any] = {
|
|
35
|
+
"overall_passed": True,
|
|
36
|
+
"total_checks": len(results),
|
|
37
|
+
"passed_checks": 0,
|
|
38
|
+
"failed_checks": 0,
|
|
39
|
+
"skipped_checks": 0,
|
|
40
|
+
"by_checker": {},
|
|
41
|
+
"failed_checkers": [],
|
|
42
|
+
"total_execution_time": 0.0,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for result in results:
|
|
46
|
+
# Add to by_checker mapping
|
|
47
|
+
aggregated["by_checker"][result.checker_name] = {
|
|
48
|
+
"passed": result.passed,
|
|
49
|
+
"status": result.status,
|
|
50
|
+
"errors": result.errors,
|
|
51
|
+
"warnings": result.warnings,
|
|
52
|
+
"info": result.info,
|
|
53
|
+
"execution_time": result.execution_time,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Update counters
|
|
57
|
+
if result.status == "skipped":
|
|
58
|
+
aggregated["skipped_checks"] += 1
|
|
59
|
+
elif result.passed:
|
|
60
|
+
aggregated["passed_checks"] += 1
|
|
61
|
+
else:
|
|
62
|
+
aggregated["failed_checks"] += 1
|
|
63
|
+
aggregated["overall_passed"] = False
|
|
64
|
+
aggregated["failed_checkers"].append(result.checker_name)
|
|
65
|
+
|
|
66
|
+
# Add execution time
|
|
67
|
+
aggregated["total_execution_time"] += result.execution_time
|
|
68
|
+
|
|
69
|
+
return aggregated
|
|
70
|
+
|
|
71
|
+
def get_summary_text(self, aggregated: dict[str, Any]) -> str:
|
|
72
|
+
"""Generate a text summary of aggregated results.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
aggregated: Aggregated results dictionary
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Human-readable summary string
|
|
79
|
+
"""
|
|
80
|
+
total = aggregated["total_checks"]
|
|
81
|
+
passed = aggregated["passed_checks"]
|
|
82
|
+
failed = aggregated["failed_checks"]
|
|
83
|
+
skipped = aggregated["skipped_checks"]
|
|
84
|
+
exec_time = aggregated["total_execution_time"]
|
|
85
|
+
|
|
86
|
+
summary = []
|
|
87
|
+
summary.append(f"Total Checks: {total}")
|
|
88
|
+
summary.append(f"Passed: {passed}")
|
|
89
|
+
summary.append(f"Failed: {failed}")
|
|
90
|
+
summary.append(f"Skipped: {skipped}")
|
|
91
|
+
summary.append(f"Execution Time: {exec_time:.2f}s")
|
|
92
|
+
|
|
93
|
+
if aggregated["overall_passed"]:
|
|
94
|
+
summary.append("\n✓ All quality checks passed")
|
|
95
|
+
else:
|
|
96
|
+
summary.append(f"\n✗ Quality checks failed: {', '.join(aggregated['failed_checkers'])}")
|
|
97
|
+
|
|
98
|
+
return "\n".join(summary)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Session management for Solokit workflow."""
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Session briefing package.
|
|
4
|
+
|
|
5
|
+
This package provides modular components for generating comprehensive session briefings.
|
|
6
|
+
The package is organized into focused, single-responsibility modules.
|
|
7
|
+
|
|
8
|
+
Public API exports maintain backward compatibility with the original briefing.py module.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from solokit.core.logging_config import get_logger
|
|
18
|
+
|
|
19
|
+
from .documentation_loader import DocumentationLoader
|
|
20
|
+
from .formatter import BriefingFormatter
|
|
21
|
+
from .git_context import GitContext
|
|
22
|
+
from .learning_loader import LearningLoader
|
|
23
|
+
from .milestone_builder import MilestoneBuilder
|
|
24
|
+
from .orchestrator import SessionBriefing
|
|
25
|
+
from .stack_detector import StackDetector
|
|
26
|
+
from .tree_generator import TreeGenerator
|
|
27
|
+
from .work_item_loader import WorkItemLoader
|
|
28
|
+
|
|
29
|
+
# Package-level logger for backward compatibility
|
|
30
|
+
logger = get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
# Get the parent module (solokit.session)
|
|
33
|
+
_parent_module_path = Path(__file__).parent.parent
|
|
34
|
+
if str(_parent_module_path) not in sys.path:
|
|
35
|
+
sys.path.insert(0, str(_parent_module_path))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Import main from the briefing.py module (not package)
|
|
39
|
+
# This is a bit tricky since briefing is now a package, but main() is in briefing.py
|
|
40
|
+
# We need to import the actual module file, not the package
|
|
41
|
+
def main() -> int:
|
|
42
|
+
"""Main entry point - delegates to briefing.py main()."""
|
|
43
|
+
# Import the briefing module file (not the package) using importlib
|
|
44
|
+
import importlib.util
|
|
45
|
+
import sys
|
|
46
|
+
from pathlib import Path
|
|
47
|
+
|
|
48
|
+
# Get the path to briefing.py (the module file, not the package)
|
|
49
|
+
module_path = Path(__file__).parent.parent / "briefing.py"
|
|
50
|
+
|
|
51
|
+
# Load the module directly from the file
|
|
52
|
+
spec = importlib.util.spec_from_file_location("solokit.session._briefing_module", module_path)
|
|
53
|
+
if spec is None or spec.loader is None:
|
|
54
|
+
raise ImportError(f"Could not load briefing module from {module_path}")
|
|
55
|
+
briefing_module = importlib.util.module_from_spec(spec)
|
|
56
|
+
sys.modules["solokit.session._briefing_module"] = briefing_module
|
|
57
|
+
spec.loader.exec_module(briefing_module)
|
|
58
|
+
|
|
59
|
+
# Call the main function from the loaded module
|
|
60
|
+
return briefing_module.main() # type: ignore[no-any-return]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Export commonly used functions for backward compatibility
|
|
64
|
+
# These maintain the original module-level function API
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
# Classes
|
|
68
|
+
"SessionBriefing",
|
|
69
|
+
"WorkItemLoader",
|
|
70
|
+
"LearningLoader",
|
|
71
|
+
"DocumentationLoader",
|
|
72
|
+
"StackDetector",
|
|
73
|
+
"TreeGenerator",
|
|
74
|
+
"GitContext",
|
|
75
|
+
"MilestoneBuilder",
|
|
76
|
+
"BriefingFormatter",
|
|
77
|
+
# Functions (for backward compatibility with old code that imports functions)
|
|
78
|
+
"load_work_items",
|
|
79
|
+
"load_learnings",
|
|
80
|
+
"get_next_work_item",
|
|
81
|
+
"get_relevant_learnings",
|
|
82
|
+
"load_milestone_context",
|
|
83
|
+
"load_project_docs",
|
|
84
|
+
"load_current_stack",
|
|
85
|
+
"load_current_tree",
|
|
86
|
+
"load_work_item_spec",
|
|
87
|
+
"shift_heading_levels",
|
|
88
|
+
"extract_section",
|
|
89
|
+
"generate_previous_work_section",
|
|
90
|
+
"extract_keywords",
|
|
91
|
+
"calculate_days_ago",
|
|
92
|
+
"validate_environment",
|
|
93
|
+
"check_git_status",
|
|
94
|
+
"generate_briefing",
|
|
95
|
+
"check_command_exists",
|
|
96
|
+
"generate_integration_test_briefing",
|
|
97
|
+
"generate_deployment_briefing",
|
|
98
|
+
"determine_git_branch_final_status",
|
|
99
|
+
"finalize_previous_work_item_git_status",
|
|
100
|
+
"main", # Add main to exports
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Backward compatibility: Module-level function wrappers
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def load_work_items() -> dict[str, Any]:
|
|
108
|
+
"""Load work items from tracking file (backward compatibility wrapper)."""
|
|
109
|
+
from pathlib import Path
|
|
110
|
+
|
|
111
|
+
work_items_file = Path(".session/tracking/work_items.json")
|
|
112
|
+
logger.debug("Loading work items from: %s", work_items_file)
|
|
113
|
+
|
|
114
|
+
loader = WorkItemLoader()
|
|
115
|
+
return loader.load_work_items()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def load_learnings() -> dict[str, Any]:
|
|
119
|
+
"""Load learnings from tracking file (backward compatibility wrapper)."""
|
|
120
|
+
loader = LearningLoader()
|
|
121
|
+
return loader.load_learnings()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_next_work_item(work_items_data: dict) -> tuple[str | None, dict | None]:
|
|
125
|
+
"""Find next available work item (backward compatibility wrapper)."""
|
|
126
|
+
loader = WorkItemLoader()
|
|
127
|
+
return loader.get_next_work_item(work_items_data)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def get_relevant_learnings(
|
|
131
|
+
learnings_data: dict, work_item: dict, spec_content: str = ""
|
|
132
|
+
) -> list[dict]:
|
|
133
|
+
"""Get relevant learnings (backward compatibility wrapper)."""
|
|
134
|
+
loader = LearningLoader()
|
|
135
|
+
return loader.get_relevant_learnings(learnings_data, work_item, spec_content)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def load_milestone_context(work_item: dict) -> dict | None:
|
|
139
|
+
"""Load milestone context (backward compatibility wrapper)."""
|
|
140
|
+
builder = MilestoneBuilder()
|
|
141
|
+
return builder.load_milestone_context(work_item)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def load_project_docs() -> dict[str, str]:
|
|
145
|
+
"""Load project documentation (backward compatibility wrapper)."""
|
|
146
|
+
loader = DocumentationLoader()
|
|
147
|
+
return loader.load_project_docs()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def load_current_stack() -> str:
|
|
151
|
+
"""Load current technology stack (backward compatibility wrapper)."""
|
|
152
|
+
detector = StackDetector()
|
|
153
|
+
return detector.load_current_stack()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def load_current_tree() -> str:
|
|
157
|
+
"""Load current project structure (backward compatibility wrapper)."""
|
|
158
|
+
generator = TreeGenerator()
|
|
159
|
+
return generator.load_current_tree()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def load_work_item_spec(work_item: str | dict[str, Any]) -> str:
|
|
163
|
+
"""Load work item specification file (backward compatibility wrapper)."""
|
|
164
|
+
loader = WorkItemLoader()
|
|
165
|
+
return loader.load_work_item_spec(work_item)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def shift_heading_levels(markdown_content: str, shift: int) -> str:
|
|
169
|
+
"""Shift markdown heading levels (backward compatibility wrapper)."""
|
|
170
|
+
formatter = BriefingFormatter()
|
|
171
|
+
return formatter.shift_heading_levels(markdown_content, shift)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def extract_section(markdown: str, heading: str) -> str:
|
|
175
|
+
"""Extract section from markdown (backward compatibility wrapper)."""
|
|
176
|
+
formatter = BriefingFormatter()
|
|
177
|
+
return formatter.extract_section(markdown, heading)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def generate_previous_work_section(item_id: str, item: dict) -> str:
|
|
181
|
+
"""Generate previous work context (backward compatibility wrapper)."""
|
|
182
|
+
formatter = BriefingFormatter()
|
|
183
|
+
return formatter.generate_previous_work_section(item_id, item)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def extract_keywords(text: str) -> set[str]:
|
|
187
|
+
"""Extract meaningful keywords from text (backward compatibility wrapper)."""
|
|
188
|
+
loader = LearningLoader()
|
|
189
|
+
return loader._extract_keywords(text)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def calculate_days_ago(timestamp: str) -> int:
|
|
193
|
+
"""Calculate days since timestamp (backward compatibility wrapper)."""
|
|
194
|
+
loader = LearningLoader()
|
|
195
|
+
return loader._calculate_days_ago(timestamp)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def validate_environment() -> list[str]:
|
|
199
|
+
"""Validate development environment (backward compatibility wrapper)."""
|
|
200
|
+
formatter = BriefingFormatter()
|
|
201
|
+
return formatter.validate_environment()
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def check_git_status() -> dict[str, Any]:
|
|
205
|
+
"""Check git status for session start (backward compatibility wrapper)."""
|
|
206
|
+
context = GitContext()
|
|
207
|
+
return context.check_git_status()
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def generate_briefing(item_id: str, item: dict, learnings_data: dict) -> str:
|
|
211
|
+
"""Generate comprehensive markdown briefing (backward compatibility wrapper)."""
|
|
212
|
+
briefing = SessionBriefing()
|
|
213
|
+
return briefing.generate_briefing(item_id, item, learnings_data)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def check_command_exists(command: str) -> bool:
|
|
217
|
+
"""Check if a command is available (backward compatibility wrapper)."""
|
|
218
|
+
formatter = BriefingFormatter()
|
|
219
|
+
return formatter.check_command_exists(command)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def generate_integration_test_briefing(work_item: dict) -> str:
|
|
223
|
+
"""Generate integration test briefing (backward compatibility wrapper)."""
|
|
224
|
+
formatter = BriefingFormatter()
|
|
225
|
+
return formatter.generate_integration_test_briefing(work_item)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def generate_deployment_briefing(work_item: dict) -> str:
|
|
229
|
+
"""Generate deployment briefing (backward compatibility wrapper)."""
|
|
230
|
+
formatter = BriefingFormatter()
|
|
231
|
+
return formatter.generate_deployment_briefing(work_item)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def determine_git_branch_final_status(branch_name: str, git_info: dict) -> str:
|
|
235
|
+
"""Determine final git branch status (backward compatibility wrapper)."""
|
|
236
|
+
context = GitContext()
|
|
237
|
+
return context.determine_git_branch_final_status(branch_name, git_info)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def finalize_previous_work_item_git_status(
|
|
241
|
+
work_items_data: dict, current_work_item_id: str
|
|
242
|
+
) -> str | None:
|
|
243
|
+
"""Finalize git status for previous work item (backward compatibility wrapper)."""
|
|
244
|
+
context = GitContext()
|
|
245
|
+
return context.finalize_previous_work_item_git_status(work_items_data, current_work_item_id)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Documentation discovery and loading.
|
|
4
|
+
Part of the briefing module decomposition.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from solokit.core.exceptions import FileOperationError
|
|
12
|
+
from solokit.core.logging_config import get_logger
|
|
13
|
+
|
|
14
|
+
logger = get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DocumentationLoader:
|
|
18
|
+
"""Load project documentation for context."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, project_root: Path | None = None):
|
|
21
|
+
"""Initialize documentation loader.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
project_root: Path to project root (defaults to current directory)
|
|
25
|
+
"""
|
|
26
|
+
self.project_root = project_root or Path.cwd()
|
|
27
|
+
|
|
28
|
+
def load_project_docs(self) -> dict[str, str]:
|
|
29
|
+
"""Load project documentation for context.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Dictionary mapping doc filename to content
|
|
33
|
+
"""
|
|
34
|
+
docs = {}
|
|
35
|
+
|
|
36
|
+
# Look for common doc files
|
|
37
|
+
doc_files = ["docs/vision.md", "docs/prd.md", "docs/architecture.md", "README.md"]
|
|
38
|
+
|
|
39
|
+
for doc_file in doc_files:
|
|
40
|
+
path = self.project_root / doc_file
|
|
41
|
+
if path.exists():
|
|
42
|
+
try:
|
|
43
|
+
docs[path.name] = path.read_text()
|
|
44
|
+
logger.debug("Loaded documentation: %s", doc_file)
|
|
45
|
+
except (OSError, UnicodeDecodeError) as e:
|
|
46
|
+
raise FileOperationError(
|
|
47
|
+
operation="read",
|
|
48
|
+
file_path=str(path),
|
|
49
|
+
details=f"Failed to read documentation file: {e}",
|
|
50
|
+
cause=e,
|
|
51
|
+
) from e
|
|
52
|
+
|
|
53
|
+
return docs
|