@voodocs/cli 0.4.2 → 1.0.1

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 (55) hide show
  1. package/CHANGELOG.md +431 -0
  2. package/lib/cli/__init__.py +53 -0
  3. package/lib/cli/benchmark.py +311 -0
  4. package/lib/cli/fix.py +244 -0
  5. package/lib/cli/generate.py +310 -0
  6. package/lib/cli/test_cli.py +215 -0
  7. package/lib/cli/validate.py +364 -0
  8. package/lib/darkarts/__init__.py +11 -5
  9. package/lib/darkarts/annotations/__init__.py +11 -3
  10. package/lib/darkarts/annotations/darkarts_parser.py +1 -1
  11. package/lib/darkarts/annotations/translator.py +32 -5
  12. package/lib/darkarts/annotations/types.py +15 -2
  13. package/lib/darkarts/cli_darkarts.py +143 -15
  14. package/lib/darkarts/context/__init__.py +11 -3
  15. package/lib/darkarts/context/ai_integrations.py +7 -21
  16. package/lib/darkarts/context/commands.py +1 -1
  17. package/lib/darkarts/context/diagram.py +8 -22
  18. package/lib/darkarts/context/models.py +7 -22
  19. package/lib/darkarts/context/module_utils.py +1 -1
  20. package/lib/darkarts/context/ui.py +1 -1
  21. package/lib/darkarts/context/validation.py +1 -1
  22. package/lib/darkarts/context/yaml_utils.py +8 -23
  23. package/lib/darkarts/core/__init__.py +12 -2
  24. package/lib/darkarts/core/interface.py +15 -1
  25. package/lib/darkarts/core/loader.py +16 -1
  26. package/lib/darkarts/core/plugin.py +15 -2
  27. package/lib/darkarts/core/registry.py +16 -1
  28. package/lib/darkarts/exceptions.py +16 -2
  29. package/lib/darkarts/plugins/voodocs/__init__.py +12 -2
  30. package/lib/darkarts/plugins/voodocs/ai_native_plugin.py +15 -4
  31. package/lib/darkarts/plugins/voodocs/annotation_validator.py +15 -2
  32. package/lib/darkarts/plugins/voodocs/api_spec_generator.py +15 -2
  33. package/lib/darkarts/plugins/voodocs/documentation_generator.py +15 -2
  34. package/lib/darkarts/plugins/voodocs/html_exporter.py +15 -2
  35. package/lib/darkarts/plugins/voodocs/instruction_generator.py +1 -1
  36. package/lib/darkarts/plugins/voodocs/pdf_exporter.py +15 -2
  37. package/lib/darkarts/plugins/voodocs/test_generator.py +15 -2
  38. package/lib/darkarts/telemetry.py +15 -2
  39. package/lib/darkarts/validation/README.md +147 -0
  40. package/lib/darkarts/validation/__init__.py +91 -0
  41. package/lib/darkarts/validation/autofix.py +297 -0
  42. package/lib/darkarts/validation/benchmark.py +426 -0
  43. package/lib/darkarts/validation/benchmark_wrapper.py +22 -0
  44. package/lib/darkarts/validation/config.py +257 -0
  45. package/lib/darkarts/validation/performance.py +412 -0
  46. package/lib/darkarts/validation/performance_wrapper.py +37 -0
  47. package/lib/darkarts/validation/semantic.py +461 -0
  48. package/lib/darkarts/validation/semantic_wrapper.py +77 -0
  49. package/lib/darkarts/validation/test_validation.py +160 -0
  50. package/lib/darkarts/validation/types.py +97 -0
  51. package/lib/darkarts/validation/watch.py +239 -0
  52. package/package.json +19 -6
  53. package/voodocs_cli.py +28 -0
  54. package/cli.py +0 -1646
  55. package/lib/darkarts/cli.py +0 -128
