lite-kits 0.1.0__py3-none-any.whl → 0.3.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 (48) hide show
  1. lite_kits/__init__.py +61 -9
  2. lite_kits/cli.py +788 -262
  3. lite_kits/core/__init__.py +19 -0
  4. lite_kits/core/banner.py +160 -0
  5. lite_kits/core/conflict_checker.py +115 -0
  6. lite_kits/core/detector.py +140 -0
  7. lite_kits/core/installer.py +322 -0
  8. lite_kits/core/manifest.py +146 -0
  9. lite_kits/core/validator.py +146 -0
  10. lite_kits/kits/README.md +14 -15
  11. lite_kits/kits/dev/README.md +241 -0
  12. lite_kits/kits/dev/commands/.claude/audit.md +143 -0
  13. lite_kits/kits/{git/claude/commands → dev/commands/.claude}/cleanup.md +2 -2
  14. lite_kits/kits/{git/claude/commands → dev/commands/.claude}/commit.md +2 -2
  15. lite_kits/kits/{project/claude/commands → dev/commands/.claude}/orient.md +30 -48
  16. lite_kits/kits/{git/claude/commands → dev/commands/.claude}/pr.md +1 -1
  17. lite_kits/kits/dev/commands/.claude/review.md +202 -0
  18. lite_kits/kits/dev/commands/.claude/stats.md +162 -0
  19. lite_kits/kits/dev/commands/.github/audit.prompt.md +143 -0
  20. lite_kits/kits/{git/github/prompts → dev/commands/.github}/cleanup.prompt.md +2 -2
  21. lite_kits/kits/{git/github/prompts → dev/commands/.github}/commit.prompt.md +2 -2
  22. lite_kits/kits/{project/github/prompts → dev/commands/.github}/orient.prompt.md +34 -48
  23. lite_kits/kits/{git/github/prompts → dev/commands/.github}/pr.prompt.md +1 -1
  24. lite_kits/kits/dev/commands/.github/review.prompt.md +202 -0
  25. lite_kits/kits/dev/commands/.github/stats.prompt.md +163 -0
  26. lite_kits/kits/kits.yaml +497 -0
  27. lite_kits/kits/multiagent/README.md +28 -17
  28. lite_kits/kits/multiagent/{claude/commands → commands/.claude}/sync.md +331 -331
  29. lite_kits/kits/multiagent/{github/prompts → commands/.github}/sync.prompt.md +73 -69
  30. lite_kits/kits/multiagent/memory/git-worktrees-protocol.md +370 -370
  31. lite_kits/kits/multiagent/memory/parallel-work-protocol.md +536 -536
  32. lite_kits/kits/multiagent/memory/pr-workflow-guide.md +275 -281
  33. lite_kits/kits/multiagent/templates/collaboration-structure/README.md +166 -166
  34. lite_kits/kits/multiagent/templates/decision.md +79 -79
  35. lite_kits/kits/multiagent/templates/handoff.md +95 -95
  36. lite_kits/kits/multiagent/templates/session-log.md +68 -68
  37. lite_kits-0.3.1.dist-info/METADATA +259 -0
  38. lite_kits-0.3.1.dist-info/RECORD +41 -0
  39. {lite_kits-0.1.0.dist-info → lite_kits-0.3.1.dist-info}/licenses/LICENSE +21 -21
  40. lite_kits/installer.py +0 -417
  41. lite_kits/kits/git/README.md +0 -374
  42. lite_kits/kits/git/scripts/bash/get-git-context.sh +0 -208
  43. lite_kits/kits/git/scripts/powershell/Get-GitContext.ps1 +0 -242
  44. lite_kits/kits/project/README.md +0 -244
  45. lite_kits-0.1.0.dist-info/METADATA +0 -415
  46. lite_kits-0.1.0.dist-info/RECORD +0 -31
  47. {lite_kits-0.1.0.dist-info → lite_kits-0.3.1.dist-info}/WHEEL +0 -0
  48. {lite_kits-0.1.0.dist-info → lite_kits-0.3.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,322 @@
1
+ """
2
+ Manifest-driven installer for lite-kits.
3
+
4
+ Orchestrates detection, validation, and file operations.
5
+ Delegates to specialized modules for specific tasks.
6
+ """
7
+
8
+ import shutil
9
+ from pathlib import Path
10
+ from typing import Dict, List, Optional
11
+
12
+ from .conflict_checker import ConflictChecker
13
+ from .detector import Detector
14
+ from .manifest import KitManifest
15
+ from .validator import Validator
16
+
17
+
18
+ class Installer:
19
+ """Main installer orchestrator."""
20
+
21
+ def __init__(
22
+ self,
23
+ target_dir: Path,
24
+ kits: Optional[List[str]] = None,
25
+ force: bool = False,
26
+ agent: Optional[str] = None,
27
+ shell: Optional[str] = None,
28
+ ):
29
+ """
30
+ Initialize installer.
31
+
32
+ Args:
33
+ target_dir: Target spec-kit project directory
34
+ kits: List of kits to install (None = use default from manifest)
35
+ force: Skip confirmations and overwrite existing files
36
+ agent: Explicit agent preference (None = auto-detect)
37
+ shell: Explicit shell preference (None = auto-detect)
38
+ """
39
+ self.target_dir = Path(target_dir).resolve()
40
+ self.kits_dir = Path(__file__).parent.parent / "kits"
41
+
42
+ # Load manifest
43
+ self.manifest = KitManifest(self.kits_dir)
44
+
45
+ # Initialize specialized modules
46
+ self.detector = Detector(self.target_dir, self.manifest)
47
+ self.validator = Validator(self.target_dir, self.manifest)
48
+ self.conflict_checker = ConflictChecker(
49
+ self.target_dir,
50
+ self.kits_dir,
51
+ self.manifest
52
+ )
53
+
54
+ # Operational modes
55
+ self.force = force
56
+
57
+ # Preferences
58
+ self.preferred_agent = agent
59
+ self.preferred_shell = shell
60
+
61
+ # Kits to install
62
+ self.kits = kits or [self.manifest.get_default_kit()]
63
+
64
+ # Validate kit names
65
+ self._validate_kit_names()
66
+
67
+ def _validate_kit_names(self):
68
+ """Validate kit names against manifest."""
69
+ valid_kits = set(self.manifest.get_kit_names())
70
+ invalid = set(self.kits) - valid_kits
71
+ if invalid:
72
+ valid_list = ', '.join(sorted(valid_kits))
73
+ raise ValueError(f"Invalid kit(s): {invalid}. Valid: {valid_list}")
74
+
75
+ def is_spec_kit_project(self) -> bool:
76
+ """Check if target is a spec-kit project."""
77
+ return self.detector.is_spec_kit_project()
78
+
79
+ def is_kit_installed(self, kit_name: str) -> bool:
80
+ """Check if kit is installed."""
81
+ return self.validator.is_kit_installed(kit_name)
82
+
83
+ def preview_installation(self) -> Dict:
84
+ """Preview installation without making changes."""
85
+ agents = self.detector.detect_agents(self.preferred_agent)
86
+ shells = self.detector.detect_shells(self.preferred_shell)
87
+
88
+ preview = {
89
+ "kits": [],
90
+ "conflicts": [],
91
+ "warnings": [],
92
+ "agents": agents,
93
+ "shells": shells,
94
+ }
95
+
96
+ if not agents:
97
+ supported = [
98
+ name for name, config in self.manifest.manifest.get('agents', {}).items()
99
+ if config.get('supported', False)
100
+ ]
101
+ preview['warnings'].append(f"No AI agents detected. Supported: {', '.join(supported)}")
102
+ return preview
103
+
104
+ conflicts = self.conflict_checker.check_conflicts(self.kits, agents, shells)
105
+ preview['conflicts'] = conflicts['overwrites']
106
+
107
+ for kit_name in self.kits:
108
+ kit_preview = self._preview_kit(kit_name, agents, shells)
109
+ preview['kits'].append(kit_preview)
110
+
111
+ return preview
112
+
113
+ def _preview_kit(self, kit_name: str, agents: List[str], shells: List[str]) -> Dict:
114
+ """Preview installation for a single kit."""
115
+ kit_info = self.manifest.get_kit(kit_name)
116
+ kit_preview = {
117
+ "name": kit_info['name'],
118
+ "new_files": [],
119
+ "modified_files": [],
120
+ "new_directories": [],
121
+ }
122
+
123
+ for agent in agents:
124
+ files = self.manifest.get_kit_files(kit_name, agent=agent)
125
+ self._preview_files(files, kit_preview)
126
+
127
+ for shell in shells:
128
+ files = self.manifest.get_kit_files(kit_name, agent=shell)
129
+ self._preview_files(files, kit_preview)
130
+
131
+ # Get other files (not commands\prompts\scripts - those are handled above)
132
+ all_files = self.manifest.get_kit_files(kit_name, agent=None)
133
+ for file_info in all_files:
134
+ if file_info.get('type') in ['command', 'prompt', 'script']:
135
+ continue # Already handled by agent/shell sections above
136
+ self._preview_files([file_info], kit_preview)
137
+
138
+ return kit_preview
139
+
140
+ def _preview_files(self, files: List[Dict], preview: Dict):
141
+ """Preview a list of files."""
142
+ for file_info in files:
143
+ if file_info.get('status') == 'planned':
144
+ continue
145
+
146
+ # Normalize paths to use backslashes for Windows display
147
+ target_path = str(file_info['path']).replace("/", "\\")
148
+ target_full = self.target_dir / file_info['path']
149
+
150
+ if target_full.exists():
151
+ if target_path not in preview["modified_files"]:
152
+ preview["modified_files"].append(target_path)
153
+ else:
154
+ if target_path not in preview["new_files"]:
155
+ preview["new_files"].append(target_path)
156
+
157
+ parent_dir = str(target_full.parent.relative_to(self.target_dir))
158
+ if parent_dir not in preview["new_directories"]:
159
+ if not target_full.parent.exists():
160
+ preview["new_directories"].append(parent_dir)
161
+
162
+ def install(self) -> Dict:
163
+ """Install kits to target project."""
164
+ result = {
165
+ "success": False,
166
+ "installed": [],
167
+ "skipped": [],
168
+ "error": None,
169
+ }
170
+
171
+ try:
172
+ agents = self.detector.detect_agents(self.preferred_agent)
173
+ shells = self.detector.detect_shells(self.preferred_shell)
174
+
175
+ if not agents:
176
+ supported = [
177
+ name for name, config in self.manifest.manifest.get('agents', {}).items()
178
+ if config.get('supported', False)
179
+ ]
180
+ result["error"] = (
181
+ f"No supported AI interface found. Supported: {', '.join(supported)}. "
182
+ r"To enable AI interface support, create a '.claude\' or '.github\prompts\' directory in your project."
183
+ )
184
+ return result
185
+
186
+ if not self.force:
187
+ conflicts = self.conflict_checker.check_conflicts(self.kits, agents, shells)
188
+
189
+ if conflicts['has_conflicts']:
190
+ result["conflicts"] = conflicts['overwrites']
191
+ result["error"] = f"Found {len(conflicts['conflicts'])} file conflicts. Use --force to overwrite."
192
+ return result
193
+
194
+ options = self.manifest.manifest.get('options', {})
195
+
196
+ for kit_name in self.kits:
197
+ self._install_kit(kit_name, agents, shells, options, result)
198
+
199
+ result["success"] = True
200
+
201
+ if options.get('validate_on_install', True):
202
+ result["validation"] = self.validator.validate_all()
203
+
204
+ except Exception as e:
205
+ result["error"] = str(e)
206
+
207
+ return result
208
+
209
+ def _install_kit(self, kit_name: str, agents: List[str], shells: List[str], options: Dict, result: Dict):
210
+ """Install a single kit."""
211
+ skip_existing = options.get('skip_existing', True)
212
+
213
+ for agent in agents:
214
+ files = self.manifest.get_kit_files(kit_name, agent=agent)
215
+ self._install_files(files, skip_existing, result)
216
+
217
+ for shell in shells:
218
+ files = self.manifest.get_kit_files(kit_name, agent=shell)
219
+ self._install_files(files, skip_existing, result)
220
+
221
+ all_files = self.manifest.get_kit_files(kit_name, agent=None)
222
+ for file_info in all_files:
223
+ if file_info.get('type') in ['command', 'prompt', 'script']:
224
+ continue
225
+ self._install_files([file_info], skip_existing, result)
226
+
227
+ def _install_files(self, files: List[Dict], skip_existing: bool, result: Dict):
228
+ """Install a list of files."""
229
+ for file_info in files:
230
+ if file_info.get('status') == 'planned':
231
+ result["skipped"].append(f"{file_info['path']} (planned)")
232
+ continue
233
+
234
+ target_path = self.target_dir / file_info['path']
235
+
236
+ if skip_existing and target_path.exists() and not self.force:
237
+ result["skipped"].append(file_info['path'])
238
+ continue
239
+
240
+ self._copy_file(file_info['source'], file_info['path'])
241
+ result["installed"].append(file_info['path'])
242
+
243
+ def validate(self) -> Dict:
244
+ """Validate all installed kits."""
245
+ return self.validator.validate_all()
246
+
247
+ def preview_removal(self) -> Dict:
248
+ """Preview files that would be removed."""
249
+ preview = {
250
+ "kits": [],
251
+ "total_files": 0,
252
+ }
253
+
254
+ for kit_name in self.kits:
255
+ kit_info = self.manifest.get_kit(kit_name)
256
+ files_to_remove = []
257
+
258
+ all_files = self.manifest.get_kit_files(kit_name, agent=None)
259
+
260
+ for file_info in all_files:
261
+ target_path = self.target_dir / file_info['path']
262
+ if target_path.exists():
263
+ files_to_remove.append(file_info['path'])
264
+
265
+ if files_to_remove:
266
+ preview["kits"].append({
267
+ 'name': kit_info['name'],
268
+ 'files': files_to_remove
269
+ })
270
+ preview["total_files"] += len(files_to_remove)
271
+
272
+ return preview
273
+
274
+ def remove(self) -> Dict:
275
+ """Remove kits from project."""
276
+ result = {
277
+ "success": False,
278
+ "removed": [],
279
+ "not_found": [],
280
+ "error": None,
281
+ }
282
+
283
+ try:
284
+ for kit_name in self.kits:
285
+ kit_info = self.manifest.get_kit(kit_name)
286
+ removed_files = []
287
+ not_found_files = []
288
+
289
+ all_files = self.manifest.get_kit_files(kit_name, agent=None)
290
+
291
+ for file_info in all_files:
292
+ target_path = self.target_dir / file_info['path']
293
+
294
+ if target_path.exists():
295
+ target_path.unlink()
296
+ removed_files.append(file_info['path'])
297
+ else:
298
+ not_found_files.append(file_info['path'])
299
+
300
+ if removed_files:
301
+ result["removed"].append({'kit': kit_info['name'], 'files': removed_files})
302
+
303
+ if not_found_files:
304
+ result["not_found"].extend(not_found_files)
305
+
306
+ result["success"] = True
307
+
308
+ except Exception as e:
309
+ result["error"] = str(e)
310
+
311
+ return result
312
+
313
+ def _copy_file(self, kit_relative_path: str, target_relative_path: str):
314
+ """Copy file from kits/ to target project."""
315
+ source = self.kits_dir / kit_relative_path
316
+ target = self.target_dir / target_relative_path
317
+
318
+ if not source.exists():
319
+ raise FileNotFoundError(f"Kit file not found: {source}")
320
+
321
+ target.parent.mkdir(parents=True, exist_ok=True)
322
+ shutil.copy2(source, target)
@@ -0,0 +1,146 @@
1
+ """
2
+ Kit manifest loader and utilities.
3
+
4
+ Loads kit definitions from kits.yaml and provides helpers for installation,
5
+ validation, and status checking.
6
+ """
7
+
8
+ from pathlib import Path
9
+ from typing import Dict, List, Optional
10
+ import yaml
11
+
12
+
13
+ class KitManifest:
14
+ """Loads and provides access to kit definitions from kits.yaml"""
15
+
16
+ def __init__(self, kits_dir: Path):
17
+ """
18
+ Initialize manifest loader.
19
+
20
+ Args:
21
+ kits_dir: Path to kits directory containing kits.yaml
22
+ """
23
+ self.kits_dir = kits_dir
24
+ self.manifest_path = kits_dir / "kits.yaml"
25
+ self._manifest = None
26
+
27
+ @property
28
+ def manifest(self) -> Dict:
29
+ """Load and cache manifest data"""
30
+ if self._manifest is None:
31
+ with open(self.manifest_path, encoding='utf-8') as f:
32
+ self._manifest = yaml.safe_load(f)
33
+ return self._manifest
34
+
35
+ def get_kit(self, kit_name: str) -> Optional[Dict]:
36
+ """Get kit definition by name"""
37
+ return self.manifest['kits'].get(kit_name)
38
+
39
+ def get_all_kits(self) -> Dict[str, Dict]:
40
+ """Get all kit definitions"""
41
+ return self.manifest['kits']
42
+
43
+ def get_kit_names(self) -> List[str]:
44
+ """Get list of all kit names"""
45
+ return list(self.manifest['kits'].keys())
46
+
47
+ def get_recommended_kits(self) -> List[str]:
48
+ """Get list of recommended kit names"""
49
+ return [
50
+ name for name, kit in self.manifest['kits'].items()
51
+ if kit.get('recommended', False)
52
+ ]
53
+
54
+ def get_default_kit(self) -> str:
55
+ """Get default kit name"""
56
+ return self.manifest['options']['default_kit']
57
+
58
+ def get_kit_files(self, kit_name: str, agent: Optional[str] = None) -> List[Dict]:
59
+ """
60
+ Get list of files for a kit.
61
+
62
+ Args:
63
+ kit_name: Name of kit
64
+ agent: Optional agent filter ('claude', 'copilot', None for all)
65
+
66
+ Returns:
67
+ List of file dicts with 'path', 'source', 'required' keys
68
+ """
69
+ kit = self.get_kit(kit_name)
70
+ if not kit:
71
+ return []
72
+
73
+ files = []
74
+ file_groups = kit.get('files', {})
75
+
76
+ # Map agent names to file groups
77
+ agent_groups = {
78
+ 'claude': ['claude'],
79
+ 'copilot': ['copilot'],
80
+ None: list(file_groups.keys()) # All groups
81
+ }
82
+
83
+ groups_to_include = agent_groups.get(agent, [])
84
+
85
+ for group_name in groups_to_include:
86
+ if group_name in file_groups:
87
+ files.extend(file_groups[group_name])
88
+
89
+ return files
90
+
91
+ def get_kit_markers(self, kit_name: str) -> List[str]:
92
+ """
93
+ Get marker files for kit detection.
94
+
95
+ Args:
96
+ kit_name: Name of kit
97
+
98
+ Returns:
99
+ List of marker file paths
100
+ """
101
+ kit = self.get_kit(kit_name)
102
+ return kit.get('markers', []) if kit else []
103
+
104
+ def get_kit_commands(self, kit_name: str) -> List[Dict]:
105
+ """
106
+ Get list of commands for a kit.
107
+
108
+ Args:
109
+ kit_name: Name of kit
110
+
111
+ Returns:
112
+ List of command dicts with 'name', 'description', 'status' keys
113
+ """
114
+ kit = self.get_kit(kit_name)
115
+ return kit.get('commands', []) if kit else []
116
+
117
+ def get_agent_config(self, agent: str) -> Optional[Dict]:
118
+ """
119
+ Get agent configuration.
120
+
121
+ Args:
122
+ agent: Agent name ('claude', 'copilot')
123
+
124
+ Returns:
125
+ Agent config dict or None
126
+ """
127
+ return self.manifest.get('agents', {}).get(agent)
128
+
129
+ def validate_kit_name(self, kit_name: str) -> bool:
130
+ """Check if kit name is valid"""
131
+ return kit_name in self.get_kit_names()
132
+
133
+ def get_kit_description(self, kit_name: str) -> str:
134
+ """Get kit description"""
135
+ kit = self.get_kit(kit_name)
136
+ return kit.get('description', '') if kit else ''
137
+
138
+ def get_kit_icon(self, kit_name: str) -> str:
139
+ """Get kit icon emoji"""
140
+ kit = self.get_kit(kit_name)
141
+ return kit.get('icon', '📦') if kit else '📦'
142
+
143
+ def is_recommended(self, kit_name: str) -> bool:
144
+ """Check if kit is recommended"""
145
+ kit = self.get_kit(kit_name)
146
+ return kit.get('recommended', False) if kit else False
@@ -0,0 +1,146 @@
1
+ """
2
+ Kit validation and integrity checking.
3
+
4
+ Validates installed kits, checks for missing/corrupted files.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Dict
9
+
10
+ from .manifest import KitManifest
11
+
12
+
13
+ class Validator:
14
+ """Validates kit installations."""
15
+
16
+ def __init__(self, target_dir: Path, manifest: KitManifest):
17
+ """
18
+ Initialize validator.
19
+
20
+ Args:
21
+ target_dir: Target project directory
22
+ manifest: Loaded kit manifest
23
+ """
24
+ self.target_dir = target_dir
25
+ self.manifest = manifest
26
+
27
+ def validate_all(self) -> Dict:
28
+ """
29
+ Validate all kits.
30
+
31
+ Returns:
32
+ Validation results for all kits
33
+ """
34
+ checks = {}
35
+ options = self.manifest.manifest.get('options', {})
36
+
37
+ for kit_name in self.manifest.get_kit_names():
38
+ checks[kit_name] = self.validate_kit(kit_name, options)
39
+
40
+ # Overall validation passes if at least one kit is fully installed
41
+ any_installed = any(
42
+ check['status'] == 'installed'
43
+ for check in checks.values()
44
+ )
45
+
46
+ return {
47
+ "valid": any_installed,
48
+ "checks": checks,
49
+ }
50
+
51
+ def validate_kit(self, kit_name: str, options: Dict) -> Dict:
52
+ """
53
+ Validate a single kit.
54
+
55
+ Args:
56
+ kit_name: Name of kit to validate
57
+ options: Options from manifest
58
+
59
+ Returns:
60
+ Validation result for this kit
61
+ """
62
+ kit_info = self.manifest.get_kit(kit_name)
63
+ markers = self.manifest.get_kit_markers(kit_name)
64
+
65
+ # Check if kit is installed
66
+ kit_installed = any(
67
+ (self.target_dir / marker).exists()
68
+ for marker in markers
69
+ )
70
+
71
+ if not kit_installed:
72
+ return {
73
+ "passed": True,
74
+ "status": "not_installed",
75
+ "message": f"{kit_info['name']}: not installed",
76
+ }
77
+
78
+ # Kit is installed, validate files
79
+ all_files = self.manifest.get_kit_files(kit_name, agent=None)
80
+
81
+ missing = []
82
+ corrupted = []
83
+ outdated = []
84
+
85
+ for file_info in all_files:
86
+ # Skip non-required files
87
+ if not file_info.get('required', True):
88
+ continue
89
+
90
+ # Skip planned files
91
+ if file_info.get('status') == 'planned':
92
+ continue
93
+
94
+ target_path = self.target_dir / file_info['path']
95
+
96
+ # Check exists
97
+ if not target_path.exists():
98
+ missing.append(file_info['path'])
99
+ continue
100
+
101
+ # Check integrity
102
+ if options.get('check_file_integrity', True):
103
+ min_size = options.get('min_file_size', 100)
104
+ if target_path.stat().st_size < min_size:
105
+ corrupted.append(file_info['path'])
106
+
107
+ # Check if outdated (differs from source)
108
+ # (Placeholder for now, can add diff later)
109
+
110
+ # Build result
111
+ if missing or corrupted:
112
+ issues = []
113
+ if missing:
114
+ issues.append(f"{len(missing)} missing")
115
+ if corrupted:
116
+ issues.append(f"{len(corrupted)} corrupted")
117
+
118
+ return {
119
+ "passed": False,
120
+ "status": "partial",
121
+ "message": f"{kit_info['name']}: {', '.join(issues)}",
122
+ "missing_files": missing,
123
+ "corrupted_files": corrupted,
124
+ }
125
+
126
+ return {
127
+ "passed": True,
128
+ "status": "installed",
129
+ "message": f"{kit_info['name']}: all files present",
130
+ }
131
+
132
+ def is_kit_installed(self, kit_name: str) -> bool:
133
+ """
134
+ Quick check if kit is installed.
135
+
136
+ Args:
137
+ kit_name: Name of kit
138
+
139
+ Returns:
140
+ True if any marker exists
141
+ """
142
+ markers = self.manifest.get_kit_markers(kit_name)
143
+ return any(
144
+ (self.target_dir / marker).exists()
145
+ for marker in markers
146
+ )
lite_kits/kits/README.md CHANGED
@@ -6,11 +6,11 @@ This directory contains modular add-on kits that can be installed independently
6
6
 
7
7
  ### ✅ Recommended (Default Installation)
8
8
 
9
- #### 1. **project-kit**
10
- **Commands**: `/orient` ⭐, `/review`, `/audit`, `/stats`
9
+ #### 1. **dev-kit**
10
+ **Commands**: `/orient` ⭐, `/audit`, `/stats`
11
11
  **Scripts**: Enhanced feature creation with custom naming
12
12
 
13
- Essential project-level utilities combining agent orientation, code quality checks, and vanilla spec-kit enhancements.
13
+ Essential project-level utilities combining agent orientation, quality checks, and vanilla spec-kit enhancements.
14
14
 
15
15
  **Installs to**:
16
16
  - `.claude/commands/` (Claude Code)
@@ -21,10 +21,10 @@ Essential project-level utilities combining agent orientation, code quality chec
21
21
 
22
22
  ---
23
23
 
24
- #### 2. **git-kit**
25
- **Commands**: `/commit`, `/pr`, `/sync`, `/cleanup`
24
+ #### 2. **dev-kit**
25
+ **Commands**: `/commit`, `/pr`, `/review`, `/sync`, `/cleanup`
26
26
 
27
- Git workflow automation with smart commits, PR creation, sync status, and cleanup operations. Includes ASCII visualization for better readability.
27
+ Git workflow automation with smart commits, PR creation, code review, sync status, and cleanup operations. Includes ASCII visualization for better readability.
28
28
 
29
29
  **Installs to**:
30
30
  - `.claude/commands/` (Claude Code)
@@ -41,14 +41,14 @@ Git workflow automation with smart commits, PR creation, sync status, and cleanu
41
41
 
42
42
  Multi-agent coordination structure for complex projects with multiple AI agents working in parallel.
43
43
 
44
- **Dependencies**: Requires `project-kit` (for `/review`) and `git-kit` (for `/commit`, `/pr`)
44
+ **Dependencies**: None (standalone)
45
45
 
46
46
  **Installs to**:
47
47
  - `.specify/memory/pr-workflow-guide.md`
48
48
  - `.specify/memory/git-worktrees-protocol.md`
49
49
  - `specs/*/collaboration/` (template, created per-feature)
50
50
 
51
- **Use case**: Large projects with multiple AI agents collaborating (e.g., Claude Code + Copilot).
51
+ **Use case**: Large projects with multiple AI agents collaborating (e.g., Claude Code + Copilot). Works best when combined with dev-kit and dev-kit.
52
52
 
53
53
  ---
54
54
 
@@ -56,9 +56,9 @@ Multi-agent coordination structure for complex projects with multiple AI agents
56
56
 
57
57
  | Kit | Default | Target Users | Adds | Dependencies |
58
58
  |-----|---------|--------------|------|--------------|
59
- | **project** | ✅ Yes | Everyone | 4 commands + enhanced scripts | None |
59
+ | **project** | ✅ Yes | Everyone | 3 commands + enhanced scripts | None |
60
60
  | **git** | ✅ Yes | Everyone | 4 commands with ASCII viz | None |
61
- | **multiagent** | ❌ No | Multi-agent projects | Collaboration structure | project, git |
61
+ | **multiagent** | ❌ No | Multi-agent projects | Collaboration structure + /sync | None |
62
62
 
63
63
  ## Kit Structure
64
64
 
@@ -139,25 +139,24 @@ lite-kits remove -Kit git,project
139
139
 
140
140
  ## Kit Details
141
141
 
142
- ### project-kit Commands
142
+ ### dev-kit Commands
143
143
 
144
144
  | Command | Description |
145
145
  |---------|-------------|
146
146
  | `/orient` | Agent orientation (read docs, check git, determine role) |
147
- | `/review` | Code review against constitution and best practices |
148
147
  | `/audit` | Security and quality audit |
149
148
  | `/stats` | Project statistics (LOC, test coverage, complexity) |
150
149
 
151
- ### git-kit Commands
150
+ ### dev-kit Commands
152
151
 
153
152
  | Command | Description |
154
153
  |---------|-------------|
155
154
  | `/commit` | Smart commit with agent attribution |
156
155
  | `/pr` | Create pull request with auto-generated description |
157
- | `/sync` | Show sync status with ASCII visualization |
156
+ | `/review` | Code review of staged changes against best practices |
158
157
  | `/cleanup` | Clean merged branches, stale worktrees |
159
158
 
160
- ### project-kit Enhancements
159
+ ### dev-kit Enhancements
161
160
 
162
161
  | Enhancement | Description |
163
162
  |-------------|-------------|