@voodocs/cli 3.0.1 → 3.0.3
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.
package/lib/cli/__init__.py
CHANGED
package/lib/cli/generate.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
#
|
|
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
|
|
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,47 @@ 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.path:
|
|
439
|
+
lines.append(f"**Path:** {module.path}")
|
|
440
|
+
lines.append("")
|
|
441
|
+
if module.language:
|
|
442
|
+
lines.append(f"**Language:** {module.language}")
|
|
443
|
+
lines.append("")
|
|
444
|
+
if module.dependencies:
|
|
445
|
+
lines.append(f"**Dependencies:** {', '.join(module.dependencies)}")
|
|
446
|
+
lines.append("")
|
|
447
|
+
if module.public_api:
|
|
448
|
+
lines.append("**Public API:**")
|
|
449
|
+
for api in module.public_api:
|
|
450
|
+
lines.append(f"- {api}")
|
|
451
|
+
lines.append("")
|
|
452
|
+
lines.append("---")
|
|
453
|
+
lines.append("")
|
|
454
|
+
|
|
455
|
+
# Assumptions
|
|
456
|
+
if context.assumptions:
|
|
457
|
+
lines.append("## ⚠️ Assumptions")
|
|
458
|
+
lines.append("")
|
|
459
|
+
lines.append(f"Total assumptions: {len(context.assumptions)}")
|
|
460
|
+
lines.append("")
|
|
461
|
+
for assumption in context.assumptions:
|
|
462
|
+
lines.append(f"- {assumption}")
|
|
463
|
+
lines.append("")
|
|
464
|
+
lines.append("---")
|
|
465
|
+
lines.append("")
|
|
466
|
+
|
|
426
467
|
# Known Issues
|
|
427
468
|
if context.known_issues:
|
|
428
469
|
lines.append("## ⚠️ Known Issues")
|
package/package.json
CHANGED
|
@@ -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
|