@voodocs/cli 0.1.0
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/LICENSE +37 -0
- package/README.md +153 -0
- package/USAGE.md +314 -0
- package/cli.py +1340 -0
- package/examples/.cursorrules +437 -0
- package/examples/instructions/.claude/instructions.md +372 -0
- package/examples/instructions/.cursorrules +437 -0
- package/examples/instructions/.windsurfrules +437 -0
- package/examples/instructions/VOODOCS_INSTRUCTIONS.md +437 -0
- package/examples/math_example.py +41 -0
- package/examples/phase2_test.py +24 -0
- package/examples/test_compound_conditions.py +40 -0
- package/examples/test_math_example.py +186 -0
- package/lib/darkarts/README.md +115 -0
- package/lib/darkarts/__init__.py +16 -0
- package/lib/darkarts/annotations/__init__.py +34 -0
- package/lib/darkarts/annotations/parser.py +618 -0
- package/lib/darkarts/annotations/types.py +181 -0
- package/lib/darkarts/cli.py +128 -0
- package/lib/darkarts/core/__init__.py +32 -0
- package/lib/darkarts/core/interface.py +256 -0
- package/lib/darkarts/core/loader.py +231 -0
- package/lib/darkarts/core/plugin.py +215 -0
- package/lib/darkarts/core/registry.py +146 -0
- package/lib/darkarts/exceptions.py +51 -0
- package/lib/darkarts/parsers/typescript/dist/cli.d.ts +9 -0
- package/lib/darkarts/parsers/typescript/dist/cli.d.ts.map +1 -0
- package/lib/darkarts/parsers/typescript/dist/cli.js +69 -0
- package/lib/darkarts/parsers/typescript/dist/cli.js.map +1 -0
- package/lib/darkarts/parsers/typescript/dist/parser.d.ts +111 -0
- package/lib/darkarts/parsers/typescript/dist/parser.d.ts.map +1 -0
- package/lib/darkarts/parsers/typescript/dist/parser.js +365 -0
- package/lib/darkarts/parsers/typescript/dist/parser.js.map +1 -0
- package/lib/darkarts/parsers/typescript/package-lock.json +51 -0
- package/lib/darkarts/parsers/typescript/package.json +19 -0
- package/lib/darkarts/parsers/typescript/src/cli.ts +41 -0
- package/lib/darkarts/parsers/typescript/src/parser.ts +408 -0
- package/lib/darkarts/parsers/typescript/tsconfig.json +19 -0
- package/lib/darkarts/plugins/voodocs/__init__.py +379 -0
- package/lib/darkarts/plugins/voodocs/ai_native_plugin.py +151 -0
- package/lib/darkarts/plugins/voodocs/annotation_validator.py +280 -0
- package/lib/darkarts/plugins/voodocs/api_spec_generator.py +486 -0
- package/lib/darkarts/plugins/voodocs/documentation_generator.py +610 -0
- package/lib/darkarts/plugins/voodocs/html_exporter.py +260 -0
- package/lib/darkarts/plugins/voodocs/instruction_generator.py +706 -0
- package/lib/darkarts/plugins/voodocs/pdf_exporter.py +66 -0
- package/lib/darkarts/plugins/voodocs/test_generator.py +636 -0
- package/package.json +70 -0
- package/requirements.txt +13 -0
- package/templates/ci/github-actions.yml +73 -0
- package/templates/ci/gitlab-ci.yml +35 -0
- package/templates/ci/pre-commit-hook.sh +26 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
"""
|
|
2
|
+
VooDocs AI Instruction Generator
|
|
3
|
+
|
|
4
|
+
Generates instruction files that teach AI coding assistants (Cursor, Claude Code, etc.)
|
|
5
|
+
how to use @voodocs annotations while writing code.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Optional, Dict, List
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InstructionGenerator:
|
|
14
|
+
"""Generates AI assistant instruction files for VooDocs."""
|
|
15
|
+
|
|
16
|
+
# Supported AI assistants
|
|
17
|
+
ASSISTANTS = {
|
|
18
|
+
"cursor": {
|
|
19
|
+
"name": "Cursor",
|
|
20
|
+
"config_file": ".cursorrules",
|
|
21
|
+
"format": "markdown"
|
|
22
|
+
},
|
|
23
|
+
"claude": {
|
|
24
|
+
"name": "Claude Code / Cline",
|
|
25
|
+
"config_file": ".claude/instructions.md",
|
|
26
|
+
"format": "markdown"
|
|
27
|
+
},
|
|
28
|
+
"copilot": {
|
|
29
|
+
"name": "GitHub Copilot",
|
|
30
|
+
"config_file": ".github/copilot-instructions.md",
|
|
31
|
+
"format": "markdown"
|
|
32
|
+
},
|
|
33
|
+
"windsurf": {
|
|
34
|
+
"name": "Windsurf",
|
|
35
|
+
"config_file": ".windsurfrules",
|
|
36
|
+
"format": "markdown"
|
|
37
|
+
},
|
|
38
|
+
"generic": {
|
|
39
|
+
"name": "Generic AI Assistant",
|
|
40
|
+
"config_file": "VOODOCS_INSTRUCTIONS.md",
|
|
41
|
+
"format": "markdown"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
def __init__(self, assistant: str = "generic", project_name: str = "Your Project"):
|
|
46
|
+
"""
|
|
47
|
+
Initialize instruction generator.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
assistant: AI assistant type ("cursor", "claude", "copilot", "windsurf", "generic")
|
|
51
|
+
project_name: Name of the project for personalization
|
|
52
|
+
"""
|
|
53
|
+
if assistant not in self.ASSISTANTS:
|
|
54
|
+
raise ValueError(f"Unsupported assistant: {assistant}. Choose from: {list(self.ASSISTANTS.keys())}")
|
|
55
|
+
|
|
56
|
+
self.assistant = assistant
|
|
57
|
+
self.assistant_info = self.ASSISTANTS[assistant]
|
|
58
|
+
self.project_name = project_name
|
|
59
|
+
|
|
60
|
+
def generate(self, output_file: Optional[str] = None, language: str = "python") -> str:
|
|
61
|
+
"""
|
|
62
|
+
Generate instruction file for the AI assistant.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
output_file: Optional output file path (defaults to assistant's config file)
|
|
66
|
+
language: Primary programming language ("python", "typescript", "javascript")
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Generated instruction content
|
|
70
|
+
"""
|
|
71
|
+
instructions = self._generate_instructions(language)
|
|
72
|
+
|
|
73
|
+
# Determine output file
|
|
74
|
+
if output_file is None:
|
|
75
|
+
output_file = self.assistant_info["config_file"]
|
|
76
|
+
|
|
77
|
+
# Write to file
|
|
78
|
+
output_path = Path(output_file)
|
|
79
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
output_path.write_text(instructions, encoding='utf-8')
|
|
81
|
+
|
|
82
|
+
return instructions
|
|
83
|
+
|
|
84
|
+
def _generate_instructions(self, language: str) -> str:
|
|
85
|
+
"""Generate the instruction content."""
|
|
86
|
+
sections = []
|
|
87
|
+
|
|
88
|
+
# Header
|
|
89
|
+
sections.append(self._generate_header())
|
|
90
|
+
|
|
91
|
+
# Overview
|
|
92
|
+
sections.append(self._generate_overview())
|
|
93
|
+
|
|
94
|
+
# Core principles
|
|
95
|
+
sections.append(self._generate_core_principles())
|
|
96
|
+
|
|
97
|
+
# Annotation syntax
|
|
98
|
+
sections.append(self._generate_annotation_syntax(language))
|
|
99
|
+
|
|
100
|
+
# Annotation fields
|
|
101
|
+
sections.append(self._generate_annotation_fields())
|
|
102
|
+
|
|
103
|
+
# DarkArts language guide
|
|
104
|
+
sections.append(self._generate_darkarts_guide())
|
|
105
|
+
|
|
106
|
+
# Examples
|
|
107
|
+
sections.append(self._generate_examples(language))
|
|
108
|
+
|
|
109
|
+
# Workflow integration
|
|
110
|
+
sections.append(self._generate_workflow())
|
|
111
|
+
|
|
112
|
+
# Best practices
|
|
113
|
+
sections.append(self._generate_best_practices())
|
|
114
|
+
|
|
115
|
+
# Footer
|
|
116
|
+
sections.append(self._generate_footer())
|
|
117
|
+
|
|
118
|
+
return "\n\n".join(sections)
|
|
119
|
+
|
|
120
|
+
def _generate_header(self) -> str:
|
|
121
|
+
"""Generate instruction header."""
|
|
122
|
+
return f"""# VooDocs Instructions for {self.assistant_info['name']}
|
|
123
|
+
|
|
124
|
+
**Project**: {self.project_name}
|
|
125
|
+
**Generated**: Automatically by VooDocs
|
|
126
|
+
**Purpose**: Guide AI assistants to document code using @voodocs annotations
|
|
127
|
+
|
|
128
|
+
---"""
|
|
129
|
+
|
|
130
|
+
def _generate_overview(self) -> str:
|
|
131
|
+
"""Generate overview section."""
|
|
132
|
+
return """## Overview
|
|
133
|
+
|
|
134
|
+
VooDocs is an AI-native documentation system that allows you to document code in **DarkArts language** - a mathematical and logical notation that AI naturally understands. Your annotations will be automatically translated into human-readable documentation, property-based tests, and API specifications.
|
|
135
|
+
|
|
136
|
+
**Key Benefits:**
|
|
137
|
+
- Document in AI's native language (mathematical notation)
|
|
138
|
+
- Automatic generation of comprehensive tests
|
|
139
|
+
- Property-based testing with Hypothesis
|
|
140
|
+
- OpenAPI/GraphQL spec generation
|
|
141
|
+
- Human-readable documentation output
|
|
142
|
+
|
|
143
|
+
**Your Role:**
|
|
144
|
+
As an AI coding assistant, you should add `@voodocs` annotations to **every significant function, class, and module** you write. Think of it as "documentation-driven development" where you specify the contract first."""
|
|
145
|
+
|
|
146
|
+
def _generate_core_principles(self) -> str:
|
|
147
|
+
"""Generate core principles section."""
|
|
148
|
+
return """## Core Principles
|
|
149
|
+
|
|
150
|
+
When writing code with VooDocs annotations, follow these principles:
|
|
151
|
+
|
|
152
|
+
1. **Annotate as you code** - Add `@voodocs` annotations immediately when creating functions/classes
|
|
153
|
+
2. **Be precise** - Use mathematical notation for exact specifications
|
|
154
|
+
3. **Think in contracts** - Define preconditions, postconditions, and invariants
|
|
155
|
+
4. **Specify complexity** - Always include time/space complexity
|
|
156
|
+
5. **Document security** - Note security implications and assumptions
|
|
157
|
+
6. **Fail-safe design** - Specify error cases and how they're handled"""
|
|
158
|
+
|
|
159
|
+
def _generate_annotation_syntax(self, language: str) -> str:
|
|
160
|
+
"""Generate annotation syntax section."""
|
|
161
|
+
if language == "python":
|
|
162
|
+
return """## Annotation Syntax (Python)
|
|
163
|
+
|
|
164
|
+
Place `@voodocs` annotations in docstrings:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
def function_name(param1: type, param2: type) -> return_type:
|
|
168
|
+
\"\"\"@voodocs
|
|
169
|
+
preconditions: ["param1 > 0", "param2 is not None"]
|
|
170
|
+
postconditions: ["result >= param1"]
|
|
171
|
+
complexity: "O(n)"
|
|
172
|
+
\"\"\"
|
|
173
|
+
# Implementation
|
|
174
|
+
pass
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
For classes:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
class ClassName:
|
|
181
|
+
\"\"\"@voodocs
|
|
182
|
+
class_invariants: ["∀ item ∈ self.items: item.is_valid()"]
|
|
183
|
+
state_transitions: ["IDLE → PROCESSING", "PROCESSING → COMPLETE"]
|
|
184
|
+
\"\"\"
|
|
185
|
+
pass
|
|
186
|
+
```"""
|
|
187
|
+
|
|
188
|
+
elif language in ["typescript", "javascript"]:
|
|
189
|
+
return """## Annotation Syntax (TypeScript/JavaScript)
|
|
190
|
+
|
|
191
|
+
Place `@voodocs` annotations in JSDoc-style comments:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
/**@voodocs
|
|
195
|
+
preconditions: ["amount > 0", "account.isActive()"]
|
|
196
|
+
postconditions: ["account.balance decreased by amount"]
|
|
197
|
+
complexity: "O(1)"
|
|
198
|
+
security_implications: ["Requires authentication", "Validates account ownership"]
|
|
199
|
+
*/
|
|
200
|
+
function withdraw(account: Account, amount: number): boolean {
|
|
201
|
+
// Implementation
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
For classes:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
/**@voodocs
|
|
209
|
+
class_invariants: ["this.balance >= 0", "this.transactions.length >= 0"]
|
|
210
|
+
state_transitions: ["PENDING → ACTIVE", "ACTIVE → SUSPENDED", "SUSPENDED → CLOSED"]
|
|
211
|
+
*/
|
|
212
|
+
class BankAccount {
|
|
213
|
+
// Implementation
|
|
214
|
+
}
|
|
215
|
+
```"""
|
|
216
|
+
|
|
217
|
+
else:
|
|
218
|
+
return """## Annotation Syntax
|
|
219
|
+
|
|
220
|
+
Use language-appropriate comment syntax with `@voodocs` marker."""
|
|
221
|
+
|
|
222
|
+
def _generate_annotation_fields(self) -> str:
|
|
223
|
+
"""Generate annotation fields reference."""
|
|
224
|
+
return """## Annotation Fields Reference
|
|
225
|
+
|
|
226
|
+
### For Functions/Methods
|
|
227
|
+
|
|
228
|
+
| Field | Required | Description | Example |
|
|
229
|
+
|-------|----------|-------------|---------|
|
|
230
|
+
| `preconditions` | Recommended | Conditions that must be true before execution | `["x > 0", "user is authenticated"]` |
|
|
231
|
+
| `postconditions` | Recommended | Conditions guaranteed after execution | `["result > 0", "database updated"]` |
|
|
232
|
+
| `complexity` | Recommended | Time/space complexity | `"O(n log n)"` or `"O(n)"` |
|
|
233
|
+
| `invariants` | Optional | Properties that remain unchanged | `["∀ x: x ∈ original_set ⇒ x ∈ result_set"]` |
|
|
234
|
+
| `error_cases` | Optional | Error conditions and exceptions | `["x < 0 → ValueError", "file not found → FileNotFoundError"]` |
|
|
235
|
+
| `side_effects` | Optional | External changes made | `["Writes to database", "Sends email"]` |
|
|
236
|
+
| `security_implications` | Optional | Security considerations | `["Requires admin role", "Rate limited"]` |
|
|
237
|
+
| `assumptions` | Optional | Environmental assumptions | `["Database is available", "Network is stable"]` |
|
|
238
|
+
|
|
239
|
+
### For Classes
|
|
240
|
+
|
|
241
|
+
| Field | Description | Example |
|
|
242
|
+
|-------|-------------|---------|
|
|
243
|
+
| `class_invariants` | Properties that always hold | `["∀ item ∈ queue: item.status ∈ VALID_STATUSES"]` |
|
|
244
|
+
| `state_transitions` | Valid state changes | `["IDLE → PROCESSING", "PROCESSING → COMPLETE"]` |
|
|
245
|
+
| `thread_safety` | Concurrency safety | `"Thread-safe with mutex"` or `"Not thread-safe"` |
|
|
246
|
+
|
|
247
|
+
### For Modules
|
|
248
|
+
|
|
249
|
+
| Field | Description | Example |
|
|
250
|
+
|-------|-------------|---------|
|
|
251
|
+
| `module_purpose` | High-level module description | `"User authentication and authorization"` |
|
|
252
|
+
| `dependencies` | External dependencies | `["@supabase/supabase-js", "bcrypt"]` |
|
|
253
|
+
| `assumptions` | Module-level assumptions | `["Database schema v2.0", "Redis available"]` |
|
|
254
|
+
| `security_model` | Overall security approach | `"Defense in depth - fails closed"` |"""
|
|
255
|
+
|
|
256
|
+
def _generate_darkarts_guide(self) -> str:
|
|
257
|
+
"""Generate DarkArts language guide."""
|
|
258
|
+
return """## DarkArts Language Guide
|
|
259
|
+
|
|
260
|
+
DarkArts is a mathematical notation language for precise specifications. Use these symbols:
|
|
261
|
+
|
|
262
|
+
### Logical Operators
|
|
263
|
+
|
|
264
|
+
| Symbol | Meaning | Example |
|
|
265
|
+
|--------|---------|---------|
|
|
266
|
+
| `∧` | AND | `x > 0 ∧ y > 0` |
|
|
267
|
+
| `∨` | OR | `x = 0 ∨ y = 0` |
|
|
268
|
+
| `¬` | NOT | `¬(x < 0)` |
|
|
269
|
+
| `⇒` | IMPLIES | `x > 0 ⇒ result > 0` |
|
|
270
|
+
| `⇔` | IF AND ONLY IF | `result = true ⇔ user.isAdmin` |
|
|
271
|
+
|
|
272
|
+
### Quantifiers
|
|
273
|
+
|
|
274
|
+
| Symbol | Meaning | Example |
|
|
275
|
+
|--------|---------|---------|
|
|
276
|
+
| `∀` | FOR ALL | `∀ x ∈ items: x > 0` |
|
|
277
|
+
| `∃` | THERE EXISTS | `∃ x ∈ items: x = target` |
|
|
278
|
+
|
|
279
|
+
### Set Operations
|
|
280
|
+
|
|
281
|
+
| Symbol | Meaning | Example |
|
|
282
|
+
|--------|---------|---------|
|
|
283
|
+
| `∈` | IN / ELEMENT OF | `x ∈ valid_values` |
|
|
284
|
+
| `∉` | NOT IN | `x ∉ blacklist` |
|
|
285
|
+
| `⊆` | SUBSET OF | `result ⊆ input` |
|
|
286
|
+
| `∪` | UNION | `result = set1 ∪ set2` |
|
|
287
|
+
| `∩` | INTERSECTION | `common = set1 ∩ set2` |
|
|
288
|
+
|
|
289
|
+
### Comparisons
|
|
290
|
+
|
|
291
|
+
| Symbol | Meaning | Example |
|
|
292
|
+
|--------|---------|---------|
|
|
293
|
+
| `≥` | GREATER THAN OR EQUAL | `x ≥ 0` |
|
|
294
|
+
| `≤` | LESS THAN OR EQUAL | `x ≤ 100` |
|
|
295
|
+
| `≠` | NOT EQUAL | `x ≠ 0` |
|
|
296
|
+
| `≈` | APPROXIMATELY EQUAL | `result ≈ expected` |
|
|
297
|
+
|
|
298
|
+
### Number Sets
|
|
299
|
+
|
|
300
|
+
| Symbol | Meaning | Example |
|
|
301
|
+
|--------|---------|---------|
|
|
302
|
+
| `ℕ` | Natural numbers (0, 1, 2, ...) | `n ∈ ℕ` |
|
|
303
|
+
| `ℤ` | Integers (..., -1, 0, 1, ...) | `x ∈ ℤ` |
|
|
304
|
+
| `ℝ` | Real numbers | `x ∈ ℝ` |
|
|
305
|
+
|
|
306
|
+
**Tip**: You can use plain English too! VooDocs understands both mathematical notation and natural language. Mix them for clarity."""
|
|
307
|
+
|
|
308
|
+
def _generate_examples(self, language: str) -> str:
|
|
309
|
+
"""Generate example annotations."""
|
|
310
|
+
if language == "python":
|
|
311
|
+
return """## Examples
|
|
312
|
+
|
|
313
|
+
### Example 1: Simple Function
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
def calculate_discount(price: float, discount_percent: float) -> float:
|
|
317
|
+
\"\"\"@voodocs
|
|
318
|
+
preconditions: [
|
|
319
|
+
"price > 0",
|
|
320
|
+
"discount_percent >= 0",
|
|
321
|
+
"discount_percent <= 100"
|
|
322
|
+
]
|
|
323
|
+
postconditions: [
|
|
324
|
+
"result >= 0",
|
|
325
|
+
"result <= price",
|
|
326
|
+
"result = price * (1 - discount_percent/100)"
|
|
327
|
+
]
|
|
328
|
+
complexity: "O(1)"
|
|
329
|
+
error_cases: [
|
|
330
|
+
"price <= 0 → ValueError",
|
|
331
|
+
"discount_percent < 0 → ValueError",
|
|
332
|
+
"discount_percent > 100 → ValueError"
|
|
333
|
+
]
|
|
334
|
+
\"\"\"
|
|
335
|
+
if price <= 0:
|
|
336
|
+
raise ValueError("Price must be positive")
|
|
337
|
+
if not 0 <= discount_percent <= 100:
|
|
338
|
+
raise ValueError("Discount must be between 0 and 100")
|
|
339
|
+
|
|
340
|
+
return price * (1 - discount_percent / 100)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Example 2: Function with Security
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
def delete_user(user_id: str, admin_token: str) -> bool:
|
|
347
|
+
\"\"\"@voodocs
|
|
348
|
+
preconditions: [
|
|
349
|
+
"user_id is valid UUID",
|
|
350
|
+
"admin_token is valid JWT",
|
|
351
|
+
"admin has 'delete_user' permission"
|
|
352
|
+
]
|
|
353
|
+
postconditions: [
|
|
354
|
+
"returns true ⇔ user deleted successfully",
|
|
355
|
+
"returns false ⇔ user not found ∨ permission denied"
|
|
356
|
+
]
|
|
357
|
+
security_implications: [
|
|
358
|
+
"Requires admin authentication",
|
|
359
|
+
"Logs deletion for audit trail",
|
|
360
|
+
"Soft delete - data retained for 30 days"
|
|
361
|
+
]
|
|
362
|
+
side_effects: [
|
|
363
|
+
"Writes to audit log",
|
|
364
|
+
"Sends notification email",
|
|
365
|
+
"Invalidates user sessions"
|
|
366
|
+
]
|
|
367
|
+
complexity: "O(1)"
|
|
368
|
+
\"\"\"
|
|
369
|
+
# Implementation
|
|
370
|
+
pass
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Example 3: Class with Invariants
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
class BankAccount:
|
|
377
|
+
\"\"\"@voodocs
|
|
378
|
+
class_invariants: [
|
|
379
|
+
"self.balance >= 0",
|
|
380
|
+
"len(self.transactions) >= 0",
|
|
381
|
+
"∀ tx ∈ self.transactions: tx.amount ≠ 0"
|
|
382
|
+
]
|
|
383
|
+
state_transitions: [
|
|
384
|
+
"PENDING → ACTIVE: when KYC verified",
|
|
385
|
+
"ACTIVE → FROZEN: when suspicious activity detected",
|
|
386
|
+
"FROZEN → ACTIVE: when investigation cleared",
|
|
387
|
+
"ACTIVE → CLOSED: when user requests closure"
|
|
388
|
+
]
|
|
389
|
+
thread_safety: "Thread-safe with account-level mutex"
|
|
390
|
+
\"\"\"
|
|
391
|
+
|
|
392
|
+
def __init__(self, account_id: str):
|
|
393
|
+
self.balance = 0.0
|
|
394
|
+
self.transactions = []
|
|
395
|
+
self.status = "PENDING"
|
|
396
|
+
|
|
397
|
+
def deposit(self, amount: float) -> bool:
|
|
398
|
+
\"\"\"@voodocs
|
|
399
|
+
preconditions: [
|
|
400
|
+
"amount > 0",
|
|
401
|
+
"self.status = ACTIVE"
|
|
402
|
+
]
|
|
403
|
+
postconditions: [
|
|
404
|
+
"self.balance = old(self.balance) + amount",
|
|
405
|
+
"len(self.transactions) = old(len(self.transactions)) + 1"
|
|
406
|
+
]
|
|
407
|
+
invariants: [
|
|
408
|
+
"self.balance >= 0"
|
|
409
|
+
]
|
|
410
|
+
complexity: "O(1)"
|
|
411
|
+
\"\"\"
|
|
412
|
+
# Implementation
|
|
413
|
+
pass
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Example 4: Algorithm with Complexity
|
|
417
|
+
|
|
418
|
+
```python
|
|
419
|
+
def quicksort(arr: list[int]) -> list[int]:
|
|
420
|
+
\"\"\"@voodocs
|
|
421
|
+
preconditions: [
|
|
422
|
+
"arr is list of integers"
|
|
423
|
+
]
|
|
424
|
+
postconditions: [
|
|
425
|
+
"len(result) = len(arr)",
|
|
426
|
+
"∀ i, j: i < j ⇒ result[i] <= result[j]",
|
|
427
|
+
"result contains same elements as arr (permutation)"
|
|
428
|
+
]
|
|
429
|
+
complexity: "O(n log n)"
|
|
430
|
+
invariants: [
|
|
431
|
+
"Partition maintains: ∀ x ∈ left: x <= pivot",
|
|
432
|
+
"∀ x ∈ right: x > pivot"
|
|
433
|
+
]
|
|
434
|
+
\"\"\"
|
|
435
|
+
# Implementation
|
|
436
|
+
pass
|
|
437
|
+
```"""
|
|
438
|
+
|
|
439
|
+
else: # TypeScript/JavaScript
|
|
440
|
+
return """## Examples
|
|
441
|
+
|
|
442
|
+
### Example 1: API Route Handler
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
/**@voodocs
|
|
446
|
+
preconditions: [
|
|
447
|
+
"request.user is authenticated",
|
|
448
|
+
"request.body.amount > 0",
|
|
449
|
+
"request.body.recipientId exists in database"
|
|
450
|
+
]
|
|
451
|
+
postconditions: [
|
|
452
|
+
"returns 200 ⇔ transfer successful",
|
|
453
|
+
"returns 400 ⇔ invalid input",
|
|
454
|
+
"returns 403 ⇔ insufficient funds",
|
|
455
|
+
"sender.balance decreased by amount",
|
|
456
|
+
"recipient.balance increased by amount"
|
|
457
|
+
]
|
|
458
|
+
security_implications: [
|
|
459
|
+
"Requires authentication",
|
|
460
|
+
"Rate limited to 10 transfers/minute",
|
|
461
|
+
"Validates account ownership"
|
|
462
|
+
]
|
|
463
|
+
side_effects: [
|
|
464
|
+
"Updates database (2 accounts)",
|
|
465
|
+
"Creates transaction record",
|
|
466
|
+
"Sends notification emails"
|
|
467
|
+
]
|
|
468
|
+
complexity: "O(1)"
|
|
469
|
+
*/
|
|
470
|
+
async function transferMoney(
|
|
471
|
+
request: Request,
|
|
472
|
+
response: Response
|
|
473
|
+
): Promise<void> {
|
|
474
|
+
// Implementation
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Example 2: React Component
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
/**@voodocs
|
|
482
|
+
preconditions: [
|
|
483
|
+
"props.items is non-empty array",
|
|
484
|
+
"props.onSelect is function"
|
|
485
|
+
]
|
|
486
|
+
postconditions: [
|
|
487
|
+
"renders list with props.items.length elements",
|
|
488
|
+
"clicking item calls props.onSelect with item"
|
|
489
|
+
]
|
|
490
|
+
assumptions: [
|
|
491
|
+
"items have unique 'id' property",
|
|
492
|
+
"items have 'name' property for display"
|
|
493
|
+
]
|
|
494
|
+
complexity: "O(n) where n = props.items.length"
|
|
495
|
+
*/
|
|
496
|
+
function ItemList({ items, onSelect }: ItemListProps) {
|
|
497
|
+
// Implementation
|
|
498
|
+
}
|
|
499
|
+
```"""
|
|
500
|
+
|
|
501
|
+
def _generate_workflow(self) -> str:
|
|
502
|
+
"""Generate workflow integration section."""
|
|
503
|
+
return """## Workflow Integration
|
|
504
|
+
|
|
505
|
+
### When to Add Annotations
|
|
506
|
+
|
|
507
|
+
Add `@voodocs` annotations in these scenarios:
|
|
508
|
+
|
|
509
|
+
1. **New Functions** - Annotate immediately after writing the function signature
|
|
510
|
+
2. **New Classes** - Annotate class and all public methods
|
|
511
|
+
3. **API Endpoints** - Always annotate with security and side effects
|
|
512
|
+
4. **Complex Logic** - Annotate algorithms with complexity and invariants
|
|
513
|
+
5. **Security-Critical Code** - Always annotate with security implications
|
|
514
|
+
|
|
515
|
+
### Annotation Workflow
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
1. Write function signature
|
|
519
|
+
↓
|
|
520
|
+
2. Add @voodocs annotation with preconditions/postconditions
|
|
521
|
+
↓
|
|
522
|
+
3. Implement function body
|
|
523
|
+
↓
|
|
524
|
+
4. Verify implementation matches postconditions
|
|
525
|
+
↓
|
|
526
|
+
5. Run `voodocs generate` to create tests and docs
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### Generated Outputs
|
|
530
|
+
|
|
531
|
+
When you annotate code with `@voodocs`, the following are automatically generated:
|
|
532
|
+
|
|
533
|
+
1. **Property-Based Tests** - Hypothesis tests with inferred strategies
|
|
534
|
+
2. **Documentation** - Human-readable Markdown docs
|
|
535
|
+
3. **API Specs** - OpenAPI 3.0 or GraphQL schemas
|
|
536
|
+
4. **Type Hints** - Enhanced type information
|
|
537
|
+
|
|
538
|
+
### Example Generation
|
|
539
|
+
|
|
540
|
+
Given this annotation:
|
|
541
|
+
|
|
542
|
+
```python
|
|
543
|
+
\"\"\"@voodocs
|
|
544
|
+
preconditions: ["x > 0", "y > 0"]
|
|
545
|
+
postconditions: ["result > x", "result > y"]
|
|
546
|
+
complexity: "O(1)"
|
|
547
|
+
\"\"\"
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
VooDocs generates:
|
|
551
|
+
|
|
552
|
+
```python
|
|
553
|
+
# Generated test
|
|
554
|
+
@given(x=st.integers(min_value=1), y=st.integers(min_value=1))
|
|
555
|
+
def test_property_based_add(x, y):
|
|
556
|
+
assume(x > 0)
|
|
557
|
+
assume(y > 0)
|
|
558
|
+
result = add(x, y)
|
|
559
|
+
assert result > x
|
|
560
|
+
assert result > y
|
|
561
|
+
```"""
|
|
562
|
+
|
|
563
|
+
def _generate_best_practices(self) -> str:
|
|
564
|
+
"""Generate best practices section."""
|
|
565
|
+
return """## Best Practices
|
|
566
|
+
|
|
567
|
+
### 1. Be Specific with Preconditions
|
|
568
|
+
|
|
569
|
+
**Good:**
|
|
570
|
+
```python
|
|
571
|
+
preconditions: [
|
|
572
|
+
"amount > 0",
|
|
573
|
+
"amount <= account.balance",
|
|
574
|
+
"account.status = ACTIVE"
|
|
575
|
+
]
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Avoid:**
|
|
579
|
+
```python
|
|
580
|
+
preconditions: ["valid input"] # Too vague
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### 2. Use Mathematical Notation for Precision
|
|
584
|
+
|
|
585
|
+
**Good:**
|
|
586
|
+
```python
|
|
587
|
+
postconditions: [
|
|
588
|
+
"∀ x ∈ result: x ∈ input", # All results are from input
|
|
589
|
+
"len(result) ≤ len(input)" # Result is subset
|
|
590
|
+
]
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**Avoid:**
|
|
594
|
+
```python
|
|
595
|
+
postconditions: ["returns filtered list"] # Imprecise
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### 3. Always Specify Complexity
|
|
599
|
+
|
|
600
|
+
**Good:**
|
|
601
|
+
```python
|
|
602
|
+
complexity: "O(n log n)"
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Also Good:**
|
|
606
|
+
```python
|
|
607
|
+
complexity: "O(n)" # VooDocs infers space as O(1)
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### 4. Document Security Implications
|
|
611
|
+
|
|
612
|
+
**Good:**
|
|
613
|
+
```python
|
|
614
|
+
security_implications: [
|
|
615
|
+
"Requires admin role",
|
|
616
|
+
"Rate limited to 100 requests/hour",
|
|
617
|
+
"Validates CSRF token"
|
|
618
|
+
]
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
### 5. Specify Error Cases
|
|
622
|
+
|
|
623
|
+
**Good:**
|
|
624
|
+
```python
|
|
625
|
+
error_cases: [
|
|
626
|
+
"amount <= 0 → ValueError",
|
|
627
|
+
"insufficient funds → InsufficientFundsError",
|
|
628
|
+
"account frozen → AccountFrozenError"
|
|
629
|
+
]
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### 6. Use Invariants for Loops and Recursion
|
|
633
|
+
|
|
634
|
+
**Good:**
|
|
635
|
+
```python
|
|
636
|
+
invariants: [
|
|
637
|
+
"∀ iteration: 0 <= i < len(arr)",
|
|
638
|
+
"sorted(arr[0:i])" # First i elements are sorted
|
|
639
|
+
]
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
### 7. Document Side Effects
|
|
643
|
+
|
|
644
|
+
**Good:**
|
|
645
|
+
```python
|
|
646
|
+
side_effects: [
|
|
647
|
+
"Writes to database",
|
|
648
|
+
"Sends email notification",
|
|
649
|
+
"Updates cache"
|
|
650
|
+
]
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**Avoid:**
|
|
654
|
+
```python
|
|
655
|
+
side_effects: ["Does stuff"] # Too vague
|
|
656
|
+
```"""
|
|
657
|
+
|
|
658
|
+
def _generate_footer(self) -> str:
|
|
659
|
+
"""Generate footer section."""
|
|
660
|
+
return """---
|
|
661
|
+
|
|
662
|
+
## Summary
|
|
663
|
+
|
|
664
|
+
**Remember**: Every time you write a function or class, ask yourself:
|
|
665
|
+
|
|
666
|
+
1. What must be true before this runs? → **preconditions**
|
|
667
|
+
2. What will be true after this runs? → **postconditions**
|
|
668
|
+
3. How fast is this? → **complexity**
|
|
669
|
+
4. What can go wrong? → **error_cases**
|
|
670
|
+
5. Is this security-sensitive? → **security_implications**
|
|
671
|
+
|
|
672
|
+
By documenting in DarkArts language, you're not just writing comments - you're creating a **formal specification** that generates tests, documentation, and API specs automatically.
|
|
673
|
+
|
|
674
|
+
**Generated by VooDocs** - AI-native documentation for modern development."""
|
|
675
|
+
|
|
676
|
+
def detect_assistant(self) -> Optional[str]:
|
|
677
|
+
"""
|
|
678
|
+
Detect which AI assistant is being used based on environment or config files.
|
|
679
|
+
|
|
680
|
+
Returns:
|
|
681
|
+
Assistant name or None if not detected
|
|
682
|
+
"""
|
|
683
|
+
# Check for config files in current directory
|
|
684
|
+
for assistant, info in self.ASSISTANTS.items():
|
|
685
|
+
config_path = Path(info["config_file"])
|
|
686
|
+
if config_path.exists():
|
|
687
|
+
return assistant
|
|
688
|
+
|
|
689
|
+
return None
|
|
690
|
+
|
|
691
|
+
@staticmethod
|
|
692
|
+
def list_assistants() -> List[Dict[str, str]]:
|
|
693
|
+
"""
|
|
694
|
+
List all supported AI assistants.
|
|
695
|
+
|
|
696
|
+
Returns:
|
|
697
|
+
List of assistant info dictionaries
|
|
698
|
+
"""
|
|
699
|
+
return [
|
|
700
|
+
{
|
|
701
|
+
"id": assistant_id,
|
|
702
|
+
"name": info["name"],
|
|
703
|
+
"config_file": info["config_file"]
|
|
704
|
+
}
|
|
705
|
+
for assistant_id, info in InstructionGenerator.ASSISTANTS.items()
|
|
706
|
+
]
|