Coverage for src / moai_adk / core / diagnostics / slash_commands.py: 0.00%

41 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-20 20:52 +0900

1"""Slash command diagnostics 

2 

3Diagnose and validate Claude Code slash command loading issues. 

4 

5Functions: 

6- validate_command_file: Validate YAML front matter and required fields 

7- scan_command_files: Recursively scan for .md files 

8- diagnose_slash_commands: Comprehensive diagnostic report 

9""" 

10 

11from pathlib import Path 

12 

13import yaml # type: ignore[import-untyped] 

14 

15 

16def validate_command_file(file_path: Path) -> dict: 

17 """Validate slash command file format 

18 

19 Checks: 

20 1. File exists and readable 

21 2. YAML front matter present (starts with ---) 

22 3. Valid YAML syntax 

23 4. Required fields: name, description 

24 

25 Args: 

26 file_path: Path to command file (.md) 

27 

28 Returns: 

29 dict with 'valid' (bool) and optional 'errors' (list[str]) 

30 

31 Example: 

32 >>> result = validate_command_file(Path("cmd.md")) 

33 >>> if result["valid"]: 

34 ... print("Valid command file") 

35 ... else: 

36 ... print(f"Errors: {result['errors']}") 

37 """ 

38 try: 

39 # Check file exists 

40 if not file_path.exists(): 

41 return {"valid": False, "errors": ["File not found"]} 

42 

43 # Read file content 

44 content = file_path.read_text(encoding="utf-8") 

45 

46 # Check front matter delimiter 

47 if not content.startswith("---"): 

48 return { 

49 "valid": False, 

50 "errors": ["Missing YAML front matter (must start with ---)"], 

51 } 

52 

53 # Split by --- delimiter 

54 parts = content.split("---", 2) 

55 if len(parts) < 3: 

56 return { 

57 "valid": False, 

58 "errors": ["Invalid front matter format (missing closing ---)"], 

59 } 

60 

61 # Parse YAML 

62 try: 

63 metadata = yaml.safe_load(parts[1]) 

64 except yaml.YAMLError as e: 

65 return {"valid": False, "errors": [f"YAML parsing error: {e}"]} 

66 

67 # Check required fields 

68 required_fields = ["name", "description"] 

69 missing_fields = [field for field in required_fields if field not in metadata] 

70 

71 if missing_fields: 

72 return { 

73 "valid": False, 

74 "errors": [f"Missing required field: {', '.join(missing_fields)}"], 

75 } 

76 

77 return {"valid": True} 

78 

79 except Exception as e: 

80 return {"valid": False, "errors": [str(e)]} 

81 

82 

83def scan_command_files(commands_dir: Path) -> list[Path]: 

84 """Scan directory for all .md files 

85 

86 Recursively searches for .md files in the given directory. 

87 

88 Args: 

89 commands_dir: Directory to scan (e.g., .claude/commands) 

90 

91 Returns: 

92 List of Path objects for found .md files 

93 

94 Example: 

95 >>> files = scan_command_files(Path(".claude/commands")) 

96 >>> print(f"Found {len(files)} command files") 

97 """ 

98 if not commands_dir.exists(): 

99 return [] 

100 

101 try: 

102 return list(commands_dir.glob("**/*.md")) 

103 except Exception: 

104 return [] 

105 

106 

107def diagnose_slash_commands() -> dict: 

108 """Diagnose slash command loading issues 

109 

110 Comprehensive diagnostic that: 

111 1. Checks if .claude/commands directory exists 

112 2. Scans for all .md files 

113 3. Validates each file's format 

114 4. Returns detailed report 

115 

116 Returns: 

117 dict with diagnostic results: 

118 - total_files: Number of .md files found 

119 - valid_commands: Number of valid command files 

120 - details: List of per-file validation results 

121 OR 

122 - error: Error message if directory not found 

123 

124 Example: 

125 >>> result = diagnose_slash_commands() 

126 >>> if "error" in result: 

127 ... print(f"Error: {result['error']}") 

128 ... else: 

129 ... print(f"{result['valid_commands']}/{result['total_files']} valid") 

130 """ 

131 commands_dir = Path(".claude/commands") 

132 

133 # Check if directory exists 

134 if not commands_dir.exists(): 

135 return {"error": "Commands directory not found"} 

136 

137 # Scan for .md files 

138 md_files = scan_command_files(commands_dir) 

139 

140 # Validate each file 

141 details = [] 

142 for file_path in md_files: 

143 validation = validate_command_file(file_path) 

144 details.append( 

145 { 

146 "file": str(file_path.relative_to(commands_dir)), 

147 "valid": validation["valid"], 

148 "errors": validation.get("errors", []), 

149 } 

150 ) 

151 

152 # Count valid commands 

153 valid_count = sum(1 for detail in details if detail["valid"]) 

154 

155 return { 

156 "total_files": len(md_files), 

157 "valid_commands": valid_count, 

158 "details": details, 

159 }