devforgeai 1.0.4 → 1.0.6

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 (134) hide show
  1. package/CLAUDE.md +120 -0
  2. package/package.json +9 -1
  3. package/src/CLAUDE.md +699 -0
  4. package/src/claude/scripts/README.md +396 -0
  5. package/src/claude/scripts/audit-command-skill-overlap.sh +67 -0
  6. package/src/claude/scripts/check-hooks-fast.sh +70 -0
  7. package/src/claude/scripts/devforgeai-validate +6 -0
  8. package/src/claude/scripts/devforgeai_cli/README.md +531 -0
  9. package/src/claude/scripts/devforgeai_cli/__init__.py +12 -0
  10. package/src/claude/scripts/devforgeai_cli/cli.py +716 -0
  11. package/src/claude/scripts/devforgeai_cli/commands/__init__.py +1 -0
  12. package/src/claude/scripts/devforgeai_cli/commands/check_hooks.py +384 -0
  13. package/src/claude/scripts/devforgeai_cli/commands/invoke_hooks.py +149 -0
  14. package/src/claude/scripts/devforgeai_cli/commands/phase_commands.py +731 -0
  15. package/src/claude/scripts/devforgeai_cli/commands/validate_installation.py +412 -0
  16. package/src/claude/scripts/devforgeai_cli/context_extraction.py +426 -0
  17. package/src/claude/scripts/devforgeai_cli/feedback/AC_TO_TEST_MAPPING.md +636 -0
  18. package/src/claude/scripts/devforgeai_cli/feedback/DELIVERY_SUMMARY.txt +329 -0
  19. package/src/claude/scripts/devforgeai_cli/feedback/README_TEST_SPECS.md +486 -0
  20. package/src/claude/scripts/devforgeai_cli/feedback/TEST_IMPLEMENTATION_GUIDE.md +529 -0
  21. package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECIFICATIONS.md +2652 -0
  22. package/src/claude/scripts/devforgeai_cli/feedback/TEST_SPECS_INDEX.md +398 -0
  23. package/src/claude/scripts/devforgeai_cli/feedback/__init__.py +34 -0
  24. package/src/claude/scripts/devforgeai_cli/feedback/adaptive_questioning_engine.py +581 -0
  25. package/src/claude/scripts/devforgeai_cli/feedback/aggregation.py +179 -0
  26. package/src/claude/scripts/devforgeai_cli/feedback/commands.py +535 -0
  27. package/src/claude/scripts/devforgeai_cli/feedback/config_defaults.py +58 -0
  28. package/src/claude/scripts/devforgeai_cli/feedback/config_manager.py +423 -0
  29. package/src/claude/scripts/devforgeai_cli/feedback/config_models.py +192 -0
  30. package/src/claude/scripts/devforgeai_cli/feedback/config_schema.py +140 -0
  31. package/src/claude/scripts/devforgeai_cli/feedback/coverage.json +1 -0
  32. package/src/claude/scripts/devforgeai_cli/feedback/feature_flag.py +152 -0
  33. package/src/claude/scripts/devforgeai_cli/feedback/feedback_indexer.py +394 -0
  34. package/src/claude/scripts/devforgeai_cli/feedback/hot_reload.py +226 -0
  35. package/src/claude/scripts/devforgeai_cli/feedback/longitudinal.py +115 -0
  36. package/src/claude/scripts/devforgeai_cli/feedback/models.py +67 -0
  37. package/src/claude/scripts/devforgeai_cli/feedback/question_router.py +236 -0
  38. package/src/claude/scripts/devforgeai_cli/feedback/retrospective.py +233 -0
  39. package/src/claude/scripts/devforgeai_cli/feedback/skip_tracker.py +177 -0
  40. package/src/claude/scripts/devforgeai_cli/feedback/skip_tracking.py +221 -0
  41. package/src/claude/scripts/devforgeai_cli/feedback/template_engine.py +549 -0
  42. package/src/claude/scripts/devforgeai_cli/feedback/validation.py +163 -0
  43. package/src/claude/scripts/devforgeai_cli/headless/__init__.py +30 -0
  44. package/src/claude/scripts/devforgeai_cli/headless/answer_models.py +206 -0
  45. package/src/claude/scripts/devforgeai_cli/headless/answer_resolver.py +204 -0
  46. package/src/claude/scripts/devforgeai_cli/headless/exceptions.py +36 -0
  47. package/src/claude/scripts/devforgeai_cli/headless/pattern_matcher.py +156 -0
  48. package/src/claude/scripts/devforgeai_cli/hooks.py +313 -0
  49. package/src/claude/scripts/devforgeai_cli/metrics/__init__.py +46 -0
  50. package/src/claude/scripts/devforgeai_cli/metrics/command_metrics.py +142 -0
  51. package/src/claude/scripts/devforgeai_cli/metrics/failure_modes.py +152 -0
  52. package/src/claude/scripts/devforgeai_cli/metrics/story_segmentation.py +181 -0
  53. package/src/claude/scripts/devforgeai_cli/orchestrate_hooks.py +780 -0
  54. package/src/claude/scripts/devforgeai_cli/phase_state.py +1229 -0
  55. package/src/claude/scripts/devforgeai_cli/session/__init__.py +30 -0
  56. package/src/claude/scripts/devforgeai_cli/session/checkpoint.py +268 -0
  57. package/src/claude/scripts/devforgeai_cli/tests/__init__.py +1 -0
  58. package/src/claude/scripts/devforgeai_cli/tests/conftest.py +29 -0
  59. package/src/claude/scripts/devforgeai_cli/tests/feedback/TEST_EXECUTION_GUIDE.md +298 -0
  60. package/src/claude/scripts/devforgeai_cli/tests/feedback/__init__.py +3 -0
  61. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_adaptive_questioning_engine.py +2171 -0
  62. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_aggregation.py +476 -0
  63. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_defaults.py +133 -0
  64. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_manager.py +592 -0
  65. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_models.py +373 -0
  66. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_config_schema.py +130 -0
  67. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_configuration_management.py +1355 -0
  68. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_edge_cases.py +308 -0
  69. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feature_flag.py +307 -0
  70. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_feedback_indexer.py +384 -0
  71. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_hot_reload.py +580 -0
  72. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_integration.py +402 -0
  73. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_models.py +105 -0
  74. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_question_routing.py +262 -0
  75. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_retrospective.py +333 -0
  76. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracker.py +410 -0
  77. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking.py +159 -0
  78. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_skip_tracking_integration.py +1155 -0
  79. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_template_engine.py +1389 -0
  80. package/src/claude/scripts/devforgeai_cli/tests/feedback/test_validation_comprehensive.py +210 -0
  81. package/src/claude/scripts/devforgeai_cli/tests/fixtures/autonomous-deferral-story.md +46 -0
  82. package/src/claude/scripts/devforgeai_cli/tests/fixtures/missing-impl-notes.md +31 -0
  83. package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-deferral-story.md +46 -0
  84. package/src/claude/scripts/devforgeai_cli/tests/fixtures/valid-story-complete.md +48 -0
  85. package/src/claude/scripts/devforgeai_cli/tests/manual_test_invoke_hooks.sh +200 -0
  86. package/src/claude/scripts/devforgeai_cli/tests/session/DELIVERABLES.md +518 -0
  87. package/src/claude/scripts/devforgeai_cli/tests/session/TEST_SUMMARY.md +468 -0
  88. package/src/claude/scripts/devforgeai_cli/tests/session/__init__.py +6 -0
  89. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/corrupted-checkpoint.json +1 -0
  90. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/missing-fields-checkpoint.json +4 -0
  91. package/src/claude/scripts/devforgeai_cli/tests/session/fixtures/valid-checkpoint.json +15 -0
  92. package/src/claude/scripts/devforgeai_cli/tests/session/test_checkpoint.py +851 -0
  93. package/src/claude/scripts/devforgeai_cli/tests/test_check_hooks.py +1886 -0
  94. package/src/claude/scripts/devforgeai_cli/tests/test_depends_on_normalizer.py +171 -0
  95. package/src/claude/scripts/devforgeai_cli/tests/test_dod_validator.py +97 -0
  96. package/src/claude/scripts/devforgeai_cli/tests/test_invoke_hooks.py +1902 -0
  97. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands.py +320 -0
  98. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_error_handling.py +1021 -0
  99. package/src/claude/scripts/devforgeai_cli/tests/test_phase_commands_import.py +697 -0
  100. package/src/claude/scripts/devforgeai_cli/tests/test_phase_state.py +2187 -0
  101. package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking.py +2141 -0
  102. package/src/claude/scripts/devforgeai_cli/tests/test_skip_tracking_coverage_gap.py +195 -0
  103. package/src/claude/scripts/devforgeai_cli/tests/test_subagent_enforcement.py +539 -0
  104. package/src/claude/scripts/devforgeai_cli/tests/test_validate_installation.py +361 -0
  105. package/src/claude/scripts/devforgeai_cli/utils/__init__.py +11 -0
  106. package/src/claude/scripts/devforgeai_cli/utils/depends_on_normalizer.py +149 -0
  107. package/src/claude/scripts/devforgeai_cli/utils/markdown_parser.py +219 -0
  108. package/src/claude/scripts/devforgeai_cli/utils/story_analyzer.py +249 -0
  109. package/src/claude/scripts/devforgeai_cli/utils/yaml_parser.py +152 -0
  110. package/src/claude/scripts/devforgeai_cli/validators/__init__.py +27 -0
  111. package/src/claude/scripts/devforgeai_cli/validators/ast_grep_validator.py +373 -0
  112. package/src/claude/scripts/devforgeai_cli/validators/context_validator.py +180 -0
  113. package/src/claude/scripts/devforgeai_cli/validators/dod_validator.py +309 -0
  114. package/src/claude/scripts/devforgeai_cli/validators/git_validator.py +107 -0
  115. package/src/claude/scripts/devforgeai_cli/validators/grep_fallback.py +300 -0
  116. package/src/claude/scripts/install_hooks.sh +186 -0
  117. package/src/claude/scripts/invoke_feedback_hooks.sh +59 -0
  118. package/src/claude/scripts/migrate-ac-headers.sh +122 -0
  119. package/src/claude/scripts/plan_file_kb.sh +704 -0
  120. package/src/claude/scripts/requirements.txt +8 -0
  121. package/src/claude/scripts/session_catalog.sh +543 -0
  122. package/src/claude/scripts/setup.py +55 -0
  123. package/src/claude/scripts/start-devforgeai.sh +16 -0
  124. package/src/claude/scripts/statusline.sh +27 -0
  125. package/src/claude/scripts/validate_deferrals.py +344 -0
  126. package/src/claude/skills/devforgeai-qa/SKILL.md +1 -1
  127. package/src/claude/skills/researching-market/SKILL.md +2 -1
  128. package/src/cli/lib/copier.js +13 -1
  129. package/src/claude/skills/designing-systems/scripts/__pycache__/detect_anti_patterns.cpython-312.pyc +0 -0
  130. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_all_context.cpython-312.pyc +0 -0
  131. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_architecture.cpython-312.pyc +0 -0
  132. package/src/claude/skills/designing-systems/scripts/__pycache__/validate_dependencies.cpython-312.pyc +0 -0
  133. package/src/claude/skills/devforgeai-story-creation/scripts/__pycache__/migrate_story_v1_to_v2.cpython-312.pyc +0 -0
  134. package/src/claude/skills/devforgeai-story-creation/scripts/tests/__pycache__/measure_accuracy.cpython-312.pyc +0 -0