@@ -0,0 +1,364 @@
1
+ """@darkarts
2
+ ⊢cli:validate
3
+ ∂{click,pathlib,typing,sys,darkarts,json}
4
+ ⚠{python≥3.7,click≥8.0,rich≥10.0}
5
+ ⊨{∀validation→executed,∀result→displayed}
6
+ 🔒{read-only:validation}
7
+ ⚡{O(n²)|n=files,nested-iteration-for-display}
8
+ """
9
+
10
+ """
11
+ VooDocs CLI - Validate Command
12
+
13
+ Validates @darkarts annotations in Python files.
14
+ """
15
+
16
+ import click
17
+ import sys
18
+ from pathlib import Path
19
+ from typing import List, Optional
20
+
21
+ # Import validation module
22
+ import sys
23
+ sys.path.insert(0, str(Path(__file__).parent.parent))
24
+ from darkarts.validation import SemanticValidator, PerformanceTracker
25
+ from darkarts.validation.types import ValidationResult, PerformanceResult
26
+
27
+
28
+ @click.command()
29
+ @click.argument('path', type=click.Path(exists=True))
30
+ @click.option(
31
+ '-r', '--recursive',
32
+ is_flag=True,
33
+ help='Recursively validate all Python files in directory'
34
+ )
35
+ @click.option(
36
+ '--deps/--no-deps',
37
+ default=True,
38
+ help='Validate dependencies (default: enabled)'
39
+ )
40
+ @click.option(
41
+ '--perf/--no-perf',
42
+ default=True,
43
+ help='Validate performance claims (default: enabled)'
44
+ )
45
+ @click.option(
46
+ '--strict',
47
+ is_flag=True,
48
+ help='Exit with error code if any validation fails'
49
+ )
50
+ @click.option(
51
+ '--format',
52
+ type=click.Choice(['text', 'json', 'html']),
53
+ default='text',
54
+ help='Output format (default: text)'
55
+ )
56
+ @click.option(
57
+ '--output',
58
+ type=click.Path(),
59
+ help='Output file (default: stdout)'
60
+ )
61
+ @click.option(
62
+ '--exclude',
63
+ multiple=True,
64
+ help='Exclude patterns (can be used multiple times)'
65
+ )
66
+ @click.option(
67
+ '--fix',
68
+ is_flag=True,
69
+ help='Automatically fix issues (preview with --dry-run)'
70
+ )
71
+ @click.option(
72
+ '--dry-run',
73
+ is_flag=True,
74
+ help='Show what would be fixed without making changes'
75
+ )
76
+ def validate(
77
+ path: str,
78
+ recursive: bool,
79
+ deps: bool,
80
+ perf: bool,
81
+ strict: bool,
82
+ format: str,
83
+ output: Optional[str],
84
+ exclude: tuple,
85
+ fix: bool,
86
+ dry_run: bool,
87
+ ):
88
+ """
89
+ Validate @darkarts annotations in Python files.
90
+
91
+ Examples:
92
+
93
+ # Validate a single file
94
+ voodocs validate myfile.py
95
+
96
+ # Validate all files in a directory
97
+ voodocs validate lib/ -r
98
+
99
+ # Validate with strict mode (exit code 1 on failure)
100
+ voodocs validate lib/ -r --strict
101
+
102
+ # Validate only dependencies
103
+ voodocs validate lib/ -r --no-perf
104
+
105
+ # Output as JSON
106
+ voodocs validate lib/ -r --format json --output report.json
107
+
108
+ # Auto-fix issues
109
+ voodocs validate lib/ -r --fix
110
+ """
111
+ path_obj = Path(path)
112
+
113
+ # Print header
114
+ click.echo(f"Validating: {path}")
115
+ click.echo("━" * 60)
116
+ click.echo()
117
+
118
+ # Collect results
119
+ semantic_results: List[ValidationResult] = []
120
+ performance_results: List[PerformanceResult] = []
121
+
122
+ # Run semantic validation
123
+ if deps:
124
+ click.echo("Running semantic validation...")
125
+ validator = SemanticValidator()
126
+
127
+ if path_obj.is_file():
128
+ semantic_results = [validator.validate_file(path_obj)]
129
+ else:
130
+ semantic_results = validator.validate_directory(path_obj, recursive=recursive)
131
+
132
+ click.echo(f"✓ Validated {len(semantic_results)} files")
133
+ click.echo()
134
+
135
+ # Run performance validation
136
+ if perf:
137
+ click.echo("Running performance validation...")
138
+ tracker = PerformanceTracker()
139
+
140
+ if path_obj.is_file():
141
+ performance_results = [tracker.analyze_file(path_obj)]
142
+ else:
143
+ performance_results = tracker.analyze_directory(path_obj, recursive=recursive)
144
+
145
+ click.echo(f"✓ Analyzed {len(performance_results)} files")
146
+ click.echo()
147
+
148
+ # Display results based on format
149
+ if format == 'text':
150
+ display_text_results(semantic_results, performance_results)
151
+ elif format == 'json':
152
+ display_json_results(semantic_results, performance_results, output)
153
+ elif format == 'html':
154
+ display_html_results(semantic_results, performance_results, output)
155
+
156
+ # Summary
157
+ click.echo()
158
+ click.echo("━" * 60)
159
+
160
+ total_files = len(semantic_results) if semantic_results else len(performance_results)
161
+ valid_semantic = sum(1 for r in semantic_results if r.is_valid) if semantic_results else 0
162
+ valid_perf = sum(1 for r in performance_results if r.is_valid) if performance_results else 0
163
+
164
+ if deps and perf:
165
+ valid = min(valid_semantic, valid_perf)
166
+ invalid = total_files - valid
167
+ elif deps:
168
+ valid = valid_semantic
169
+ invalid = total_files - valid
170
+ elif perf:
171
+ valid = valid_perf
172
+ invalid = total_files - valid
173
+ else:
174
+ valid = total_files
175
+ invalid = 0
176
+
177
+ click.echo(f"Total: {total_files} files")
178
+ click.echo(f"Valid: {valid} ({valid/total_files*100:.1f}%)" if total_files > 0 else "Valid: 0")
179
+ click.echo(f"Invalid: {invalid} ({invalid/total_files*100:.1f}%)" if total_files > 0 else "Invalid: 0")
180
+ click.echo("━" * 60)
181
+
182
+ # Exit code
183
+ if strict and invalid > 0:
184
+ click.echo()
185
+ click.echo("❌ Validation failed (strict mode)", err=True)
186
+ sys.exit(1)
187
+ elif invalid > 0:
188
+ click.echo()
189
+ click.echo("💡 Run 'voodocs fix' to automatically fix issues")
190
+ else:
191
+ click.echo()
192
+ click.echo("✅ All validations passed!")
193
+
194
+
195
+ def display_text_results(
196
+ semantic_results: List[ValidationResult],
197
+ performance_results: List[PerformanceResult]
198
+ ):
199
+ """Display results in text format."""
200
+
201
+ # Display semantic results
202
+ if semantic_results:
203
+ click.echo("Semantic Validation Results:")
204
+ click.echo()
205
+
206
+ for result in semantic_results:
207
+ if result.is_valid:
208
+ click.echo(f"✅ {result.file_path}")
209
+ else:
210
+ click.echo(f"❌ {result.file_path}")
211
+
212
+ if result.missing_deps:
213
+ click.echo(f" Missing from ∂{{}}: {', '.join(sorted(result.missing_deps))}")
214
+
215
+ if result.extra_deps:
216
+ click.echo(f" Extra in ∂{{}}: {', '.join(sorted(result.extra_deps))}")
217
+
218
+ if result.errors:
219
+ for error in result.errors:
220
+ click.echo(f" Error: {error}")
221
+
222
+ if result.warnings:
223
+ for warning in result.warnings:
224
+ click.echo(f" Warning: {warning}")
225
+
226
+ click.echo()
227
+
228
+ # Display performance results
229
+ if performance_results:
230
+ click.echo("Performance Validation Results:")
231
+ click.echo()
232
+
233
+ for result in performance_results:
234
+ if result.is_valid:
235
+ click.echo(f"✅ {result.file_path}")
236
+ if hasattr(result, 'claimed_complexity') and result.claimed_complexity:
237
+ click.echo(f" Complexity: {result.claimed_complexity}")
238
+ else:
239
+ click.echo(f"❌ {result.file_path}")
240
+ if hasattr(result, 'claimed_complexity') and result.claimed_complexity:
241
+ click.echo(f" Claimed: {result.claimed_complexity}")
242
+ if hasattr(result, 'static_analysis') and result.static_analysis:
243
+ click.echo(f" Static Analysis: {result.static_analysis}")
244
+
245
+ if hasattr(result, 'warnings') and result.warnings:
246
+ for warning in result.warnings:
247
+ click.echo(f" Warning: {warning}")
248
+
249
+ if hasattr(result, 'suggestions') and result.suggestions:
250
+ for suggestion in result.suggestions:
251
+ click.echo(f" Suggestion: {suggestion}")
252
+
253
+ click.echo()
254
+
255
+
256
+ def display_json_results(
257
+ semantic_results: List[ValidationResult],
258
+ performance_results: List[PerformanceResult],
259
+ output: Optional[str]
260
+ ):
261
+ """Display results in JSON format."""
262
+ import json
263
+
264
+ # Convert results to dicts
265
+ semantic_dicts = []
266
+ for r in semantic_results:
267
+ semantic_dicts.append({
268
+ "file_path": r.file_path,
269
+ "is_valid": r.is_valid,
270
+ "missing_deps": list(r.missing_deps) if hasattr(r, 'missing_deps') else [],
271
+ "extra_deps": list(r.extra_deps) if hasattr(r, 'extra_deps') else [],
272
+ "errors": r.errors if hasattr(r, 'errors') else [],
273
+ "warnings": r.warnings if hasattr(r, 'warnings') else [],
274
+ "suggestions": r.suggestions if hasattr(r, 'suggestions') else [],
275
+ })
276
+
277
+ # Performance results
278
+ perf_dicts = []
279
+ for r in performance_results:
280
+ perf_dicts.append({
281
+ "file_path": r.file_path,
282
+ "is_valid": r.is_valid,
283
+ "claimed_complexity": str(r.claimed_complexity) if hasattr(r, 'claimed_complexity') else None,
284
+ "warnings": r.warnings if hasattr(r, 'warnings') else [],
285
+ "suggestions": r.suggestions if hasattr(r, 'suggestions') else [],
286
+ })
287
+
288
+ data = {
289
+ "semantic": semantic_dicts,
290
+ "performance": perf_dicts,
291
+ }
292
+
293
+ json_str = json.dumps(data, indent=2)
294
+
295
+ if output:
296
+ Path(output).write_text(json_str)
297
+ click.echo(f"Results written to: {output}")
298
+ else:
299
+ click.echo(json_str)
300
+
301
+
302
+ def display_html_results(
303
+ semantic_results: List[ValidationResult],
304
+ performance_results: List[PerformanceResult],
305
+ output: Optional[str]
306
+ ):
307
+ """Display results in HTML format."""
308
+ html = """
309
+ <!DOCTYPE html>
310
+ <html>
311
+ <head>
312
+ <title>VooDocs Validation Report</title>
313
+ <style>
314
+ body { font-family: Arial, sans-serif; margin: 20px; }
315
+ h1 { color: #333; }
316
+ .valid { color: green; }
317
+ .invalid { color: red; }
318
+ .file { margin: 10px 0; padding: 10px; border: 1px solid #ddd; }
319
+ </style>
320
+ </head>
321
+ <body>
322
+ <h1>VooDocs Validation Report</h1>
323
+
324
+ <h2>Semantic Validation</h2>
325
+ """
326
+
327
+ for result in semantic_results:
328
+ status = "valid" if result.is_valid else "invalid"
329
+ html += f'<div class="file {status}">\n'
330
+ html += f'<strong>{result.file_path}</strong>: {"✅ Valid" if result.is_valid else "❌ Invalid"}<br>\n'
331
+
332
+ if not result.is_valid:
333
+ if result.missing_deps:
334
+ html += f'Missing: {", ".join(sorted(result.missing_deps))}<br>\n'
335
+ if result.extra_deps:
336
+ html += f'Extra: {", ".join(sorted(result.extra_deps))}<br>\n'
337
+
338
+ html += '</div>\n'
339
+
340
+ html += """
341
+ <h2>Performance Validation</h2>
342
+ """
343
+
344
+ for result in performance_results:
345
+ status = "valid" if result.is_valid else "invalid"
346
+ html += f'<div class="file {status}">\n'
347
+ html += f'<strong>{result.file_path}</strong>: {"✅ Valid" if result.is_valid else "❌ Invalid"}<br>\n'
348
+ html += f'Claimed: {result.claimed_complexity}<br>\n'
349
+
350
+ if not result.is_valid:
351
+ html += f'Actual: {result.actual_complexity}<br>\n'
352
+
353
+ html += '</div>\n'
354
+
355
+ html += """
356
+ </body>
357
+ </html>
358
+ """
359
+
360
+ if output:
361
+ Path(output).write_text(html)
362
+ click.echo(f"Results written to: {output}")
363
+ else:
364
+ click.echo(html)
@@ -1,11 +1,17 @@
1
- """
2
- DarkArts: An execution engine for mathematical notation.
1
+ """@darkarts
2
+ ⊢init:lib.darkarts.package
3
+ ∂{}
4
+ ⚠{python≥3.7}
5
+ ⊨{∀import→exports-available,namespace:clean,¬side-effects-on-import}
6
+ 🔒{pure-init,¬io,¬network,¬exec}
7
+ ⚡{O(1):import-time}
8
+
9
+ Package initialization for lib.darkarts.
3
10
 
