spec-kitty-cli 0.12.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. spec_kitty_cli-0.12.1.dist-info/METADATA +1767 -0
  2. spec_kitty_cli-0.12.1.dist-info/RECORD +242 -0
  3. spec_kitty_cli-0.12.1.dist-info/WHEEL +4 -0
  4. spec_kitty_cli-0.12.1.dist-info/entry_points.txt +2 -0
  5. spec_kitty_cli-0.12.1.dist-info/licenses/LICENSE +21 -0
  6. specify_cli/__init__.py +171 -0
  7. specify_cli/acceptance.py +627 -0
  8. specify_cli/agent_utils/README.md +157 -0
  9. specify_cli/agent_utils/__init__.py +9 -0
  10. specify_cli/agent_utils/status.py +356 -0
  11. specify_cli/cli/__init__.py +6 -0
  12. specify_cli/cli/commands/__init__.py +46 -0
  13. specify_cli/cli/commands/accept.py +189 -0
  14. specify_cli/cli/commands/agent/__init__.py +22 -0
  15. specify_cli/cli/commands/agent/config.py +382 -0
  16. specify_cli/cli/commands/agent/context.py +191 -0
  17. specify_cli/cli/commands/agent/feature.py +1057 -0
  18. specify_cli/cli/commands/agent/release.py +11 -0
  19. specify_cli/cli/commands/agent/tasks.py +1253 -0
  20. specify_cli/cli/commands/agent/workflow.py +801 -0
  21. specify_cli/cli/commands/context.py +246 -0
  22. specify_cli/cli/commands/dashboard.py +85 -0
  23. specify_cli/cli/commands/implement.py +973 -0
  24. specify_cli/cli/commands/init.py +827 -0
  25. specify_cli/cli/commands/init_help.py +62 -0
  26. specify_cli/cli/commands/merge.py +755 -0
  27. specify_cli/cli/commands/mission.py +240 -0
  28. specify_cli/cli/commands/ops.py +265 -0
  29. specify_cli/cli/commands/orchestrate.py +640 -0
  30. specify_cli/cli/commands/repair.py +175 -0
  31. specify_cli/cli/commands/research.py +165 -0
  32. specify_cli/cli/commands/sync.py +364 -0
  33. specify_cli/cli/commands/upgrade.py +249 -0
  34. specify_cli/cli/commands/validate_encoding.py +186 -0
  35. specify_cli/cli/commands/validate_tasks.py +186 -0
  36. specify_cli/cli/commands/verify.py +310 -0
  37. specify_cli/cli/helpers.py +123 -0
  38. specify_cli/cli/step_tracker.py +91 -0
  39. specify_cli/cli/ui.py +192 -0
  40. specify_cli/core/__init__.py +53 -0
  41. specify_cli/core/agent_context.py +311 -0
  42. specify_cli/core/config.py +96 -0
  43. specify_cli/core/context_validation.py +362 -0
  44. specify_cli/core/dependency_graph.py +351 -0
  45. specify_cli/core/git_ops.py +129 -0
  46. specify_cli/core/multi_parent_merge.py +323 -0
  47. specify_cli/core/paths.py +260 -0
  48. specify_cli/core/project_resolver.py +110 -0
  49. specify_cli/core/stale_detection.py +263 -0
  50. specify_cli/core/tool_checker.py +79 -0
  51. specify_cli/core/utils.py +43 -0
  52. specify_cli/core/vcs/__init__.py +114 -0
  53. specify_cli/core/vcs/detection.py +341 -0
  54. specify_cli/core/vcs/exceptions.py +85 -0
  55. specify_cli/core/vcs/git.py +1304 -0
  56. specify_cli/core/vcs/jujutsu.py +1208 -0
  57. specify_cli/core/vcs/protocol.py +285 -0
  58. specify_cli/core/vcs/types.py +249 -0
  59. specify_cli/core/version_checker.py +261 -0
  60. specify_cli/core/worktree.py +506 -0
  61. specify_cli/dashboard/__init__.py +28 -0
  62. specify_cli/dashboard/diagnostics.py +204 -0
  63. specify_cli/dashboard/handlers/__init__.py +17 -0
  64. specify_cli/dashboard/handlers/api.py +143 -0
  65. specify_cli/dashboard/handlers/base.py +65 -0
  66. specify_cli/dashboard/handlers/features.py +390 -0
  67. specify_cli/dashboard/handlers/router.py +81 -0
  68. specify_cli/dashboard/handlers/static.py +50 -0
  69. specify_cli/dashboard/lifecycle.py +541 -0
  70. specify_cli/dashboard/scanner.py +437 -0
  71. specify_cli/dashboard/server.py +123 -0
  72. specify_cli/dashboard/static/dashboard/dashboard.css +722 -0
  73. specify_cli/dashboard/static/dashboard/dashboard.js +1424 -0
  74. specify_cli/dashboard/static/spec-kitty.png +0 -0
  75. specify_cli/dashboard/templates/__init__.py +36 -0
  76. specify_cli/dashboard/templates/index.html +258 -0
  77. specify_cli/doc_generators.py +621 -0
  78. specify_cli/doc_state.py +408 -0
  79. specify_cli/frontmatter.py +384 -0
  80. specify_cli/gap_analysis.py +915 -0
  81. specify_cli/gitignore_manager.py +300 -0
  82. specify_cli/guards.py +145 -0
  83. specify_cli/legacy_detector.py +83 -0
  84. specify_cli/manifest.py +286 -0
  85. specify_cli/merge/__init__.py +63 -0
  86. specify_cli/merge/executor.py +653 -0
  87. specify_cli/merge/forecast.py +215 -0
  88. specify_cli/merge/ordering.py +126 -0
  89. specify_cli/merge/preflight.py +230 -0
  90. specify_cli/merge/state.py +185 -0
  91. specify_cli/merge/status_resolver.py +354 -0
  92. specify_cli/mission.py +654 -0
  93. specify_cli/missions/documentation/command-templates/implement.md +309 -0
  94. specify_cli/missions/documentation/command-templates/plan.md +275 -0
  95. specify_cli/missions/documentation/command-templates/review.md +344 -0
  96. specify_cli/missions/documentation/command-templates/specify.md +206 -0
  97. specify_cli/missions/documentation/command-templates/tasks.md +189 -0
  98. specify_cli/missions/documentation/mission.yaml +113 -0
  99. specify_cli/missions/documentation/templates/divio/explanation-template.md +192 -0
  100. specify_cli/missions/documentation/templates/divio/howto-template.md +168 -0
  101. specify_cli/missions/documentation/templates/divio/reference-template.md +179 -0
  102. specify_cli/missions/documentation/templates/divio/tutorial-template.md +146 -0
  103. specify_cli/missions/documentation/templates/generators/jsdoc.json.template +18 -0
  104. specify_cli/missions/documentation/templates/generators/sphinx-conf.py.template +36 -0
  105. specify_cli/missions/documentation/templates/plan-template.md +269 -0
  106. specify_cli/missions/documentation/templates/release-template.md +222 -0
  107. specify_cli/missions/documentation/templates/spec-template.md +172 -0
  108. specify_cli/missions/documentation/templates/task-prompt-template.md +140 -0
  109. specify_cli/missions/documentation/templates/tasks-template.md +159 -0
  110. specify_cli/missions/research/command-templates/merge.md +388 -0
  111. specify_cli/missions/research/command-templates/plan.md +125 -0
  112. specify_cli/missions/research/command-templates/review.md +144 -0
  113. specify_cli/missions/research/command-templates/tasks.md +225 -0
  114. specify_cli/missions/research/mission.yaml +115 -0
  115. specify_cli/missions/research/templates/data-model-template.md +33 -0
  116. specify_cli/missions/research/templates/plan-template.md +161 -0
  117. specify_cli/missions/research/templates/research/evidence-log.csv +18 -0
  118. specify_cli/missions/research/templates/research/source-register.csv +18 -0
  119. specify_cli/missions/research/templates/research-template.md +35 -0
  120. specify_cli/missions/research/templates/spec-template.md +64 -0
  121. specify_cli/missions/research/templates/task-prompt-template.md +148 -0
  122. specify_cli/missions/research/templates/tasks-template.md +114 -0
  123. specify_cli/missions/software-dev/command-templates/accept.md +75 -0
  124. specify_cli/missions/software-dev/command-templates/analyze.md +183 -0
  125. specify_cli/missions/software-dev/command-templates/checklist.md +286 -0
  126. specify_cli/missions/software-dev/command-templates/clarify.md +157 -0
  127. specify_cli/missions/software-dev/command-templates/constitution.md +432 -0
  128. specify_cli/missions/software-dev/command-templates/dashboard.md +101 -0
  129. specify_cli/missions/software-dev/command-templates/implement.md +41 -0
  130. specify_cli/missions/software-dev/command-templates/merge.md +383 -0
  131. specify_cli/missions/software-dev/command-templates/plan.md +171 -0
  132. specify_cli/missions/software-dev/command-templates/review.md +32 -0
  133. specify_cli/missions/software-dev/command-templates/specify.md +321 -0
  134. specify_cli/missions/software-dev/command-templates/tasks.md +566 -0
  135. specify_cli/missions/software-dev/mission.yaml +100 -0
  136. specify_cli/missions/software-dev/templates/plan-template.md +132 -0
  137. specify_cli/missions/software-dev/templates/spec-template.md +116 -0
  138. specify_cli/missions/software-dev/templates/task-prompt-template.md +140 -0
  139. specify_cli/missions/software-dev/templates/tasks-template.md +159 -0
  140. specify_cli/orchestrator/__init__.py +75 -0
  141. specify_cli/orchestrator/agent_config.py +224 -0
  142. specify_cli/orchestrator/agents/__init__.py +170 -0
  143. specify_cli/orchestrator/agents/augment.py +112 -0
  144. specify_cli/orchestrator/agents/base.py +243 -0
  145. specify_cli/orchestrator/agents/claude.py +112 -0
  146. specify_cli/orchestrator/agents/codex.py +106 -0
  147. specify_cli/orchestrator/agents/copilot.py +137 -0
  148. specify_cli/orchestrator/agents/cursor.py +139 -0
  149. specify_cli/orchestrator/agents/gemini.py +115 -0
  150. specify_cli/orchestrator/agents/kilocode.py +94 -0
  151. specify_cli/orchestrator/agents/opencode.py +132 -0
  152. specify_cli/orchestrator/agents/qwen.py +96 -0
  153. specify_cli/orchestrator/config.py +455 -0
  154. specify_cli/orchestrator/executor.py +642 -0
  155. specify_cli/orchestrator/integration.py +1230 -0
  156. specify_cli/orchestrator/monitor.py +898 -0
  157. specify_cli/orchestrator/scheduler.py +832 -0
  158. specify_cli/orchestrator/state.py +508 -0
  159. specify_cli/orchestrator/testing/__init__.py +122 -0
  160. specify_cli/orchestrator/testing/availability.py +346 -0
  161. specify_cli/orchestrator/testing/fixtures.py +684 -0
  162. specify_cli/orchestrator/testing/paths.py +218 -0
  163. specify_cli/plan_validation.py +107 -0
  164. specify_cli/scripts/debug-dashboard-scan.py +61 -0
  165. specify_cli/scripts/tasks/acceptance_support.py +695 -0
  166. specify_cli/scripts/tasks/task_helpers.py +506 -0
  167. specify_cli/scripts/tasks/tasks_cli.py +848 -0
  168. specify_cli/scripts/validate_encoding.py +180 -0
  169. specify_cli/task_metadata_validation.py +274 -0
  170. specify_cli/tasks_support.py +447 -0
  171. specify_cli/template/__init__.py +47 -0
  172. specify_cli/template/asset_generator.py +206 -0
  173. specify_cli/template/github_client.py +334 -0
  174. specify_cli/template/manager.py +193 -0
  175. specify_cli/template/renderer.py +99 -0
  176. specify_cli/templates/AGENTS.md +190 -0
  177. specify_cli/templates/POWERSHELL_SYNTAX.md +229 -0
  178. specify_cli/templates/agent-file-template.md +35 -0
  179. specify_cli/templates/checklist-template.md +42 -0
  180. specify_cli/templates/claudeignore-template +58 -0
  181. specify_cli/templates/command-templates/accept.md +141 -0
  182. specify_cli/templates/command-templates/analyze.md +253 -0
  183. specify_cli/templates/command-templates/checklist.md +352 -0
  184. specify_cli/templates/command-templates/clarify.md +224 -0
  185. specify_cli/templates/command-templates/constitution.md +432 -0
  186. specify_cli/templates/command-templates/dashboard.md +175 -0
  187. specify_cli/templates/command-templates/implement.md +190 -0
  188. specify_cli/templates/command-templates/merge.md +374 -0
  189. specify_cli/templates/command-templates/plan.md +171 -0
  190. specify_cli/templates/command-templates/research.md +88 -0
  191. specify_cli/templates/command-templates/review.md +510 -0
  192. specify_cli/templates/command-templates/specify.md +321 -0
  193. specify_cli/templates/command-templates/status.md +92 -0
  194. specify_cli/templates/command-templates/tasks.md +199 -0
  195. specify_cli/templates/git-hooks/pre-commit +22 -0
  196. specify_cli/templates/git-hooks/pre-commit-agent-check +37 -0
  197. specify_cli/templates/git-hooks/pre-commit-encoding-check +142 -0
  198. specify_cli/templates/plan-template.md +108 -0
  199. specify_cli/templates/spec-template.md +118 -0
  200. specify_cli/templates/task-prompt-template.md +165 -0
  201. specify_cli/templates/tasks-template.md +161 -0
  202. specify_cli/templates/vscode-settings.json +13 -0
  203. specify_cli/text_sanitization.py +225 -0
  204. specify_cli/upgrade/__init__.py +18 -0
  205. specify_cli/upgrade/detector.py +239 -0
  206. specify_cli/upgrade/metadata.py +182 -0
  207. specify_cli/upgrade/migrations/__init__.py +65 -0
  208. specify_cli/upgrade/migrations/base.py +80 -0
  209. specify_cli/upgrade/migrations/m_0_10_0_python_only.py +359 -0
  210. specify_cli/upgrade/migrations/m_0_10_12_constitution_cleanup.py +99 -0
  211. specify_cli/upgrade/migrations/m_0_10_14_update_implement_slash_command.py +176 -0
  212. specify_cli/upgrade/migrations/m_0_10_1_populate_slash_commands.py +174 -0
  213. specify_cli/upgrade/migrations/m_0_10_2_update_slash_commands.py +172 -0
  214. specify_cli/upgrade/migrations/m_0_10_6_workflow_simplification.py +174 -0
  215. specify_cli/upgrade/migrations/m_0_10_8_fix_memory_structure.py +252 -0
  216. specify_cli/upgrade/migrations/m_0_10_9_repair_templates.py +168 -0
  217. specify_cli/upgrade/migrations/m_0_11_0_workspace_per_wp.py +182 -0
  218. specify_cli/upgrade/migrations/m_0_11_1_improved_workflow_templates.py +173 -0
  219. specify_cli/upgrade/migrations/m_0_11_1_update_implement_slash_command.py +160 -0
  220. specify_cli/upgrade/migrations/m_0_11_2_improved_workflow_templates.py +173 -0
  221. specify_cli/upgrade/migrations/m_0_11_3_workflow_agent_flag.py +114 -0
  222. specify_cli/upgrade/migrations/m_0_12_0_documentation_mission.py +155 -0
  223. specify_cli/upgrade/migrations/m_0_12_1_remove_kitty_specs_from_gitignore.py +183 -0
  224. specify_cli/upgrade/migrations/m_0_2_0_specify_to_kittify.py +80 -0
  225. specify_cli/upgrade/migrations/m_0_4_8_gitignore_agents.py +118 -0
  226. specify_cli/upgrade/migrations/m_0_5_0_encoding_hooks.py +141 -0
  227. specify_cli/upgrade/migrations/m_0_6_5_commands_rename.py +169 -0
  228. specify_cli/upgrade/migrations/m_0_6_7_ensure_missions.py +228 -0
  229. specify_cli/upgrade/migrations/m_0_7_2_worktree_commands_dedup.py +89 -0
  230. specify_cli/upgrade/migrations/m_0_7_3_update_scripts.py +114 -0
  231. specify_cli/upgrade/migrations/m_0_8_0_remove_active_mission.py +82 -0
  232. specify_cli/upgrade/migrations/m_0_8_0_worktree_agents_symlink.py +148 -0
  233. specify_cli/upgrade/migrations/m_0_9_0_frontmatter_only_lanes.py +346 -0
  234. specify_cli/upgrade/migrations/m_0_9_1_complete_lane_migration.py +656 -0
  235. specify_cli/upgrade/migrations/m_0_9_2_research_mission_templates.py +221 -0
  236. specify_cli/upgrade/registry.py +121 -0
  237. specify_cli/upgrade/runner.py +284 -0
  238. specify_cli/validators/__init__.py +14 -0
  239. specify_cli/validators/paths.py +154 -0
  240. specify_cli/validators/research.py +428 -0
  241. specify_cli/verify_enhanced.py +270 -0
  242. specify_cli/workspace_context.py +224 -0
