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,291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized constants and configuration values for Solokit
|
|
3
|
+
|
|
4
|
+
This module contains all magic numbers, default values, paths, and
|
|
5
|
+
configuration constants used throughout the Solokit codebase.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Final
|
|
10
|
+
|
|
11
|
+
# ============================================================================
|
|
12
|
+
# Directory and Path Constants
|
|
13
|
+
# ============================================================================
|
|
14
|
+
|
|
15
|
+
# Session directory name
|
|
16
|
+
SESSION_DIR_NAME: Final[str] = ".session"
|
|
17
|
+
|
|
18
|
+
# Subdirectories within session directory
|
|
19
|
+
TRACKING_DIR_NAME: Final[str] = "tracking"
|
|
20
|
+
SPECS_DIR_NAME: Final[str] = "specs"
|
|
21
|
+
CONFIG_DIR_NAME: Final[str] = "config"
|
|
22
|
+
LEARNINGS_DIR_NAME: Final[str] = "learnings"
|
|
23
|
+
BRIEFINGS_DIR_NAME: Final[str] = "briefings"
|
|
24
|
+
STATUS_DIR_NAME: Final[str] = "status"
|
|
25
|
+
|
|
26
|
+
# Tracking file names
|
|
27
|
+
WORK_ITEMS_FILE: Final[str] = "work_items.json"
|
|
28
|
+
LEARNINGS_FILE: Final[str] = "learnings.json"
|
|
29
|
+
STATUS_UPDATE_FILE: Final[str] = "status_update.json"
|
|
30
|
+
SESSIONS_FILE: Final[str] = "sessions.json"
|
|
31
|
+
CONFIG_FILE: Final[str] = "config.json"
|
|
32
|
+
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# Git Operation Timeouts (in seconds)
|
|
35
|
+
# ============================================================================
|
|
36
|
+
|
|
37
|
+
# Quick git operations (status, diff, log)
|
|
38
|
+
GIT_QUICK_TIMEOUT: Final[int] = 5
|
|
39
|
+
|
|
40
|
+
# Standard git operations (add, commit)
|
|
41
|
+
GIT_STANDARD_TIMEOUT: Final[int] = 10
|
|
42
|
+
|
|
43
|
+
# Long-running git operations (push, pull, clone)
|
|
44
|
+
GIT_LONG_TIMEOUT: Final[int] = 30
|
|
45
|
+
|
|
46
|
+
# ============================================================================
|
|
47
|
+
# Learning Curator Constants
|
|
48
|
+
# ============================================================================
|
|
49
|
+
|
|
50
|
+
# Maximum age of learnings before archiving (in sessions)
|
|
51
|
+
MAX_LEARNING_AGE_SESSIONS: Final[int] = 50
|
|
52
|
+
|
|
53
|
+
# Auto-curation threshold (number of uncategorized learnings)
|
|
54
|
+
AUTO_CURATE_THRESHOLD: Final[int] = 10
|
|
55
|
+
|
|
56
|
+
# Similarity thresholds for learning deduplication
|
|
57
|
+
JACCARD_SIMILARITY_THRESHOLD: Final[float] = 0.6
|
|
58
|
+
CONTAINMENT_SIMILARITY_THRESHOLD: Final[float] = 0.8
|
|
59
|
+
|
|
60
|
+
# Minimum similarity score for related learnings
|
|
61
|
+
MIN_RELATED_SIMILARITY: Final[float] = 0.3
|
|
62
|
+
|
|
63
|
+
# ============================================================================
|
|
64
|
+
# Session and Briefing Constants
|
|
65
|
+
# ============================================================================
|
|
66
|
+
|
|
67
|
+
# Maximum spec keywords to display
|
|
68
|
+
MAX_SPEC_KEYWORDS: Final[int] = 500
|
|
69
|
+
|
|
70
|
+
# Maximum number of recent learnings to show in briefing
|
|
71
|
+
MAX_RECENT_LEARNINGS: Final[int] = 10
|
|
72
|
+
|
|
73
|
+
# Maximum number of recent commits to show
|
|
74
|
+
MAX_RECENT_COMMITS: Final[int] = 20
|
|
75
|
+
|
|
76
|
+
# Maximum work items to show in status
|
|
77
|
+
MAX_STATUS_WORK_ITEMS: Final[int] = 15
|
|
78
|
+
|
|
79
|
+
# ============================================================================
|
|
80
|
+
# Quality Gate Constants
|
|
81
|
+
# ============================================================================
|
|
82
|
+
|
|
83
|
+
# Minimum test coverage percentage
|
|
84
|
+
MIN_TEST_COVERAGE: Final[float] = 80.0
|
|
85
|
+
|
|
86
|
+
# Maximum cyclomatic complexity per function
|
|
87
|
+
MAX_CYCLOMATIC_COMPLEXITY: Final[int] = 10
|
|
88
|
+
|
|
89
|
+
# Maximum line length
|
|
90
|
+
MAX_LINE_LENGTH: Final[int] = 100
|
|
91
|
+
|
|
92
|
+
# ============================================================================
|
|
93
|
+
# Performance Testing Constants
|
|
94
|
+
# ============================================================================
|
|
95
|
+
|
|
96
|
+
# Default performance regression threshold (1.1 = 10% slower)
|
|
97
|
+
PERFORMANCE_REGRESSION_THRESHOLD: Final[float] = 1.1
|
|
98
|
+
|
|
99
|
+
# Performance test timeout
|
|
100
|
+
PERFORMANCE_TEST_TIMEOUT: Final[int] = 10
|
|
101
|
+
|
|
102
|
+
# Number of warmup runs for performance tests
|
|
103
|
+
PERFORMANCE_WARMUP_RUNS: Final[int] = 3
|
|
104
|
+
|
|
105
|
+
# Number of measurement runs for performance tests
|
|
106
|
+
PERFORMANCE_MEASUREMENT_RUNS: Final[int] = 10
|
|
107
|
+
|
|
108
|
+
# ============================================================================
|
|
109
|
+
# API and HTTP Constants
|
|
110
|
+
# ============================================================================
|
|
111
|
+
|
|
112
|
+
# Default HTTP request timeout
|
|
113
|
+
HTTP_REQUEST_TIMEOUT: Final[int] = 5
|
|
114
|
+
|
|
115
|
+
# API endpoint timeout
|
|
116
|
+
API_ENDPOINT_TIMEOUT: Final[int] = 10
|
|
117
|
+
|
|
118
|
+
# ============================================================================
|
|
119
|
+
# Work Item Constants
|
|
120
|
+
# ============================================================================
|
|
121
|
+
|
|
122
|
+
# Work item types
|
|
123
|
+
WORK_ITEM_TYPES: Final[tuple[str, ...]] = (
|
|
124
|
+
"feature",
|
|
125
|
+
"bug",
|
|
126
|
+
"refactor",
|
|
127
|
+
"security",
|
|
128
|
+
"integration_test",
|
|
129
|
+
"deployment",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Priority levels (in order from highest to lowest)
|
|
133
|
+
PRIORITY_LEVELS: Final[tuple[str, ...]] = (
|
|
134
|
+
"critical",
|
|
135
|
+
"high",
|
|
136
|
+
"medium",
|
|
137
|
+
"low",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Work item statuses
|
|
141
|
+
WORK_ITEM_STATUSES: Final[tuple[str, ...]] = (
|
|
142
|
+
"not_started",
|
|
143
|
+
"in_progress",
|
|
144
|
+
"completed",
|
|
145
|
+
"blocked",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Maximum work item ID length (for slug generation)
|
|
149
|
+
MAX_WORK_ITEM_ID_LENGTH: Final[int] = 40
|
|
150
|
+
|
|
151
|
+
# ============================================================================
|
|
152
|
+
# CLI and User Interface Constants
|
|
153
|
+
# ============================================================================
|
|
154
|
+
|
|
155
|
+
# Minimum arguments for CLI commands
|
|
156
|
+
MIN_CLI_ARGS: Final[int] = 1
|
|
157
|
+
|
|
158
|
+
# Progress bar length
|
|
159
|
+
PROGRESS_BAR_LENGTH: Final[int] = 20
|
|
160
|
+
|
|
161
|
+
# ============================================================================
|
|
162
|
+
# File Size and Limit Constants
|
|
163
|
+
# ============================================================================
|
|
164
|
+
|
|
165
|
+
# Maximum file size for parsing (in bytes) - 10MB
|
|
166
|
+
MAX_FILE_SIZE_BYTES: Final[int] = 10 * 1024 * 1024
|
|
167
|
+
|
|
168
|
+
# Maximum number of files to process in batch
|
|
169
|
+
MAX_BATCH_FILE_COUNT: Final[int] = 100
|
|
170
|
+
|
|
171
|
+
# ============================================================================
|
|
172
|
+
# Subprocess and Process Constants
|
|
173
|
+
# ============================================================================
|
|
174
|
+
|
|
175
|
+
# Default subprocess timeout (for general operations)
|
|
176
|
+
DEFAULT_SUBPROCESS_TIMEOUT: Final[int] = 10
|
|
177
|
+
|
|
178
|
+
# Exit codes
|
|
179
|
+
EXIT_SUCCESS: Final[int] = 0
|
|
180
|
+
EXIT_FAILURE: Final[int] = 1
|
|
181
|
+
|
|
182
|
+
# ============================================================================
|
|
183
|
+
# Quality Gate Timeouts (in seconds)
|
|
184
|
+
# ============================================================================
|
|
185
|
+
|
|
186
|
+
# Quick quality checks (version checks, git operations)
|
|
187
|
+
QUALITY_CHECK_QUICK_TIMEOUT: Final[int] = 5
|
|
188
|
+
|
|
189
|
+
# Standard quality checks (linting, formatting)
|
|
190
|
+
QUALITY_CHECK_STANDARD_TIMEOUT: Final[int] = 30
|
|
191
|
+
|
|
192
|
+
# Long-running quality checks (formatting tools, complex linting)
|
|
193
|
+
QUALITY_CHECK_LONG_TIMEOUT: Final[int] = 60
|
|
194
|
+
|
|
195
|
+
# Very long quality checks (full formatting, security scans)
|
|
196
|
+
QUALITY_CHECK_VERY_LONG_TIMEOUT: Final[int] = 120
|
|
197
|
+
|
|
198
|
+
# Test runner timeout (20 minutes for full test suites)
|
|
199
|
+
TEST_RUNNER_TIMEOUT: Final[int] = 1200
|
|
200
|
+
|
|
201
|
+
# ============================================================================
|
|
202
|
+
# Integration Testing Timeouts (in seconds)
|
|
203
|
+
# ============================================================================
|
|
204
|
+
|
|
205
|
+
# Docker command timeout (ps, version checks)
|
|
206
|
+
DOCKER_COMMAND_TIMEOUT: Final[int] = 5
|
|
207
|
+
|
|
208
|
+
# Docker compose up/down timeout
|
|
209
|
+
DOCKER_COMPOSE_TIMEOUT: Final[int] = 180
|
|
210
|
+
|
|
211
|
+
# Fixture setup timeout
|
|
212
|
+
FIXTURE_SETUP_TIMEOUT: Final[int] = 30
|
|
213
|
+
|
|
214
|
+
# Integration test execution timeout (10 minutes)
|
|
215
|
+
INTEGRATION_TEST_TIMEOUT: Final[int] = 600
|
|
216
|
+
|
|
217
|
+
# Cleanup operation timeout
|
|
218
|
+
CLEANUP_TIMEOUT: Final[int] = 60
|
|
219
|
+
|
|
220
|
+
# ============================================================================
|
|
221
|
+
# Session and Workflow Timeouts (in seconds)
|
|
222
|
+
# ============================================================================
|
|
223
|
+
|
|
224
|
+
# Session status checks
|
|
225
|
+
SESSION_STATUS_TIMEOUT: Final[int] = 5
|
|
226
|
+
|
|
227
|
+
# Session completion operations
|
|
228
|
+
SESSION_COMPLETE_TIMEOUT: Final[int] = 30
|
|
229
|
+
|
|
230
|
+
# Learning extraction timeout
|
|
231
|
+
LEARNING_EXTRACTION_TIMEOUT: Final[int] = 60
|
|
232
|
+
|
|
233
|
+
# Briefing generation timeout
|
|
234
|
+
BRIEFING_GENERATION_TIMEOUT: Final[int] = 30
|
|
235
|
+
|
|
236
|
+
# ============================================================================
|
|
237
|
+
# Project Initialization Timeouts (in seconds)
|
|
238
|
+
# ============================================================================
|
|
239
|
+
|
|
240
|
+
# Stack detection timeout (quick check)
|
|
241
|
+
STACK_DETECTION_TIMEOUT: Final[int] = 2
|
|
242
|
+
|
|
243
|
+
# Tree generation timeout
|
|
244
|
+
TREE_GENERATION_TIMEOUT: Final[int] = 30
|
|
245
|
+
|
|
246
|
+
# Dependency graph generation timeout
|
|
247
|
+
DEPENDENCY_GRAPH_TIMEOUT: Final[int] = 30
|
|
248
|
+
|
|
249
|
+
# ============================================================================
|
|
250
|
+
# Helper Functions
|
|
251
|
+
# ============================================================================
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def get_session_dir(project_root: Path) -> Path:
|
|
255
|
+
"""Get the session directory path for a project"""
|
|
256
|
+
return project_root / SESSION_DIR_NAME
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def get_tracking_dir(project_root: Path) -> Path:
|
|
260
|
+
"""Get the tracking directory path for a project"""
|
|
261
|
+
return get_session_dir(project_root) / TRACKING_DIR_NAME
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def get_specs_dir(project_root: Path) -> Path:
|
|
265
|
+
"""Get the specs directory path for a project"""
|
|
266
|
+
return get_session_dir(project_root) / SPECS_DIR_NAME
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def get_briefings_dir(project_root: Path) -> Path:
|
|
270
|
+
"""Get the briefings directory path for a project"""
|
|
271
|
+
return get_session_dir(project_root) / BRIEFINGS_DIR_NAME
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def get_status_dir(project_root: Path) -> Path:
|
|
275
|
+
"""Get the status directory path for a project"""
|
|
276
|
+
return get_session_dir(project_root) / STATUS_DIR_NAME
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def get_work_items_file(project_root: Path) -> Path:
|
|
280
|
+
"""Get the work items file path"""
|
|
281
|
+
return get_tracking_dir(project_root) / WORK_ITEMS_FILE
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def get_learnings_file(project_root: Path) -> Path:
|
|
285
|
+
"""Get the learnings file path"""
|
|
286
|
+
return get_tracking_dir(project_root) / LEARNINGS_FILE
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def get_config_file(project_root: Path) -> Path:
|
|
290
|
+
"""Get the config file path"""
|
|
291
|
+
return get_session_dir(project_root) / CONFIG_FILE
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Format exceptions for CLI display.
|
|
3
|
+
|
|
4
|
+
Separates presentation concerns from business logic. Business logic raises
|
|
5
|
+
structured exceptions, CLI layer formats them for user display.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from solokit.core.error_formatter import ErrorFormatter
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
# Business logic
|
|
12
|
+
do_something()
|
|
13
|
+
except SolokitError as e:
|
|
14
|
+
ErrorFormatter.print_error(e, verbose=args.verbose)
|
|
15
|
+
sys.exit(e.exit_code)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import sys
|
|
19
|
+
from typing import Any, Optional
|
|
20
|
+
|
|
21
|
+
from solokit.core.exceptions import ErrorCategory, SolokitError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ErrorFormatter:
|
|
25
|
+
"""Format exceptions for CLI output"""
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def format_error(error: Exception, verbose: bool = False) -> str:
|
|
29
|
+
"""
|
|
30
|
+
Format exception for display.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
error: Exception to format
|
|
34
|
+
verbose: Include full context and stack trace
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Formatted error message
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
>>> from solokit.core.exceptions import WorkItemNotFoundError
|
|
41
|
+
>>> error = WorkItemNotFoundError("my_feature")
|
|
42
|
+
>>> print(ErrorFormatter.format_error(error))
|
|
43
|
+
🔍 Work item 'my_feature' not found
|
|
44
|
+
💡 Use 'sk work-list' to see available work items
|
|
45
|
+
"""
|
|
46
|
+
if isinstance(error, SolokitError):
|
|
47
|
+
return ErrorFormatter._format_solokit_error(error, verbose)
|
|
48
|
+
else:
|
|
49
|
+
return ErrorFormatter._format_generic_error(error, verbose)
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def _format_solokit_error(error: SolokitError, verbose: bool) -> str:
|
|
53
|
+
"""Format SolokitError with structured data"""
|
|
54
|
+
lines = []
|
|
55
|
+
|
|
56
|
+
# Error symbol based on category
|
|
57
|
+
symbol = ErrorFormatter._get_error_symbol(error.category)
|
|
58
|
+
lines.append(f"{symbol} {error.message}")
|
|
59
|
+
|
|
60
|
+
# Context (if verbose or critical info)
|
|
61
|
+
if verbose and error.context:
|
|
62
|
+
lines.append("\nContext:")
|
|
63
|
+
for key, value in error.context.items():
|
|
64
|
+
# Format lists and dicts nicely
|
|
65
|
+
if isinstance(value, list):
|
|
66
|
+
lines.append(f" {key}:")
|
|
67
|
+
for item in value[:10]: # Limit to 10 items
|
|
68
|
+
lines.append(f" - {item}")
|
|
69
|
+
if len(value) > 10:
|
|
70
|
+
lines.append(f" ... and {len(value) - 10} more")
|
|
71
|
+
elif isinstance(value, dict):
|
|
72
|
+
lines.append(f" {key}:")
|
|
73
|
+
for k, v in list(value.items())[:10]:
|
|
74
|
+
lines.append(f" {k}: {v}")
|
|
75
|
+
if len(value) > 10:
|
|
76
|
+
lines.append(f" ... and {len(value) - 10} more items")
|
|
77
|
+
else:
|
|
78
|
+
lines.append(f" {key}: {value}")
|
|
79
|
+
|
|
80
|
+
# Remediation (always show if available)
|
|
81
|
+
if error.remediation:
|
|
82
|
+
lines.append(f"\n💡 {error.remediation}")
|
|
83
|
+
|
|
84
|
+
# Error code (if verbose)
|
|
85
|
+
if verbose:
|
|
86
|
+
lines.append(f"\nError Code: {error.code.name} ({error.code.value})")
|
|
87
|
+
lines.append(f"Category: {error.category.value}")
|
|
88
|
+
|
|
89
|
+
# Cause (if present)
|
|
90
|
+
if verbose and error.cause:
|
|
91
|
+
lines.append(f"\nCaused by: {error.cause}")
|
|
92
|
+
|
|
93
|
+
return "\n".join(lines)
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def _format_generic_error(error: Exception, verbose: bool) -> str:
|
|
97
|
+
"""Format generic exception"""
|
|
98
|
+
if verbose:
|
|
99
|
+
import traceback
|
|
100
|
+
|
|
101
|
+
return f"❌ {type(error).__name__}: {error}\n\n{traceback.format_exc()}"
|
|
102
|
+
else:
|
|
103
|
+
return f"❌ {type(error).__name__}: {error}"
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def _get_error_symbol(category: ErrorCategory) -> str:
|
|
107
|
+
"""Get emoji symbol for error category"""
|
|
108
|
+
symbols = {
|
|
109
|
+
ErrorCategory.VALIDATION: "⚠️",
|
|
110
|
+
ErrorCategory.NOT_FOUND: "🔍",
|
|
111
|
+
ErrorCategory.CONFIGURATION: "⚙️",
|
|
112
|
+
ErrorCategory.SYSTEM: "💥",
|
|
113
|
+
ErrorCategory.GIT: "🔀",
|
|
114
|
+
ErrorCategory.DEPENDENCY: "🔗",
|
|
115
|
+
ErrorCategory.SECURITY: "🔒",
|
|
116
|
+
ErrorCategory.TIMEOUT: "⏱️",
|
|
117
|
+
ErrorCategory.ALREADY_EXISTS: "📋",
|
|
118
|
+
ErrorCategory.PERMISSION: "🔐",
|
|
119
|
+
}
|
|
120
|
+
return symbols.get(category, "❌")
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
def print_error(error: Exception, verbose: bool = False, file: Any = None) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Print formatted error to stderr.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
error: Exception to print
|
|
129
|
+
verbose: Include full context
|
|
130
|
+
file: Output stream (default: stderr)
|
|
131
|
+
|
|
132
|
+
Example:
|
|
133
|
+
>>> try:
|
|
134
|
+
... raise ValidationError("Invalid input")
|
|
135
|
+
... except SolokitError as e:
|
|
136
|
+
... ErrorFormatter.print_error(e)
|
|
137
|
+
"""
|
|
138
|
+
import logging
|
|
139
|
+
|
|
140
|
+
if file is None:
|
|
141
|
+
file = sys.stderr
|
|
142
|
+
|
|
143
|
+
formatted = ErrorFormatter.format_error(error, verbose)
|
|
144
|
+
logger = logging.getLogger(__name__)
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
print(formatted, file=file)
|
|
148
|
+
except (ValueError, OSError) as e:
|
|
149
|
+
# Handle closed file (e.g., in tests with capsys)
|
|
150
|
+
logger.warning(f"Could not write to stderr: {e}, trying stdout")
|
|
151
|
+
try:
|
|
152
|
+
print(formatted, file=sys.stdout)
|
|
153
|
+
except (ValueError, OSError) as e2:
|
|
154
|
+
# Both are closed - log the error instead of silently suppressing
|
|
155
|
+
logger.error(f"Could not write error to stderr or stdout: {e2}")
|
|
156
|
+
logger.error(f"Original error message: {formatted}")
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def get_exit_code(error: Exception) -> int:
|
|
160
|
+
"""
|
|
161
|
+
Get appropriate exit code for error.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
error: Exception to get exit code for
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Exit code (0 for success, >0 for errors)
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
>>> from solokit.core.exceptions import ValidationError, ErrorCode
|
|
171
|
+
>>> error = ValidationError("test", code=ErrorCode.INVALID_WORK_ITEM_ID)
|
|
172
|
+
>>> ErrorFormatter.get_exit_code(error)
|
|
173
|
+
2
|
|
174
|
+
"""
|
|
175
|
+
if isinstance(error, SolokitError):
|
|
176
|
+
return error.exit_code
|
|
177
|
+
else:
|
|
178
|
+
return 1 # Generic error
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def format_validation_errors(errors: list[str], header: Optional[str] = None) -> str:
|
|
182
|
+
"""
|
|
183
|
+
Format a list of validation errors for display.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
errors: List of error messages
|
|
187
|
+
header: Optional header to display before errors
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Formatted error message
|
|
191
|
+
|
|
192
|
+
Example:
|
|
193
|
+
>>> errors = ["Missing field 'name'", "Invalid value for 'age'"]
|
|
194
|
+
>>> print(format_validation_errors(errors, "Validation failed"))
|
|
195
|
+
⚠️ Validation failed
|
|
196
|
+
|
|
197
|
+
1. Missing field 'name'
|
|
198
|
+
2. Invalid value for 'age'
|
|
199
|
+
"""
|
|
200
|
+
lines = []
|
|
201
|
+
|
|
202
|
+
if header:
|
|
203
|
+
lines.append(f"⚠️ {header}")
|
|
204
|
+
lines.append("")
|
|
205
|
+
|
|
206
|
+
for i, error in enumerate(errors, 1):
|
|
207
|
+
lines.append(f" {i}. {error}")
|
|
208
|
+
|
|
209
|
+
return "\n".join(lines)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def format_progress_message(current: int, total: int, message: str) -> str:
|
|
213
|
+
"""
|
|
214
|
+
Format a progress message with count.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
current: Current item number
|
|
218
|
+
total: Total number of items
|
|
219
|
+
message: Progress message
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Formatted progress message
|
|
223
|
+
|
|
224
|
+
Example:
|
|
225
|
+
>>> print(format_progress_message(3, 10, "Processing files"))
|
|
226
|
+
[3/10] Processing files...
|
|
227
|
+
"""
|
|
228
|
+
return f"[{current}/{total}] {message}..."
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def format_success_message(message: str) -> str:
|
|
232
|
+
"""
|
|
233
|
+
Format a success message.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
message: Success message
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Formatted success message with checkmark
|
|
240
|
+
|
|
241
|
+
Example:
|
|
242
|
+
>>> print(format_success_message("Work item created"))
|
|
243
|
+
✅ Work item created
|
|
244
|
+
"""
|
|
245
|
+
return f"✅ {message}"
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def format_warning_message(message: str) -> str:
|
|
249
|
+
"""
|
|
250
|
+
Format a warning message.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
message: Warning message
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
Formatted warning message with icon
|
|
257
|
+
|
|
258
|
+
Example:
|
|
259
|
+
>>> print(format_warning_message("Config file not found, using defaults"))
|
|
260
|
+
⚠️ Config file not found, using defaults
|
|
261
|
+
"""
|
|
262
|
+
return f"⚠️ {message}"
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def format_info_message(message: str) -> str:
|
|
266
|
+
"""
|
|
267
|
+
Format an info message.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
message: Info message
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Formatted info message with icon
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
>>> print(format_info_message("Loading configuration"))
|
|
277
|
+
ℹ️ Loading configuration
|
|
278
|
+
"""
|
|
279
|
+
return f"ℹ️ {message}"
|