4
- DarkArts bridges the gap between AI's natural mathematical reasoning
5
- and computational reality, allowing AI to express solutions in mathematics
6
- while getting executable results without writing code.
11
+ Module exports and namespace configuration.
7
12
  """
8
13
 
14
+
9
15
  __version__ = "0.1.0-alpha"
10
16
  __author__ = "Vooodooo"
11
17
 
@@ -1,9 +1,17 @@
1
- """
2
- DarkArts Annotations
1
+ """@darkarts
2
+ ⊢init:annotations.package
3
+ ∂{}
4
+ ⚠{python≥3.7}
5
+ ⊨{∀import→exports-available,namespace:clean,¬side-effects-on-import}
6
+ 🔒{pure-init,¬io,¬network,¬exec}
7
+ ⚡{O(1):import-time}
8
+
9
+ Package initialization for annotations.
3
10
 
4
- AI-native code documentation system using mathematical and logical notation.
11
+ Module exports and namespace configuration.
5
12
  """
6
13
 
14
+
7
15
  from .types import (
8
16
  ParsedAnnotations,
9
17
  ModuleAnnotation,
@@ -4,7 +4,7 @@
4
4
  ⚠{@darkarts∈docstrings,unicode-support}
5
5
  ⊨{∀parse→structured-output,¬modify-src,handle-errors}
6
6
  🔒{read-only}
7
- ⚡{O(n)|n=annotation-length}
7
+ ⚡{O(n²)|n=annotation-length,4-loops,depth=2}
8
8
 
9
9
  DarkArts Annotation Parser
10
10
 
@@ -209,7 +209,7 @@ class DarkArtsTranslator:
209
209
  Returns:
210
210
  Symbolic notation
211
211
  """
212
- result = text.lower()
212
+ result = text
213
213
 
214
214
  # Replace English phrases with symbols
215
215
  # Sort by length (longest first) to avoid partial matches
@@ -217,7 +217,14 @@ class DarkArtsTranslator:
217
217
  key=lambda x: len(x[0]), reverse=True)
218
218
 
219
219
  for english, symbol in phrases:
220
- result = result.replace(english, symbol)
220
+ # Use word boundaries to avoid mid-word replacements
221
+ # This prevents "or" in "authenticated" from being replaced
222
+ pattern = r'\b' + re.escape(english) + r'\b'
223
+ try:
224
+ result = re.sub(pattern, symbol, result, flags=re.IGNORECASE)
225
+ except re.error:
226
+ # Fallback for patterns that don't work with word boundaries
227
+ pass
221
228
 
222
229
  return result
223
230
 
@@ -311,15 +318,35 @@ class DarkArtsTranslator:
311
318
  symbolic = [self._convert_invariant(inv) for inv in invariants]
312
319
  lines.append(f"⊨{{{','.join(symbolic)}}}")
313
320
 
321
+ # Preconditions
322
+ if 'preconditions' in voodocs_dict:
323
+ preconditions = voodocs_dict['preconditions']
324
+ if isinstance(preconditions, list):
325
+ symbolic = [self._convert_invariant(pre) for pre in preconditions]
326
+ lines.append(f"⊳{{{','.join(symbolic)}}}")
327
+
328
+ # Postconditions
329
+ if 'postconditions' in voodocs_dict:
330
+ postconditions = voodocs_dict['postconditions']
331
+ if isinstance(postconditions, list):
332
+ symbolic = [self._convert_invariant(post) for post in postconditions]
333
+ lines.append(f"⊲{{{','.join(symbolic)}}}")
334
+
314
335
  # Security
315
- if 'security_model' in voodocs_dict:
316
- security = self._simplify_text(voodocs_dict['security_model'])
336
+ if 'security_model' in voodocs_dict or 'security_implications' in voodocs_dict:
337
+ security = voodocs_dict.get('security_model') or voodocs_dict.get('security_implications')
338
+ if isinstance(security, list):
339
+ security = ', '.join(security)
340
+ security = self._simplify_text(str(security))
317
341
  lines.append(f"🔒{{{security}}}")
318
342
 
319
- # Performance
343
+ # Performance/Complexity
320
344
  if 'performance_model' in voodocs_dict:
321
345
  perf = voodocs_dict['performance_model']
322
346
  lines.append(f"⚡{{{perf}}}")
347
+ elif 'complexity' in voodocs_dict:
348
+ complexity = voodocs_dict['complexity']
349
+ lines.append(f"⚡{{{complexity}}}")
323
350
 
324
351
  lines.append('"""')
325
352
  return '\n'.join(lines)
@@ -1,7 +1,20 @@
1
- """
1
+ """@darkarts
2
+ ⊢annotation-types:annotations.data-structures
3
+ ∂{dataclasses,typing,enum}
4
+ ⚠{python≥3.7}
5
+ ⊨{∀dataclass:valid-schema,∀enum:valid-values,∀annotation:complete-representation,serializable:to-dict,multi-language:supported}
6
+ 🔒{pure-data,¬io,¬side-effects,¬exec}
7
+ ⚡{O(1):all-ops,lightweight-dataclasses}
8
+
2
9
  DarkArts Annotation Types
3
10
 
4
- Data structures for representing parsed DarkArts annotations.
11
+ Data structures for parsed @darkarts/@voodocs annotations with:
12
+ - Annotation types (function, method, class, module)
13
+ - Language support (Python, TypeScript, JavaScript, Java, C++, C#, Go, Rust)
14
+ - Complexity annotations (time, space, best/worst/average case)
15
+ - State transitions (from_state → to_state with conditions)
16
+ - Error cases (condition, error_type, description)
17
+ - Structured representations (FunctionAnnotation, ClassAnnotation, ModuleAnnotation)
5
18
  """
6
19
 
7
20
  from dataclasses import dataclass, field