@@ -0,0 +1,412 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Validate Installation Command for DevForgeAI CLI.
4
+
5
+ STORY-314: Add Post-Install Validation Command
6
+
7
+ Provides comprehensive post-installation validation that checks:
8
+ 1. CLI availability (devforgeai-validate --version)
9
+ 2. Context files (6 files in devforgeai/specs/context/)
10
+ 3. Hook installation (.git/hooks/pre-commit exists)
11
+ 4. PYTHONPATH configuration
12
+ 5. Git repository (.git/ exists)
13
+ 6. Settings file (.claude/settings.json exists)
14
+
15
+ Each check returns a ValidationResult with pass/fail status,
16
+ descriptive message, and actionable fix instruction for failures.
17
+ """
18
+
19
+ import subprocess
20
+ import sys
21
+ from dataclasses import dataclass, field
22
+ from pathlib import Path
23
+ from typing import List, Optional
24
+
25
+
26
+ # =============================================================================
27
+ # Constants
28
+ # =============================================================================
29
+
30
+ # The 6 required context files
31
+ REQUIRED_CONTEXT_FILES = [
32
+ 'tech-stack.md',
33
+ 'source-tree.md',
34
+ 'dependencies.md',
35
+ 'coding-standards.md',
36
+ 'architecture-constraints.md',
37
+ 'anti-patterns.md'
38
+ ]
39
+
40
+
41
+ # =============================================================================
42
+ # Data Classes
43
+ # =============================================================================
44
+
45
+ @dataclass
46
+ class ValidationResult:
47
+ """Result of a single validation check."""
48
+ passed: bool
49
+ message: str
50
+ fix_instruction: str = ""
51
+
52
+ def __post_init__(self):
53
+ """Ensure fix_instruction has proper format for failures."""
54
+ if not self.passed and self.fix_instruction and not self.fix_instruction.startswith("To fix:"):
55
+ self.fix_instruction = f"To fix: {self.fix_instruction}"
56
+
57
+
58
+ @dataclass
59
+ class InstallationValidationResult:
60
+ """Result of complete installation validation."""
61
+ success: bool
62
+ passed_count: int
63
+ failed_count: int
64
+ checks: List[ValidationResult] = field(default_factory=list)
65
+ exit_code: int = 0
66
+ summary: str = ""
67
+
68
+ def __post_init__(self):
69
+ """Generate summary and exit code from results."""
70
+ if not self.summary:
71
+ if self.success:
72
+ self.summary = f"PASS ({self.passed_count}/{self.passed_count + self.failed_count} checks passed)"
73
+ else:
74
+ self.summary = f"FAIL ({self.passed_count}/{self.passed_count + self.failed_count} checks passed)"
75
+
76
+ if self.exit_code == 0 and not self.success:
77
+ self.exit_code = 1
78
+
79
+ def format_output(self) -> str:
80
+ """Format validation results for display."""
81
+ lines = []
82
+ lines.append("DevForgeAI Installation Validation")
83
+ lines.append("=" * 38)
84
+ lines.append("")
85
+
86
+ for check in self.checks:
87
+ marker = "[✓]" if check.passed else "[✗]"
88
+ lines.append(f"{marker} {check.message}")
89
+ if not check.passed and check.fix_instruction:
90
+ lines.append(f" {check.fix_instruction}")
91
+
92
+ lines.append("")
93
+ lines.append(f"Result: {self.summary}")
94
+
95
+ return "\n".join(lines)
96
+
97
+
98
+ # =============================================================================
99
+ # Individual Check Functions
100
+ # =============================================================================
101
+
102
+ def check_cli_available() -> ValidationResult:
103
+ """
104
+ Check 1: Verify devforgeai-validate CLI is installed and working.
105
+
106
+ Runs: devforgeai-validate --version
107
+
108
+ Returns:
109
+ ValidationResult with pass/fail and version info or fix instruction.
110
+ """
111
+ try:
112
+ result = subprocess.run(
113
+ ["devforgeai-validate", "--version"],
114
+ capture_output=True,
115
+ text=True,
116
+ timeout=10
117
+ )
118
+
119
+ if result.returncode == 0:
120
+ version_output = result.stdout.strip()
121
+ return ValidationResult(
122
+ passed=True,
123
+ message=f"CLI available: {version_output}"
124
+ )
125
+ else:
126
+ return ValidationResult(
127
+ passed=False,
128
+ message="CLI not installed",
129
+ fix_instruction="To fix: pip install -e .claude/scripts/"
130
+ )
131
+
132
+ except FileNotFoundError:
133
+ return ValidationResult(
134
+ passed=False,
135
+ message="CLI not installed",
136
+ fix_instruction="To fix: pip install -e .claude/scripts/"
137
+ )
138
+
139
+ except subprocess.TimeoutExpired:
140
+ return ValidationResult(
141
+ passed=False,
142
+ message="CLI command timed out",
143
+ fix_instruction="To fix: Check for hanging processes and reinstall: pip install -e .claude/scripts/"
144
+ )
145
+
146
+ except Exception as e:
147
+ return ValidationResult(
148
+ passed=False,
149
+ message=f"CLI check error: {e}",
150
+ fix_instruction="To fix: pip install -e .claude/scripts/"
151
+ )
152
+
153
+
154
+ def check_context_files(project_root: str) -> ValidationResult:
155
+ """
156
+ Check 2: Verify all 6 context files exist.
157
+
158
+ Checks: devforgeai/specs/context/{tech-stack,source-tree,...}.md
159
+
160
+ Args:
161
+ project_root: Path to project root directory.
162
+
163
+ Returns:
164
+ ValidationResult with count of present files and missing list.
165
+ """
166
+ root_path = Path(project_root)
167
+ context_dir = root_path / "devforgeai" / "specs" / "context"
168
+
169
+ present_files = []
170
+ missing_files = []
171
+
172
+ for filename in REQUIRED_CONTEXT_FILES:
173
+ file_path = context_dir / filename
174
+ if file_path.exists():
175
+ present_files.append(filename)
176
+ else:
177
+ missing_files.append(filename)
178
+
179
+ present_count = len(present_files)
180
+ total_count = len(REQUIRED_CONTEXT_FILES)
181
+
182
+ if present_count == total_count:
183
+ return ValidationResult(
184
+ passed=True,
185
+ message=f"Context files: {present_count}/{total_count} present"
186
+ )
187
+ else:
188
+ missing_str = ", ".join(missing_files)
189
+ return ValidationResult(
190
+ passed=False,
191
+ message=f"Context files: {present_count}/{total_count} present. Missing: {missing_str}",
192
+ fix_instruction="To fix: Run /create-context to generate missing context files"
193
+ )
194
+
195
+
196
+ def check_hooks_installed(project_root: str) -> ValidationResult:
197
+ """
198
+ Check 3: Verify Git hooks are installed.
199
+
200
+ Checks: .git/hooks/pre-commit exists
201
+
202
+ Args:
203
+ project_root: Path to project root directory.
204
+
205
+ Returns:
206
+ ValidationResult indicating hook installation status.
207
+ """
208
+ root_path = Path(project_root)
209
+ hooks_dir = root_path / ".git" / "hooks"
210
+ pre_commit = hooks_dir / "pre-commit"
211
+
212
+ if pre_commit.exists():
213
+ return ValidationResult(
214
+ passed=True,
215
+ message="Hooks: pre-commit installed"
216
+ )
217
+ elif not (root_path / ".git").exists():
218
+ return ValidationResult(
219
+ passed=False,
220
+ message="Hooks not installed (no .git directory)",
221
+ fix_instruction="To fix: Initialize Git first (git init), then run: bash .claude/scripts/install_hooks.sh"
222
+ )
223
+ else:
224
+ return ValidationResult(
225
+ passed=False,
226
+ message="Hooks not installed",
227
+ fix_instruction="To fix: Run: bash .claude/scripts/install_hooks.sh"
228
+ )
229
+
230
+
231
+ def check_pythonpath() -> ValidationResult:
232
+ """
233
+ Check 4: Verify PYTHONPATH is configured correctly.
234
+
235
+ Tests that devforgeai_cli module can be imported successfully.
236
+
237
+ Returns:
238
+ ValidationResult indicating PYTHONPATH configuration status.
239
+ """
240
+ try:
241
+ # Try to import the CLI module - if we're running, it's working
242
+ import devforgeai_cli
243
+ return ValidationResult(
244
+ passed=True,
245
+ message="PYTHONPATH: configured correctly"
246
+ )
247
+ except ImportError:
248
+ return ValidationResult(
249
+ passed=False,
250
+ message="PYTHONPATH not configured",
251
+ fix_instruction="To fix: See coding-standards.md for PYTHONPATH configuration. "
252
+ "Run: export PYTHONPATH=\".:$PYTHONPATH\""
253
+ )
254
+
255
+
256
+ def check_git_repository(project_root: str) -> ValidationResult:
257
+ """
258
+ Check 5: Verify project is a Git repository.
259
+
260
+ Checks: .git/ directory exists
261
+
262
+ Args:
263
+ project_root: Path to project root directory.
264
+
265
+ Returns:
266
+ ValidationResult indicating Git repository status.
267
+ """
268
+ root_path = Path(project_root)
269
+ git_dir = root_path / ".git"
270
+
271
+ if git_dir.exists() and git_dir.is_dir():
272
+ return ValidationResult(
273
+ passed=True,
274
+ message="Git repository: initialized"
275
+ )
276
+ else:
277
+ return ValidationResult(
278
+ passed=False,
279
+ message="Not a Git repository",
280
+ fix_instruction="To fix: Run: git init"
281
+ )
282
+
283
+
284
+ def check_settings_file(project_root: str) -> ValidationResult:
285
+ """
286
+ Check 6: Verify Claude settings file exists.
287
+
288
+ Checks: .claude/settings.json exists
289
+
290
+ Args:
291
+ project_root: Path to project root directory.
292
+
293
+ Returns:
294
+ ValidationResult indicating settings file status.
295
+ """
296
+ root_path = Path(project_root)
297
+ settings_file = root_path / ".claude" / "settings.json"
298
+
299
+ if settings_file.exists():
300
+ return ValidationResult(
301
+ passed=True,
302
+ message="Settings file: present"
303
+ )
304
+ else:
305
+ return ValidationResult(
306
+ passed=False,
307
+ message="Settings missing",
308
+ fix_instruction="To fix: Run installer to create .claude/settings.json"
309
+ )
310
+
311
+
312
+ # =============================================================================
313
+ # Main Command Function
314
+ # =============================================================================
315
+
316
+ def validate_installation_command(project_root: str) -> InstallationValidationResult:
317
+ """
318
+ Run all 6 installation validation checks.
319
+
320
+ Args:
321
+ project_root: Path to project root directory.
322
+
323
+ Returns:
324
+ InstallationValidationResult with all check results.
325
+ """
326
+ checks = []
327
+
328
+ # Run all 6 checks
329
+ checks.append(check_cli_available())
330
+ checks.append(check_context_files(project_root))
331
+ checks.append(check_hooks_installed(project_root))
332
+ checks.append(check_pythonpath())
333
+ checks.append(check_git_repository(project_root))
334
+ checks.append(check_settings_file(project_root))
335
+
336
+ # Calculate totals
337
+ passed_count = sum(1 for check in checks if check.passed)
338
+ failed_count = sum(1 for check in checks if not check.passed)
339
+ success = failed_count == 0
340
+
341
+ return InstallationValidationResult(
342
+ success=success,
343
+ passed_count=passed_count,
344
+ failed_count=failed_count,
345
+ checks=checks,
346
+ exit_code=0 if success else 1
347
+ )
348
+
349
+
350
+ # =============================================================================
351
+ # CLI Entry Point (for standalone use)
352
+ # =============================================================================
353
+
354
+ def main(project_root: str = ".", output_format: str = "text") -> int:
355
+ """
356
+ Main entry point for validate-installation command.
357
+
358
+ Args:
359
+ project_root: Project root directory.
360
+ output_format: Output format ('text' or 'json').
361
+
362
+ Returns:
363
+ Exit code: 0 if all checks pass, 1 if any fail.
364
+ """
365
+ result = validate_installation_command(project_root)
366
+
367
+ if output_format == "json":
368
+ import json
369
+ output = {
370
+ "success": result.success,
371
+ "passed_count": result.passed_count,
372
+ "failed_count": result.failed_count,
373
+ "exit_code": result.exit_code,
374
+ "summary": result.summary,
375
+ "checks": [
376
+ {
377
+ "passed": check.passed,
378
+ "message": check.message,
379
+ "fix_instruction": check.fix_instruction
380
+ }
381
+ for check in result.checks
382
+ ]
383
+ }
384
+ print(json.dumps(output, indent=2))
385
+ else:
386
+ print(result.format_output())
387
+
388
+ return result.exit_code
389
+
390
+
391
+ if __name__ == "__main__":
392
+ import argparse
393
+
394
+ parser = argparse.ArgumentParser(
395
+ description="Validate DevForgeAI installation"
396
+ )
397
+ parser.add_argument(
398
+ "--project-root",
399
+ default=".",
400
+ help="Project root directory (default: current directory)"
401
+ )
402
+ parser.add_argument(
403
+ "--format",
404
+ choices=["text", "json"],
405
+ default="text",
406
+ help="Output format (default: text)"
407
+ )
408
+
409
+ args = parser.parse_args()
410
+
411
+ exit_code = main(args.project_root, args.format)
412
+ sys.exit(exit_code)