@voodocs/cli 3.0.1 → 3.0.2

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.
@@ -16,7 +16,7 @@ This module provides the command-line interface for VooDocs.
16
16
  import click
17
17
  from typing import Optional
18
18
 
19
- __version__ = "3.0.1"
19
+ __version__ = "3.0.2"
20
20
 
21
21
 
22
22
  @click.group()
@@ -110,6 +110,47 @@ def generate(
110
110
  click.echo(f"Recursive: {click.style('Yes', fg='green')}")
111
111
  click.echo()
112
112
 
113
+ # Default exclusion patterns
114
+ DEFAULT_EXCLUDE_PATTERNS = [
115
+ '**/node_modules/**',
116
+ '**/venv/**',
117
+ '**/.venv/**',
118
+ '**/env/**',
119
+ '**/.env/**',
120
+ '**/virtualenv/**',
121
+ '**/__pycache__/**',
122
+ '**/.git/**',
123
+ '**/.svn/**',
124
+ '**/.hg/**',
125
+ '**/dist/**',
126
+ '**/build/**',
127
+ '**/.next/**',
128
+ '**/.nuxt/**',
129
+ '**/coverage/**',
130
+ '**/.pytest_cache/**',
131
+ '**/.mypy_cache/**',
132
+ '**/.tox/**',
133
+ '**/site-packages/**',
134
+ ]
135
+
136
+ def should_exclude(file_path: Path, exclude_patterns: List[str]) -> bool:
137
+ """Check if file should be excluded based on patterns."""
138
+ file_str = str(file_path)
139
+ for pattern in exclude_patterns:
140
+ # Convert glob pattern to simple string matching
141
+ # Handle ** patterns
142
+ pattern_parts = pattern.split('**')
143
+ if len(pattern_parts) > 1:
144
+ # Pattern contains **, check if any part matches
145
+ for part in pattern_parts:
146
+ if part and part.strip('/') in file_str:
147
+ return True
148
+ else:
149
+ # Simple pattern matching
150
+ if pattern.strip('*').strip('/') in file_str:
151
+ return True
152
+ return False
153
+
113
154
  # Collect source files
114
155
  source_path = Path(source)
115
156
  files_to_process: List[Path] = []
@@ -123,7 +164,10 @@ def generate(
123
164
 
124
165
  if recursive:
125
166
  for ext in extensions:
126
- files_to_process.extend([f for f in source_path.glob(f"**/{ext}") if f.is_file()])
167
+ all_files = source_path.glob(f"**/{ext}")
168
+ # Filter out excluded paths
169
+ filtered_files = [f for f in all_files if f.is_file() and not should_exclude(f, DEFAULT_EXCLUDE_PATTERNS)]
170
+ files_to_process.extend(filtered_files)
127
171
  else:
128
172
  for ext in extensions:
129
173
  files_to_process.extend([f for f in source_path.glob(ext) if f.is_file()])
@@ -1214,19 +1214,44 @@ def cmd_context_generate(source_dir: Optional[str] = None, update_existing: bool
1214
1214
  sys.path.insert(0, str(Path(__file__).parent.parent))
1215
1215
  from annotations.parser import AnnotationParser
1216
1216
 
1217
- # Scan for annotations
1217
+ # Initialize parser
1218
1218
  parser = AnnotationParser()
1219
+
1220
+ # Check for PROJECT.darkarts.md file
1221
+ project_file = scan_path / 'PROJECT.darkarts.md'
1222
+ project_annotations = None
1223
+ if project_file.exists():
1224
+ info(f"Found PROJECT.darkarts.md")
1225
+ try:
1226
+ project_annotations = parser.parse_file(str(project_file))
1227
+ except Exception as e:
1228
+ warning(f"Failed to parse PROJECT.darkarts.md: {e}")
1229
+
1230
+ # Scan for annotations
1219
1231
  results = parser.parse_directory(scan_path)
1220
1232
 
1221
- if not results:
1233
+ if not results and not project_annotations:
1222
1234
  warning("No @darkarts annotations found.")
1223
- info("Add @darkarts annotations to your code first.")
1235
+ info("Add @darkarts annotations to your code or create PROJECT.darkarts.md")
1224
1236
  return 1
1225
1237
 
1226
1238
  # Extract global invariants from all annotations
1227
1239
  global_invariants = set()
1228
1240
  assumptions = []
1229
1241
 
1242
+ # Process PROJECT.darkarts.md if it exists
1243
+ if project_annotations:
1244
+ module_ann = project_annotations.module
1245
+ if hasattr(module_ann, 'invariants') and module_ann.invariants:
1246
+ for inv in module_ann.invariants:
1247
+ global_invariants.add(inv)
1248
+ if hasattr(module_ann, 'assumptions') and module_ann.assumptions:
1249
+ for assumption in module_ann.assumptions:
1250
+ assumptions.append({
1251
+ 'description': assumption,
1252
+ 'source': 'PROJECT.darkarts.md'
1253
+ })
1254
+
1230
1255
  # Extract modules using helper function
1231
1256
  modules_info = extract_modules_from_results(results, scan_path)
1232
1257
 
@@ -423,6 +423,46 @@ def format_context_as_markdown(context: ContextFile) -> str:
423
423
  lines.append("---")
424
424
  lines.append("")
425
425
 
426
+ # Modules
427
+ if context.architecture.modules:
428
+ lines.append("## 📦 Modules")
429
+ lines.append("")
430
+ lines.append(f"Total modules: {len(context.architecture.modules)}")
431
+ lines.append("")
432
+ for name, module in context.architecture.modules.items():
433
+ lines.append(f"### {name}")
434
+ lines.append("")
435
+ if module.description:
436
+ lines.append(f"**Description:** {module.description}")
437
+ lines.append("")
438
+ if module.dependencies:
439
+ lines.append(f"**Dependencies:** {', '.join(module.dependencies)}")
440
+ lines.append("")
441
+ if module.assumptions:
442
+ lines.append("**Assumptions:**")
443
+ for assumption in module.assumptions:
444
+ lines.append(f"- {assumption}")
445
+ lines.append("")
446
+ if module.invariants:
447
+ lines.append("**Invariants:**")
448
+ for invariant in module.invariants:
449
+ lines.append(f"- {invariant}")
450
+ lines.append("")
451
+ lines.append("---")
452
+ lines.append("")
453
+
454
+ # Assumptions
455
+ if context.assumptions:
456
+ lines.append("## ⚠️ Assumptions")
457
+ lines.append("")
458
+ lines.append(f"Total assumptions: {len(context.assumptions)}")
459
+ lines.append("")
460
+ for assumption in context.assumptions:
461
+ lines.append(f"- {assumption}")
462
+ lines.append("")
463
+ lines.append("---")
464
+ lines.append("")
465
+
426
466
  # Known Issues
427
467
  if context.known_issues:
428
468
  lines.append("## ⚠️ Known Issues")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voodocs/cli",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "AI-Native Symbolic Documentation System - The world's first documentation tool using mathematical notation with semantic validation",
5
5
  "main": "voodocs_cli.py",
6
6
  "bin": {
@@ -0,0 +1,128 @@
1
+ # Project-Level DarkArts Annotations
2
+
3
+ This file contains project-wide annotations that apply to the entire codebase.
4
+
5
+ ## Usage
6
+
7
+ Place this file in your project root as `PROJECT.darkarts.md` and it will be automatically detected by `voodocs context generate`.
8
+
9
+ ## Syntax
10
+
11
+ Use standard @darkarts symbolic notation:
12
+
13
+ ```
14
+ @darkarts
15
+ ⊢{project purpose}
16
+ ⊨{global invariants}
17
+ ⊣{system-wide assumptions}
18
+ ⚠{technology requirements}
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Example: Project-Level Annotations
24
+
25
+ ```markdown
26
+ @darkarts
27
+ ⊢{distributed microservices platform for AI-powered financial services}
28
+
29
+ ⊨{
30
+ ∀service→isolated-db,
31
+ ∀api→authenticated,
32
+ ∀transaction→idempotent,
33
+ ∀data→encrypted-at-rest,
34
+ consistency:eventual
35
+ }
36
+
37
+ ⊣{
38
+ postgres≥14 available,
39
+ redis cluster available,
40
+ kubernetes cluster available,
41
+ all services use UTC timestamps,
42
+ all APIs use JSON
43
+ }
44
+
45
+ ⚠{
46
+ kubernetes≥1.24,
47
+ postgres≥14,
48
+ redis≥7.0,
49
+ node≥18,
50
+ python≥3.11
51
+ }
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Architecture Decisions
57
+
58
+ You can also document architecture decisions in plain Markdown:
59
+
60
+ ### Decision: Event-Driven Architecture
61
+
62
+ **Rationale:** Enables loose coupling between services and supports eventual consistency model.
63
+
64
+ **Alternatives Considered:**
65
+ - Synchronous REST APIs (rejected: tight coupling, cascading failures)
66
+ - GraphQL federation (rejected: complexity overhead)
67
+
68
+ **Trade-offs:**
69
+ - ✅ Better scalability and resilience
70
+ - ✅ Easier to add new services
71
+ - ❌ More complex debugging
72
+ - ❌ Requires event schema management
73
+
74
+ ---
75
+
76
+ ## Global Invariants
77
+
78
+ Document system-wide invariants that must hold across all services:
79
+
80
+ - All user data must be encrypted at rest
81
+ - All API endpoints must require authentication
82
+ - All database transactions must be idempotent
83
+ - All timestamps must use UTC
84
+ - All monetary amounts must use decimal types (never float)
85
+
86
+ ---
87
+
88
+ ## System-Wide Assumptions
89
+
90
+ Document assumptions that the entire system relies on:
91
+
92
+ - PostgreSQL is always available (99.9% SLA)
93
+ - Redis is used only for caching (not source of truth)
94
+ - All services can communicate via internal network
95
+ - Clock skew between services is < 1 second
96
+ - All services use the same authentication service
97
+
98
+ ---
99
+
100
+ ## Technology Stack
101
+
102
+ Document the standard technology stack for the project:
103
+
104
+ **Backend:**
105
+ - Node.js 18+ (TypeScript)
106
+ - Python 3.11+ (FastAPI)
107
+ - PostgreSQL 14+
108
+ - Redis 7.0+
109
+
110
+ **Frontend:**
111
+ - React 18+
112
+ - TypeScript 5+
113
+ - TailwindCSS 3+
114
+
115
+ **Infrastructure:**
116
+ - Kubernetes 1.24+
117
+ - Docker
118
+ - GitHub Actions (CI/CD)
119
+
120
+ ---
121
+
122
+ ## Notes
123
+
124
+ - This file is parsed by `voodocs context generate`
125
+ - Annotations in this file are added to the `.voodocs.context` file
126
+ - Global invariants from this file appear in the "Global Invariants" section
127
+ - Architecture decisions can be written in plain Markdown
128
+ - This file should be version controlled alongside your code