@@ -0,0 +1,261 @@
1
+ """Version compatibility checking for spec-kitty CLI and projects."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Literal, Optional
7
+
8
+ from packaging.version import Version, InvalidVersion
9
+
10
+ from specify_cli.upgrade.metadata import ProjectMetadata
11
+
12
+
13
+ MismatchType = Literal["cli_newer", "project_newer", "match", "unknown"]
14
+
15
+
16
+ def get_cli_version() -> str:
17
+ """Get the installed spec-kitty-cli version.
18
+
19
+ Returns:
20
+ Version string (e.g., "0.9.0" or "0.5.0-dev")
21
+
22
+ Raises:
23
+ RuntimeError: If test mode is enabled but no version override is set
24
+ """
25
+ import os
26
+
27
+ # Test mode: MUST use override, never fall back to installed version
28
+ # This ensures tests always use source code version, not pip-installed package
29
+ if os.environ.get("SPEC_KITTY_TEST_MODE") == "1":
30
+ override = os.environ.get("SPEC_KITTY_CLI_VERSION")
31
+ if not override:
32
+ raise RuntimeError(
33
+ "SPEC_KITTY_TEST_MODE=1 requires SPEC_KITTY_CLI_VERSION to be set. "
34
+ "This is a bug in the test fixtures. Tests must use the isolated_env "
35
+ "fixture to ensure proper version isolation."
36
+ )
37
+ return override
38
+
39
+ # Production mode: allow override, then try installed, then module __version__
40
+ override_version = os.environ.get("SPEC_KITTY_CLI_VERSION")
41
+ if override_version:
42
+ return override_version
43
+
44
+ try:
45
+ from importlib.metadata import version as get_version
46
+ return get_version("spec-kitty-cli")
47
+ except Exception:
48
+ # Fall back to __version__ from __init__.py
49
+ try:
50
+ from specify_cli import __version__
51
+ return __version__
52
+ except Exception:
53
+ return "unknown"
54
+
55
+
56
+ def get_project_version(project_root: Path) -> Optional[str]:
57
+ """Get the project's spec-kitty version from metadata.
58
+
59
+ Args:
60
+ project_root: Path to project root (parent of .kittify)
61
+
62
+ Returns:
63
+ Version string if metadata exists, None for legacy projects
64
+ """
65
+ kittify_dir = project_root / ".kittify"
66
+ if not kittify_dir.exists():
67
+ return None
68
+
69
+ metadata = ProjectMetadata.load(kittify_dir)
70
+ if metadata is None:
71
+ return None
72
+
73
+ return metadata.version
74
+
75
+
76
+ def compare_versions(cli_version: str, project_version: str) -> tuple[int, MismatchType]:
77
+ """Compare CLI and project versions using semantic versioning.
78
+
79
+ Args:
80
+ cli_version: Installed CLI version
81
+ project_version: Project's spec-kitty version
82
+
83
+ Returns:
84
+ Tuple of (comparison_result, mismatch_type):
85
+ - comparison_result: -1 (CLI older), 0 (equal), 1 (CLI newer)
86
+ - mismatch_type: Type of mismatch or "match"
87
+ """
88
+ # Handle unknown versions
89
+ if cli_version == "unknown" or project_version == "unknown":
90
+ return (0, "unknown")
91
+
92
+ try:
93
+ cli_ver = Version(cli_version)
94
+ proj_ver = Version(project_version)
95
+
96
+ if cli_ver > proj_ver:
97
+ return (1, "cli_newer")
98
+ elif cli_ver < proj_ver:
99
+ return (-1, "project_newer")
100
+ else:
101
+ return (0, "match")
102
+
103
+ except InvalidVersion:
104
+ # If version parsing fails, treat as unknown
105
+ return (0, "unknown")
106
+
107
+
108
+ def format_version_error(
109
+ cli_version: str,
110
+ project_version: str,
111
+ mismatch_type: MismatchType
112
+ ) -> str:
113
+ """Format a user-facing error message for version mismatch.
114
+
115
+ Args:
116
+ cli_version: Installed CLI version
117
+ project_version: Project's spec-kitty version
118
+ mismatch_type: Type of mismatch
119
+
120
+ Returns:
121
+ Formatted error message with resolution instructions
122
+ """
123
+ border = "━" * 80
124
+
125
+ if mismatch_type == "cli_newer":
126
+ # Check if this is the critical 0.8.x -> 0.9.x upgrade
127
+ try:
128
+ from packaging.version import Version
129
+ cli_ver = Version(cli_version)
130
+ proj_ver = Version(project_version)
131
+ is_090_upgrade = cli_ver >= Version("0.9.0") and proj_ver < Version("0.9.0")
132
+ except Exception:
133
+ is_090_upgrade = False
134
+
135
+ if is_090_upgrade:
136
+ return f"""
137
+ {border}
138
+ 🚨 CRITICAL: BREAKING CHANGES - Version Mismatch Detected 🚨
139
+ {border}
140
+
141
+ CLI version: {cli_version} ← NEWER (v0.9.0+ has BREAKING CHANGES)
142
+ Project version: {project_version} ← OLDER (pre-0.9.0 format)
143
+
144
+ ⚠️ YOU CANNOT USE v0.9.0+ CLI WITH PRE-0.9.0 PROJECTS! ⚠️
145
+
146
+ ╔════════════════════════════════════════════════════════════════════════════╗
147
+ ║ 🔴 CRITICAL BREAKING CHANGE IN v0.9.0: LANE SYSTEM REDESIGNED 🔴 ║
148
+ ╚════════════════════════════════════════════════════════════════════════════╝
149
+
150
+ 📂 OLD STRUCTURE (pre-0.9.0):
151
+ kitty-specs/<feature>/tasks/
152
+ ├── planned/WP01.md
153
+ ├── doing/WP02.md
154
+ ├── for_review/WP03.md
155
+ └── done/WP04.md
156
+
157
+ 📂 NEW STRUCTURE (v0.9.0+):
158
+ kitty-specs/<feature>/tasks/
159
+ ├── WP01.md (with "lane: planned" in frontmatter)
160
+ ├── WP02.md (with "lane: doing" in frontmatter)
161
+ ├── WP03.md (with "lane: for_review" in frontmatter)
162
+ └── WP04.md (with "lane: done" in frontmatter)
163
+
164
+ ⚠️ THIS AFFECTS ALL YOUR HISTORICAL WORK IN kitty-specs/ ⚠️
165
+
166
+ 🔧 REQUIRED ACTION - You MUST upgrade your project:
167
+
168
+ spec-kitty upgrade
169
+
170
+ This will:
171
+ ✅ Migrate ALL features from directory-based to frontmatter-only lanes
172
+ ✅ Move all WP files from subdirectories to flat tasks/ directory
173
+ ✅ Add "lane:" field to frontmatter in all WP files
174
+ ✅ Update .kittify/metadata.yaml to v{cli_version}
175
+ ✅ Remove empty lane subdirectories
176
+
177
+ 🛡️ SAFETY: The upgrade is idempotent and safe to run multiple times.
178
+
179
+ ❌ Commands are BLOCKED until you upgrade to prevent data corruption.
180
+
181
+ {border}
182
+ """.strip()
183
+ else:
184
+ return f"""
185
+ {border}
186
+ ❌ ERROR: Version Mismatch Detected
187
+ {border}
188
+
189
+ CLI version: {cli_version}
190
+ Project version: {project_version}
191
+
192
+ Your CLI is NEWER than your project.
193
+
194
+ This means your project templates and scripts are out of date.
195
+ Please upgrade your project to match:
196
+
197
+ spec-kitty upgrade
198
+
199
+ This will update your project templates and configuration
200
+ to match the installed CLI version.
201
+
202
+ {border}
203
+ """.strip()
204
+
205
+ elif mismatch_type == "project_newer":
206
+ return f"""
207
+ {border}
208
+ ❌ ERROR: Version Mismatch Detected
209
+ {border}
210
+
211
+ CLI version: {cli_version}
212
+ Project version: {project_version}
213
+
214
+ Your project is NEWER than your CLI.
215
+
216
+ This project was created or upgraded with a newer version
217
+ of spec-kitty-cli. Please upgrade your CLI:
218
+
219
+ pip install --upgrade spec-kitty-cli
220
+
221
+ After upgrading, run:
222
+
223
+ spec-kitty --version
224
+
225
+ to verify the update.
226
+
227
+ {border}
228
+ """.strip()
229
+
230
+ else:
231
+ return f"Version mismatch: CLI={cli_version}, Project={project_version}"
232
+
233
+
234
+ def should_check_version(command_name: str) -> bool:
235
+ """Determine if version check is required for a command.
236
+
237
+ Args:
238
+ command_name: Name of the command being executed
239
+
240
+ Returns:
241
+ True if version check required, False if should skip
242
+ """
243
+ # Commands that skip version check (they create or fix version issues)
244
+ skip_commands = {
245
+ "init",
246
+ "upgrade",
247
+ "version", # --version flag
248
+ "help", # --help flag
249
+ }
250
+
251
+ return command_name not in skip_commands
252
+
253
+
254
+ __all__ = [
255
+ "get_cli_version",
256
+ "get_project_version",
257
+ "compare_versions",
258
+ "format_version_error",
259
+ "should_check_version",
260
+ "MismatchType",
261
+ ]