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,182 @@
1
+ """Migration: Workspace-per-WP model with dependency tracking (0.11.0)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from importlib.resources import files
7
+ from pathlib import Path
8
+ from typing import Dict, List, Optional, Tuple
9
+
10
+ from specify_cli.template.manager import get_local_repo_root
11
+
12
+ from ..registry import MigrationRegistry
13
+ from .base import BaseMigration, MigrationResult
14
+
15
+ MIGRATION_ID = "0.11.0_workspace_per_wp"
16
+ MIGRATION_VERSION = "0.11.0"
17
+ MIGRATION_DESCRIPTION = "Workspace-per-WP model with dependency tracking"
18
+
19
+ MISSION_NAME = "software-dev"
20
+ TEMPLATE_FILES = ("specify.md", "plan.md", "tasks.md", "implement.md")
21
+
22
+
23
+ def detect_legacy_worktrees(project_root: Path) -> List[Path]:
24
+ """Find legacy worktrees (pre-0.11.0)."""
25
+ worktrees_dir = project_root / ".worktrees"
26
+ if not worktrees_dir.exists():
27
+ return []
28
+
29
+ legacy_worktrees: List[Path] = []
30
+ for item in sorted(worktrees_dir.iterdir()):
31
+ if not item.is_dir():
32
+ continue
33
+
34
+ name = item.name
35
+ has_feature_pattern = re.match(r"^\d{3}-", name)
36
+ has_wp_suffix = re.search(r"-WP\d{2}$", name)
37
+
38
+ if has_feature_pattern and not has_wp_suffix:
39
+ legacy_worktrees.append(item)
40
+
41
+ return legacy_worktrees
42
+
43
+
44
+ def validate_upgrade(project_root: Path) -> Tuple[bool, List[str]]:
45
+ """Validate project is ready for 0.11.0 upgrade."""
46
+ legacy_worktrees = detect_legacy_worktrees(project_root)
47
+ if not legacy_worktrees:
48
+ return True, []
49
+
50
+ errors = [
51
+ "Cannot upgrade to 0.11.0 - legacy worktrees detected:",
52
+ "",
53
+ ]
54
+ for worktree in legacy_worktrees:
55
+ errors.append(f" - {worktree.name}")
56
+
57
+ errors.extend(
58
+ [
59
+ "",
60
+ "Action required before upgrade:",
61
+ " 1. Complete features: spec-kitty merge <feature>",
62
+ " 2. OR delete worktrees: git worktree remove .worktrees/<feature>",
63
+ "",
64
+ "Use: spec-kitty list-legacy-features to see all legacy worktrees",
65
+ ]
66
+ )
67
+ return False, errors
68
+
69
+
70
+ def _load_template_sources(base) -> Optional[Dict[str, str]]:
71
+ contents: Dict[str, str] = {}
72
+ for name in TEMPLATE_FILES:
73
+ resource = base.joinpath(name)
74
+ if not resource.exists():
75
+ return None
76
+ contents[name] = resource.read_text(encoding="utf-8")
77
+ return contents
78
+
79
+
80
+ def _resolve_template_sources() -> Optional[Dict[str, str]]:
81
+ local_repo = get_local_repo_root()
82
+ if local_repo:
83
+ candidates = [
84
+ local_repo / "src" / "specify_cli" / "missions" / MISSION_NAME / "command-templates", # 011: New location
85
+ local_repo / ".kittify" / "missions" / MISSION_NAME / "command-templates", # Legacy (pre-011)
86
+ ]
87
+ for candidate in candidates:
88
+ if candidate.exists():
89
+ contents = _load_template_sources(candidate)
90
+ if contents:
91
+ return contents
92
+
93
+ # 011: Templates packaged in src/specify_cli/missions/
94
+ data_root = files("specify_cli")
95
+ candidate = data_root.joinpath("missions", MISSION_NAME, "command-templates")
96
+ if candidate.exists():
97
+ contents = _load_template_sources(candidate)
98
+ if contents:
99
+ return contents
100
+
101
+ return None
102
+
103
+
104
+ def update_template_sources(project_root: Path, dry_run: bool = False) -> Tuple[List[str], List[str]]:
105
+ """Update mission command templates with workspace-per-WP workflow text."""
106
+ changes: List[str] = []
107
+ errors: List[str] = []
108
+
109
+ templates_dir = project_root / ".kittify" / "missions" / MISSION_NAME / "command-templates"
110
+ if not templates_dir.exists():
111
+ errors.append(f"Missing mission templates at {templates_dir}")
112
+ return changes, errors
113
+
114
+ source_templates = _resolve_template_sources()
115
+ if not source_templates:
116
+ errors.append("Unable to locate packaged mission templates for update")
117
+ return changes, errors
118
+
119
+ updated = 0
120
+ for name, content in source_templates.items():
121
+ dest_path = templates_dir / name
122
+ current = dest_path.read_text(encoding="utf-8") if dest_path.exists() else None
123
+ if current == content:
124
+ continue
125
+
126
+ if dry_run:
127
+ changes.append(f"Would update {dest_path}")
128
+ else:
129
+ dest_path.write_text(content, encoding="utf-8")
130
+ changes.append(f"Updated {dest_path}")
131
+ updated += 1
132
+
133
+ if updated == 0:
134
+ changes.append("Templates already up to date")
135
+
136
+ return changes, errors
137
+
138
+
139
+ @MigrationRegistry.register
140
+ class WorkspacePerWPMigration(BaseMigration):
141
+ """Upgrade templates for workspace-per-WP model with dependency tracking."""
142
+
143
+ migration_id = MIGRATION_ID
144
+ description = MIGRATION_DESCRIPTION
145
+ target_version = MIGRATION_VERSION
146
+
147
+ def detect(self, project_path: Path) -> bool:
148
+ """Detect if mission templates need workspace-per-WP updates."""
149
+ templates_dir = project_path / ".kittify" / "missions" / MISSION_NAME / "command-templates"
150
+ if not templates_dir.exists():
151
+ return False
152
+
153
+ source_templates = _resolve_template_sources()
154
+ if not source_templates:
155
+ return False
156
+
157
+ for name, content in source_templates.items():
158
+ dest_path = templates_dir / name
159
+ if not dest_path.exists():
160
+ return True
161
+ if dest_path.read_text(encoding="utf-8") != content:
162
+ return True
163
+
164
+ return False
165
+
166
+ def can_apply(self, project_path: Path) -> tuple[bool, str]:
167
+ """Block upgrade when legacy worktrees exist."""
168
+ is_valid, errors = validate_upgrade(project_path)
169
+ if not is_valid:
170
+ return False, "\n".join(errors)
171
+ return True, ""
172
+
173
+ def apply(self, project_path: Path, dry_run: bool = False) -> MigrationResult:
174
+ """Apply the workspace-per-WP migration."""
175
+ changes, errors = update_template_sources(project_path, dry_run=dry_run)
176
+ success = len(errors) == 0
177
+ return MigrationResult(
178
+ success=success,
179
+ changes_made=changes,
180
+ errors=errors,
181
+ warnings=[],
182
+ )
@@ -0,0 +1,173 @@
1
+ """Migration: Update workflow templates with end-of-output instructions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ from pathlib import Path
7
+ from typing import List
8
+
9
+ from ..registry import MigrationRegistry
10
+ from .base import BaseMigration, MigrationResult
11
+ from .m_0_9_1_complete_lane_migration import get_agent_dirs_for_project
12
+
13
+
14
+ @MigrationRegistry.register
15
+ class ImprovedWorkflowTemplatesMigration(BaseMigration):
16
+ """Update implement and review templates with improved agent guidance.
17
+
18
+ This migration addresses workflow command state corruption issues by:
19
+ 1. Warning agents about long output (1000+ lines)
20
+ 2. Instructing agents to scroll to bottom for completion commands
21
+ 3. Emphasizing that Python scripts handle all file updates automatically
22
+ 4. Removing manual file editing requirements from instructions
23
+
24
+ The workflow.py commands now repeat completion instructions at the END
25
+ of output, after the long WP prompt content.
26
+ """
27
+
28
+ migration_id = "0.11.1_improved_workflow_templates"
29
+ description = "Update workflow templates with end-of-output instructions"
30
+ target_version = "0.11.1"
31
+
32
+ def detect(self, project_path: Path) -> bool:
33
+ """Check if slash commands need updating with improved guidance."""
34
+ # Check if any agent directory has the old templates (without scroll warning)
35
+ agent_dirs = get_agent_dirs_for_project(project_path)
36
+
37
+ for agent_root, subdir in agent_dirs:
38
+ agent_dir = project_path / agent_root / subdir
39
+
40
+ if not agent_dir.exists():
41
+ continue
42
+
43
+ # Check implement.md for new structure
44
+ implement_file = agent_dir / "spec-kitty.implement.md"
45
+ if implement_file.exists():
46
+ content = implement_file.read_text(encoding="utf-8")
47
+ # New template has warning about scrolling to bottom
48
+ if "scroll to the BOTTOM" not in content.lower():
49
+ return True
50
+
51
+ # Check review.md for new structure
52
+ review_file = agent_dir / "spec-kitty.review.md"
53
+ if review_file.exists():
54
+ content = review_file.read_text(encoding="utf-8")
55
+ # New template has warning about scrolling to bottom
56
+ if "scroll to the BOTTOM" not in content.lower():
57
+ return True
58
+
59
+ return False
60
+
61
+ def can_apply(self, project_path: Path) -> tuple[bool, str]:
62
+ """Check if we can apply this migration."""
63
+ kittify_dir = project_path / ".kittify"
64
+ if not kittify_dir.exists():
65
+ return False, "No .kittify directory (not a spec-kitty project)"
66
+
67
+ return True, ""
68
+
69
+ def apply(self, project_path: Path, dry_run: bool = False) -> MigrationResult:
70
+ """Update implement and review slash commands with improved templates."""
71
+ changes: List[str] = []
72
+ warnings: List[str] = []
73
+ errors: List[str] = []
74
+
75
+ missions_dir = project_path / ".kittify" / "missions"
76
+ software_dev_templates = missions_dir / "software-dev" / "command-templates"
77
+
78
+ # Copy updated mission templates from package first (if available)
79
+ try:
80
+ import specify_cli
81
+ except ImportError as exc:
82
+ errors.append(f"Failed to import specify_cli: {exc}")
83
+ return MigrationResult(
84
+ success=False,
85
+ changes_made=changes,
86
+ errors=errors,
87
+ warnings=warnings,
88
+ )
89
+
90
+ pkg_root = Path(specify_cli.__file__).parent
91
+ pkg_templates = pkg_root / "missions" / "software-dev" / "command-templates"
92
+ if not pkg_templates.exists():
93
+ pkg_templates = pkg_root / ".kittify" / "missions" / "software-dev" / "command-templates"
94
+
95
+ if pkg_templates.exists():
96
+ if not dry_run:
97
+ software_dev_templates.mkdir(parents=True, exist_ok=True)
98
+ for template_name in ("implement.md", "review.md"):
99
+ src = pkg_templates / template_name
100
+ if not src.exists():
101
+ warnings.append(f"Package template missing: {template_name}")
102
+ continue
103
+ if dry_run:
104
+ changes.append(f"Would update mission template: software-dev/{template_name}")
105
+ else:
106
+ try:
107
+ shutil.copy2(src, software_dev_templates / template_name)
108
+ changes.append(f"Updated mission template: software-dev/{template_name}")
109
+ except OSError as e:
110
+ warnings.append(f"Failed to copy mission template {template_name}: {e}")
111
+ else:
112
+ warnings.append(
113
+ "Mission templates not found in package. "
114
+ "Slash commands may already be updated or require manual repair."
115
+ )
116
+
117
+ # Update implement.md and review.md in configured agent directories only
118
+ templates_to_update = ["implement.md", "review.md"]
119
+ total_updated = 0
120
+
121
+ # Get agent dirs respecting user's config
122
+ agent_dirs_to_process = get_agent_dirs_for_project(project_path)
123
+
124
+ for agent_root, subdir in agent_dirs_to_process:
125
+ agent_dir = project_path / agent_root / subdir
126
+
127
+ # Skip if directory doesn't exist (respect user deletions)
128
+ if not agent_dir.exists():
129
+ continue
130
+
131
+ updated_count = 0
132
+ for template_name in templates_to_update:
133
+ source_template = software_dev_templates / template_name
134
+ if not source_template.exists():
135
+ continue
136
+
137
+ dest_filename = f"spec-kitty.{template_name}"
138
+ dest_path = agent_dir / dest_filename
139
+
140
+ if dry_run:
141
+ changes.append(f"Would update {agent_root}: {dest_filename}")
142
+ else:
143
+ try:
144
+ dest_path.write_text(
145
+ source_template.read_text(encoding="utf-8"),
146
+ encoding="utf-8",
147
+ )
148
+ updated_count += 1
149
+ except OSError as e:
150
+ warnings.append(f"Failed to update {agent_root}/{dest_filename}: {e}")
151
+
152
+ if updated_count > 0:
153
+ agent_name = agent_root.strip(".")
154
+ changes.append(f"Updated {updated_count} templates for {agent_name}")
155
+ total_updated += updated_count
156
+
157
+ if total_updated > 0:
158
+ changes.append(f"Total: Updated {total_updated} slash command templates across all agents")
159
+ changes.append("Templates now warn agents to scroll to bottom of long output")
160
+ changes.append("Templates emphasize automated file updates (no manual editing)")
161
+ changes.append("Prevents state corruption from incomplete workflows")
162
+ elif not changes:
163
+ warnings.append(
164
+ "No templates were updated (already updated or mission templates missing)"
165
+ )
166
+
167
+ success = len(errors) == 0
168
+ return MigrationResult(
169
+ success=success,
170
+ changes_made=changes,
171
+ errors=errors,
172
+ warnings=warnings,
173
+ )
@@ -0,0 +1,160 @@
1
+ """Migration: Update /spec-kitty.implement slash command across all agents.
2
+
3
+ This migration fixes a critical bug where the /spec-kitty.implement slash command
4
+ was severely outdated after the 0.11.0 workspace-per-WP migration.
5
+
6
+ Issue: The slash command only documented step 1 (display prompt via workflow command)
7
+ but did NOT tell agents to run step 2 (create worktree via implement command).
8
+
9
+ This caused agents to see the prompt but never create the workspace, resulting in
10
+ "no such file or directory" errors when trying to cd to .worktrees/.
11
+
12
+ Fix: Copy the correct implement.md template from packaged missions to all 12
13
+ agent directories.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import shutil
19
+ from pathlib import Path
20
+ from typing import List, Tuple
21
+
22
+ try:
23
+ from importlib.resources import files
24
+ except ImportError:
25
+ from importlib_resources import files # type: ignore
26
+
27
+ from ..registry import MigrationRegistry
28
+ from .base import BaseMigration, MigrationResult
29
+ from .m_0_9_1_complete_lane_migration import get_agent_dirs_for_project
30
+
31
+
32
+ @MigrationRegistry.register
33
+ class UpdateImplementSlashCommandMigration(BaseMigration):
34
+ """Update /spec-kitty.implement slash command to show 2-step workflow.
35
+
36
+ The 0.11.0 migration updated mission templates but did NOT update agent
37
+ slash commands. This migration copies the correct implement.md template
38
+ from packaged missions to all agent directories.
39
+ """
40
+
41
+ migration_id = "0.11.1_update_implement_slash_command"
42
+ description = "Update /spec-kitty.implement slash command to show 2-step workflow"
43
+ target_version = "0.11.1"
44
+
45
+ MISSION_NAME = "software-dev"
46
+ TEMPLATE_FILE = "implement.md"
47
+ SLASH_COMMAND_FILE = "spec-kitty.implement.md"
48
+
49
+ def detect(self, project_path: Path) -> bool:
50
+ """Check if any agent has outdated implement slash command."""
51
+ # Check for old single-step pattern that's missing the critical step 2
52
+ old_pattern = "spec-kitty agent workflow implement $ARGUMENTS"
53
+
54
+ agent_dirs = get_agent_dirs_for_project(project_path)
55
+ for agent_dir, subdir in agent_dirs:
56
+ slash_cmd = project_path / agent_dir / subdir / self.SLASH_COMMAND_FILE
57
+ if slash_cmd.exists():
58
+ content = slash_cmd.read_text(encoding="utf-8")
59
+ # If it has the old single-command pattern and NOT the two-step section
60
+ if old_pattern in content and "CRITICAL: This is a TWO-STEP Command" not in content:
61
+ return True
62
+ # If it's missing step 2 entirely
63
+ if "spec-kitty implement WP##" not in content:
64
+ return True
65
+
66
+ return False
67
+
68
+ def can_apply(self, project_path: Path) -> tuple[bool, str]:
69
+ """Check if we can read the template from packaged missions."""
70
+ # Try to load from packaged data
71
+ try:
72
+ data_root = files("specify_cli")
73
+ template_path = data_root.joinpath(
74
+ "missions", self.MISSION_NAME, "command-templates", self.TEMPLATE_FILE
75
+ )
76
+ if template_path.exists():
77
+ return True, ""
78
+ except Exception as e:
79
+ return False, f"Cannot access packaged missions: {e}"
80
+
81
+ return False, "Template not found in packaged missions"
82
+
83
+ def apply(self, project_path: Path, dry_run: bool = False) -> MigrationResult:
84
+ """Update implement slash command across all agent directories."""
85
+ changes: List[str] = []
86
+ warnings: List[str] = []
87
+ errors: List[str] = []
88
+
89
+ # Load template from packaged missions
90
+ try:
91
+ data_root = files("specify_cli")
92
+ template_path = data_root.joinpath(
93
+ "missions", self.MISSION_NAME, "command-templates", self.TEMPLATE_FILE
94
+ )
95
+
96
+ if not template_path.exists():
97
+ errors.append("Template not found in packaged missions")
98
+ return MigrationResult(
99
+ success=False,
100
+ changes_made=changes,
101
+ errors=errors,
102
+ warnings=warnings,
103
+ )
104
+
105
+ template_content = template_path.read_text(encoding="utf-8")
106
+ except Exception as e:
107
+ errors.append(f"Failed to read template: {e}")
108
+ return MigrationResult(
109
+ success=False,
110
+ changes_made=changes,
111
+ errors=errors,
112
+ warnings=warnings,
113
+ )
114
+
115
+ # Update configured agent directories
116
+ agents_updated = 0
117
+ agent_dirs = get_agent_dirs_for_project(project_path)
118
+ for agent_dir, subdir in agent_dirs:
119
+ agent_path = project_path / agent_dir / subdir
120
+ slash_cmd = agent_path / self.SLASH_COMMAND_FILE
121
+
122
+ # Skip if agent directory doesn't exist
123
+ if not agent_path.exists():
124
+ continue
125
+
126
+ # Check if command needs updating
127
+ needs_update = False
128
+ if slash_cmd.exists():
129
+ current_content = slash_cmd.read_text(encoding="utf-8")
130
+ if current_content != template_content:
131
+ needs_update = True
132
+ else:
133
+ needs_update = True
134
+
135
+ if needs_update:
136
+ if dry_run:
137
+ changes.append(f"Would update: {agent_dir}/{subdir}/{self.SLASH_COMMAND_FILE}")
138
+ else:
139
+ try:
140
+ slash_cmd.write_text(template_content, encoding="utf-8")
141
+ changes.append(f"Updated: {agent_dir}/{subdir}/{self.SLASH_COMMAND_FILE}")
142
+ agents_updated += 1
143
+ except Exception as e:
144
+ errors.append(f"Failed to update {agent_dir}/{subdir}: {e}")
145
+
146
+ if agents_updated > 0:
147
+ if dry_run:
148
+ changes.append(f"Would update {agents_updated} agent directories")
149
+ else:
150
+ changes.append(f"Updated {agents_updated} agent directories")
151
+ else:
152
+ changes.append("No agent directories needed updates")
153
+
154
+ success = len(errors) == 0
155
+ return MigrationResult(
156
+ success=success,
157
+ changes_made=changes,
158
+ errors=errors,
159
+ warnings=warnings,
160
+ )
@@ -0,0 +1,173 @@
1
+ """Migration: Update workflow templates with end-of-output instructions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ from pathlib import Path
7
+ from typing import List
8
+
9
+ from ..registry import MigrationRegistry
10
+ from .base import BaseMigration, MigrationResult
11
+ from .m_0_9_1_complete_lane_migration import get_agent_dirs_for_project
12
+
13
+
14
+ @MigrationRegistry.register
15
+ class ImprovedWorkflowTemplatesMigration(BaseMigration):
16
+ """Update implement and review templates with improved agent guidance.
17
+
18
+ This migration addresses workflow command state corruption issues by:
19
+ 1. Warning agents about long output (1000+ lines)
20
+ 2. Instructing agents to scroll to bottom for completion commands
21
+ 3. Emphasizing that Python scripts handle all file updates automatically
22
+ 4. Removing manual file editing requirements from instructions
23
+
24
+ The workflow.py commands now repeat completion instructions at the END
25
+ of output, after the long WP prompt content.
26
+ """
27
+
28
+ migration_id = "0.11.2_improved_workflow_templates"
29
+ description = "Update workflow templates with end-of-output instructions and --agent requirement"
30
+ target_version = "0.11.2"
31
+
32
+ def detect(self, project_path: Path) -> bool:
33
+ """Check if slash commands need updating with improved guidance."""
34
+ # Check if any agent directory has the old templates (without scroll warning)
35
+ agent_dirs = get_agent_dirs_for_project(project_path)
36
+
37
+ for agent_root, subdir in agent_dirs:
38
+ agent_dir = project_path / agent_root / subdir
39
+
40
+ if not agent_dir.exists():
41
+ continue
42
+
43
+ # Check implement.md for new structure
44
+ implement_file = agent_dir / "spec-kitty.implement.md"
45
+ if implement_file.exists():
46
+ content = implement_file.read_text(encoding="utf-8")
47
+ # New template has warning about scrolling to bottom
48
+ if "scroll to the BOTTOM" not in content.lower():
49
+ return True
50
+
51
+ # Check review.md for new structure
52
+ review_file = agent_dir / "spec-kitty.review.md"
53
+ if review_file.exists():
54
+ content = review_file.read_text(encoding="utf-8")
55
+ # New template has warning about scrolling to bottom
56
+ if "scroll to the BOTTOM" not in content.lower():
57
+ return True
58
+
59
+ return False
60
+
61
+ def can_apply(self, project_path: Path) -> tuple[bool, str]:
62
+ """Check if we can apply this migration."""
63
+ kittify_dir = project_path / ".kittify"
64
+ if not kittify_dir.exists():
65
+ return False, "No .kittify directory (not a spec-kitty project)"
66
+
67
+ return True, ""
68
+
69
+ def apply(self, project_path: Path, dry_run: bool = False) -> MigrationResult:
70
+ """Update implement and review slash commands with improved templates."""
71
+ changes: List[str] = []
72
+ warnings: List[str] = []
73
+ errors: List[str] = []
74
+
75
+ missions_dir = project_path / ".kittify" / "missions"
76
+ software_dev_templates = missions_dir / "software-dev" / "command-templates"
77
+
78
+ # Copy updated mission templates from package first (if available)
79
+ try:
80
+ import specify_cli
81
+ except ImportError as exc:
82
+ errors.append(f"Failed to import specify_cli: {exc}")
83
+ return MigrationResult(
84
+ success=False,
85
+ changes_made=changes,
86
+ errors=errors,
87
+ warnings=warnings,
88
+ )
89
+
90
+ pkg_root = Path(specify_cli.__file__).parent
91
+ pkg_templates = pkg_root / "missions" / "software-dev" / "command-templates"
92
+ if not pkg_templates.exists():
93
+ pkg_templates = pkg_root / ".kittify" / "missions" / "software-dev" / "command-templates"
94
+
95
+ if pkg_templates.exists():
96
+ if not dry_run:
97
+ software_dev_templates.mkdir(parents=True, exist_ok=True)
98
+ for template_name in ("implement.md", "review.md"):
99
+ src = pkg_templates / template_name
100
+ if not src.exists():
101
+ warnings.append(f"Package template missing: {template_name}")
102
+ continue
103
+ if dry_run:
104
+ changes.append(f"Would update mission template: software-dev/{template_name}")
105
+ else:
106
+ try:
107
+ shutil.copy2(src, software_dev_templates / template_name)
108
+ changes.append(f"Updated mission template: software-dev/{template_name}")
109
+ except OSError as e:
110
+ warnings.append(f"Failed to copy mission template {template_name}: {e}")
111
+ else:
112
+ warnings.append(
113
+ "Mission templates not found in package. "
114
+ "Slash commands may already be updated or require manual repair."
115
+ )
116
+
117
+ # Update implement.md and review.md in configured agent directories only
118
+ templates_to_update = ["implement.md", "review.md"]
119
+ total_updated = 0
120
+
121
+ # Get agent dirs respecting user's config
122
+ agent_dirs_to_process = get_agent_dirs_for_project(project_path)
123
+
124
+ for agent_root, subdir in agent_dirs_to_process:
125
+ agent_dir = project_path / agent_root / subdir
126
+
127
+ # Skip if directory doesn't exist (respect user deletions)
128
+ if not agent_dir.exists():
129
+ continue
130
+
131
+ updated_count = 0
132
+ for template_name in templates_to_update:
133
+ source_template = software_dev_templates / template_name
134
+ if not source_template.exists():
135
+ continue
136
+
137
+ dest_filename = f"spec-kitty.{template_name}"
138
+ dest_path = agent_dir / dest_filename
139
+
140
+ if dry_run:
141
+ changes.append(f"Would update {agent_root}: {dest_filename}")
142
+ else:
143
+ try:
144
+ dest_path.write_text(
145
+ source_template.read_text(encoding="utf-8"),
146
+ encoding="utf-8",
147
+ )
148
+ updated_count += 1
149
+ except OSError as e:
150
+ warnings.append(f"Failed to update {agent_root}/{dest_filename}: {e}")
151
+
152
+ if updated_count > 0:
153
+ agent_name = agent_root.strip(".")
154
+ changes.append(f"Updated {updated_count} templates for {agent_name}")
155
+ total_updated += updated_count
156
+
157
+ if total_updated > 0:
158
+ changes.append(f"Total: Updated {total_updated} slash command templates across all agents")
159
+ changes.append("Templates now warn agents to scroll to bottom of long output")
160
+ changes.append("Templates emphasize automated file updates (no manual editing)")
161
+ changes.append("Prevents state corruption from incomplete workflows")
162
+ elif not changes:
163
+ warnings.append(
164
+ "No templates were updated (already updated or mission templates missing)"
165
+ )
166
+
167
+ success = len(errors) == 0
168
+ return MigrationResult(
169
+ success=success,
170
+ changes_made=changes,
171
+ errors=errors,
172
+ warnings=warnings,
173
+ )