@voodocs/cli 1.0.5 → 1.0.7
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/CHANGELOG.md +59 -0
- package/lib/cli/__init__.py +1 -1
- package/lib/cli/init.py +477 -98
- package/lib/darkarts/instructions/claude.md +139 -0
- package/lib/darkarts/instructions/cursor.md +139 -0
- package/lib/darkarts/instructions/default.md +139 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,62 @@
|
|
|
1
|
+
## [1.0.7] - 2024-12-21
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- **Enhanced Init Wizard**: Complete interactive setup experience
|
|
5
|
+
- Auto-detects project details (name, version, repository)
|
|
6
|
+
- Generates AI instructions automatically
|
|
7
|
+
- Configures privacy settings (.gitignore)
|
|
8
|
+
- Creates example annotated files
|
|
9
|
+
- **Rerunnable for upgrades**: Detects existing config and adds missing features
|
|
10
|
+
- Smart defaults for non-interactive mode
|
|
11
|
+
- Beautiful CLI interface with status icons and summaries
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- `voodocs init` now includes full wizard experience
|
|
15
|
+
- Wizard supports both fresh install and upgrade scenarios
|
|
16
|
+
- Auto-detection of AI environment (Cursor, Claude)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Init command now properly integrates with instruct command
|
|
20
|
+
- Upgrade path for users installing new versions
|
|
21
|
+
|
|
22
|
+
## v1.0.6 (2024-12-21)
|
|
23
|
+
|
|
24
|
+
### 🐛 Bug Fix: Missing Instructions Directory in npm Package
|
|
25
|
+
|
|
26
|
+
**Problem:** The `voodocs instruct` command failed with "Error: Instructions directory not found" because the `lib/darkarts/instructions/` directory was not included in the npm package.
|
|
27
|
+
|
|
28
|
+
**Root Cause:** The `instructions/` directory was not listed in the `files` array in `package.json`.
|
|
29
|
+
|
|
30
|
+
**Fix:** Added `lib/darkarts/instructions/` to the `files` array in `package.json`.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
### Changes
|
|
35
|
+
|
|
36
|
+
- Added `lib/darkarts/instructions/` to package.json `files` array
|
|
37
|
+
- Verified that all instruction templates are now included in the package:
|
|
38
|
+
- `claude.md`
|
|
39
|
+
- `cursor.md`
|
|
40
|
+
- `default.md`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### Testing
|
|
45
|
+
|
|
46
|
+
| Test Case | Status |
|
|
47
|
+
|-----------|--------|
|
|
48
|
+
| Instructions directory included in package | ✅ Pass |
|
|
49
|
+
| `voodocs instruct --list-templates` | ✅ Pass |
|
|
50
|
+
| `voodocs instruct --ai cursor` | ✅ Pass |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### Upgrade
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install -g @voodocs/cli@1.0.6
|
|
58
|
+
```
|
|
59
|
+
|
|
1
60
|
## v1.0.5 (2024-12-21)
|
|
2
61
|
|
|
3
62
|
### 🐛 Bug Fix: Instruct Command Import Error
|
package/lib/cli/__init__.py
CHANGED
package/lib/cli/init.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""@darkarts
|
|
2
|
-
⊢{cli:init}
|
|
3
|
-
∂{click,pathlib,json}
|
|
2
|
+
⊢{cli:init-wizard}
|
|
3
|
+
∂{click,pathlib,json,os,subprocess}
|
|
4
4
|
⚠{write-access:cwd}
|
|
5
|
-
⊨{idempotent:config-creation}
|
|
5
|
+
⊨{idempotent:config-creation,rerunnable:upgrade-support}
|
|
6
6
|
🔒{read-write:filesystem}
|
|
7
7
|
⚡{O(1):file-creation}
|
|
8
8
|
"""
|
|
@@ -10,52 +10,277 @@
|
|
|
10
10
|
"""
|
|
11
11
|
VooDocs Init Command
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Interactive wizard to initialize or upgrade a project with VooDocs.
|
|
14
|
+
Re-runnable to add missing features after upgrades.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
17
|
import click
|
|
17
18
|
import json
|
|
19
|
+
import os
|
|
20
|
+
import subprocess
|
|
18
21
|
from pathlib import Path
|
|
22
|
+
from typing import Optional, Dict, Any
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
@click.command()
|
|
22
26
|
@click.option(
|
|
23
|
-
'--
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
help='Annotation format to use (voodocs or darkarts symbolic)'
|
|
27
|
+
'--non-interactive',
|
|
28
|
+
is_flag=True,
|
|
29
|
+
help='Skip interactive prompts and use defaults'
|
|
27
30
|
)
|
|
28
31
|
@click.option(
|
|
29
|
-
'--
|
|
32
|
+
'--upgrade',
|
|
30
33
|
is_flag=True,
|
|
31
|
-
help='
|
|
34
|
+
help='Upgrade existing configuration (add missing features)'
|
|
32
35
|
)
|
|
33
|
-
def init(
|
|
36
|
+
def init(non_interactive, upgrade):
|
|
34
37
|
"""
|
|
35
|
-
Initialize a
|
|
38
|
+
Initialize or upgrade a project with VooDocs.
|
|
39
|
+
|
|
40
|
+
This interactive wizard will:
|
|
41
|
+
- Set up your project configuration
|
|
42
|
+
- Auto-detect project details (version, repository, AI environment)
|
|
43
|
+
- Create AI instructions for your coding assistant
|
|
44
|
+
- Configure privacy settings (.gitignore)
|
|
45
|
+
- Generate example annotated files
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
example annotated files to help you get started.
|
|
47
|
+
Re-run after upgrading to add new features!
|
|
39
48
|
|
|
40
49
|
Examples:
|
|
41
|
-
voodocs init #
|
|
42
|
-
voodocs init --
|
|
43
|
-
voodocs init --
|
|
50
|
+
voodocs init # Interactive wizard
|
|
51
|
+
voodocs init --upgrade # Upgrade existing config
|
|
52
|
+
voodocs init --non-interactive # Use all defaults
|
|
44
53
|
"""
|
|
54
|
+
|
|
45
55
|
cwd = Path.cwd()
|
|
46
56
|
config_path = cwd / '.voodocs.json'
|
|
47
57
|
|
|
48
|
-
# Check if
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
# Check if this is an upgrade or fresh install
|
|
59
|
+
existing_config = None
|
|
60
|
+
is_upgrade = config_path.exists()
|
|
61
|
+
|
|
62
|
+
if is_upgrade:
|
|
63
|
+
try:
|
|
64
|
+
with open(config_path) as f:
|
|
65
|
+
existing_config = json.load(f)
|
|
66
|
+
except:
|
|
67
|
+
existing_config = None
|
|
68
|
+
|
|
69
|
+
# Print welcome header
|
|
70
|
+
click.echo()
|
|
71
|
+
if is_upgrade:
|
|
72
|
+
click.echo(click.style('╔══════════════════════════════════════════╗', fg='yellow', bold=True))
|
|
73
|
+
click.echo(click.style('║ 🔄 VooDocs Upgrade Wizard ║', fg='yellow', bold=True))
|
|
74
|
+
click.echo(click.style('╚══════════════════════════════════════════╝', fg='yellow', bold=True))
|
|
75
|
+
click.echo()
|
|
76
|
+
click.echo(click.style('Existing configuration detected!', fg='yellow'))
|
|
77
|
+
click.echo('This wizard will help you add any missing features.')
|
|
78
|
+
else:
|
|
79
|
+
click.echo(click.style('╔══════════════════════════════════════════╗', fg='cyan', bold=True))
|
|
80
|
+
click.echo(click.style('║ 🎉 Welcome to VooDocs Setup Wizard ║', fg='cyan', bold=True))
|
|
81
|
+
click.echo(click.style('╚══════════════════════════════════════════╝', fg='cyan', bold=True))
|
|
82
|
+
click.echo()
|
|
83
|
+
|
|
84
|
+
# Detect what's already configured
|
|
85
|
+
has_ai_instructions = _check_ai_instructions(cwd)
|
|
86
|
+
has_examples = (cwd / 'voodocs-examples').exists()
|
|
87
|
+
has_gitignore_entry = _check_gitignore(cwd, '.voodocs.json')
|
|
88
|
+
|
|
89
|
+
if is_upgrade and not non_interactive:
|
|
90
|
+
click.echo(click.style('Current Setup:', fg='cyan', bold=True))
|
|
91
|
+
click.echo(f' Configuration: {_status_icon(True)} .voodocs.json exists')
|
|
92
|
+
click.echo(f' AI Instructions: {_status_icon(has_ai_instructions)} {_get_ai_file_status(cwd)}')
|
|
93
|
+
click.echo(f' Example Files: {_status_icon(has_examples)} voodocs-examples/')
|
|
94
|
+
click.echo(f' .gitignore: {_status_icon(has_gitignore_entry)} .voodocs.json entry')
|
|
95
|
+
click.echo()
|
|
96
|
+
|
|
97
|
+
if not click.confirm('Continue with upgrade?', default=True):
|
|
52
98
|
click.echo('Aborted.')
|
|
53
99
|
return
|
|
100
|
+
click.echo()
|
|
101
|
+
|
|
102
|
+
# Step 1: Project Information
|
|
103
|
+
click.echo(click.style('📋 Step 1: Project Information', fg='blue', bold=True))
|
|
104
|
+
click.echo()
|
|
105
|
+
|
|
106
|
+
# Auto-detect or use existing config
|
|
107
|
+
project_name = _get_value(existing_config, 'project.name', _detect_project_name(cwd))
|
|
108
|
+
project_version = _get_value(existing_config, 'project.version', _detect_version(cwd))
|
|
109
|
+
repository_url = _get_value(existing_config, 'project.repository', _detect_repository(cwd))
|
|
110
|
+
project_purpose = _get_value(existing_config, 'project.purpose', f'{project_name} project')
|
|
111
|
+
|
|
112
|
+
if non_interactive:
|
|
113
|
+
name = project_name
|
|
114
|
+
version = project_version
|
|
115
|
+
repository = repository_url
|
|
116
|
+
purpose = project_purpose
|
|
117
|
+
else:
|
|
118
|
+
if is_upgrade:
|
|
119
|
+
click.echo(f'Current values (press Enter to keep):')
|
|
120
|
+
name = click.prompt('Project name', default=project_name)
|
|
121
|
+
purpose = click.prompt('Project purpose', default=project_purpose)
|
|
122
|
+
version = click.prompt('Current version', default=project_version)
|
|
123
|
+
repository = click.prompt('Repository URL (leave empty to skip)', default=repository_url or '', show_default=False)
|
|
124
|
+
|
|
125
|
+
click.echo()
|
|
126
|
+
|
|
127
|
+
# Step 2: Annotation Format
|
|
128
|
+
click.echo(click.style('✨ Step 2: Annotation Format', fg='blue', bold=True))
|
|
129
|
+
click.echo()
|
|
130
|
+
|
|
131
|
+
current_format = _get_value(existing_config, 'format', 'darkarts')
|
|
132
|
+
|
|
133
|
+
if is_upgrade:
|
|
134
|
+
click.echo(f'Current format: {click.style(current_format, fg="green", bold=True)}')
|
|
135
|
+
if non_interactive:
|
|
136
|
+
format_choice = current_format
|
|
137
|
+
else:
|
|
138
|
+
change_format = click.confirm('Change annotation format?', default=False)
|
|
139
|
+
if change_format:
|
|
140
|
+
click.echo()
|
|
141
|
+
click.echo('VooDocs supports two annotation formats:')
|
|
142
|
+
click.echo(' 1. Natural language (e.g., module_purpose: "...")')
|
|
143
|
+
click.echo(' 2. Symbolic DarkArts (e.g., ⊢{...}, ∂{...}, ⚠{...})')
|
|
144
|
+
click.echo()
|
|
145
|
+
format_choice = click.prompt(
|
|
146
|
+
'Choose format',
|
|
147
|
+
type=click.Choice(['voodocs', 'darkarts'], case_sensitive=False),
|
|
148
|
+
default=current_format
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
format_choice = current_format
|
|
152
|
+
else:
|
|
153
|
+
click.echo('VooDocs supports two annotation formats:')
|
|
154
|
+
click.echo(' 1. Natural language (e.g., module_purpose: "...")')
|
|
155
|
+
click.echo(' 2. Symbolic DarkArts (e.g., ⊢{...}, ∂{...}, ⚠{...})')
|
|
156
|
+
click.echo()
|
|
157
|
+
if non_interactive:
|
|
158
|
+
format_choice = 'darkarts'
|
|
159
|
+
else:
|
|
160
|
+
format_choice = click.prompt(
|
|
161
|
+
'Choose format',
|
|
162
|
+
type=click.Choice(['voodocs', 'darkarts'], case_sensitive=False),
|
|
163
|
+
default='darkarts'
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
click.echo()
|
|
167
|
+
|
|
168
|
+
# Step 3: AI Assistant Setup
|
|
169
|
+
click.echo(click.style('🤖 Step 3: AI Assistant Setup', fg='blue', bold=True))
|
|
170
|
+
click.echo()
|
|
171
|
+
|
|
172
|
+
detected_ai = _detect_ai_environment()
|
|
173
|
+
|
|
174
|
+
if has_ai_instructions and is_upgrade:
|
|
175
|
+
click.echo(f'{_status_icon(True)} AI instructions already configured')
|
|
176
|
+
if non_interactive:
|
|
177
|
+
setup_ai = False
|
|
178
|
+
ai_choice = None
|
|
179
|
+
else:
|
|
180
|
+
setup_ai = click.confirm('Update AI instructions?', default=False)
|
|
181
|
+
if setup_ai:
|
|
182
|
+
ai_choice = click.prompt(
|
|
183
|
+
'Which AI assistant?',
|
|
184
|
+
type=click.Choice(['cursor', 'claude', 'default'], case_sensitive=False),
|
|
185
|
+
default=detected_ai or 'cursor'
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
ai_choice = None
|
|
189
|
+
else:
|
|
190
|
+
if detected_ai:
|
|
191
|
+
click.echo(f'Detected AI environment: {click.style(detected_ai, fg="green", bold=True)}')
|
|
192
|
+
else:
|
|
193
|
+
click.echo('No AI environment detected')
|
|
194
|
+
click.echo()
|
|
195
|
+
|
|
196
|
+
if non_interactive:
|
|
197
|
+
setup_ai = detected_ai is not None
|
|
198
|
+
ai_choice = detected_ai or 'cursor'
|
|
199
|
+
else:
|
|
200
|
+
setup_ai = click.confirm('Generate AI instructions for your coding assistant?', default=True)
|
|
201
|
+
if setup_ai:
|
|
202
|
+
ai_choice = click.prompt(
|
|
203
|
+
'Which AI assistant?',
|
|
204
|
+
type=click.Choice(['cursor', 'claude', 'default'], case_sensitive=False),
|
|
205
|
+
default=detected_ai or 'cursor'
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
ai_choice = None
|
|
209
|
+
|
|
210
|
+
click.echo()
|
|
211
|
+
|
|
212
|
+
# Step 4: Privacy Settings
|
|
213
|
+
click.echo(click.style('🔒 Step 4: Privacy Settings', fg='blue', bold=True))
|
|
214
|
+
click.echo()
|
|
215
|
+
|
|
216
|
+
if has_gitignore_entry and is_upgrade:
|
|
217
|
+
click.echo(f'{_status_icon(True)} .gitignore already configured')
|
|
218
|
+
add_to_gitignore = False
|
|
219
|
+
else:
|
|
220
|
+
if non_interactive:
|
|
221
|
+
is_private = True
|
|
222
|
+
add_to_gitignore = True
|
|
223
|
+
else:
|
|
224
|
+
is_private = click.confirm('Is this a private project?', default=True)
|
|
225
|
+
add_to_gitignore = False
|
|
226
|
+
if is_private:
|
|
227
|
+
add_to_gitignore = click.confirm('Add .voodocs.json to .gitignore?', default=True)
|
|
228
|
+
|
|
229
|
+
click.echo()
|
|
230
|
+
|
|
231
|
+
# Step 5: Example Files
|
|
232
|
+
click.echo(click.style('📝 Step 5: Example Files', fg='blue', bold=True))
|
|
233
|
+
click.echo()
|
|
234
|
+
|
|
235
|
+
if has_examples and is_upgrade:
|
|
236
|
+
click.echo(f'{_status_icon(True)} Example files already exist')
|
|
237
|
+
create_examples = False
|
|
238
|
+
else:
|
|
239
|
+
if non_interactive:
|
|
240
|
+
create_examples = True
|
|
241
|
+
else:
|
|
242
|
+
create_examples = click.confirm('Create example annotated files?', default=not is_upgrade)
|
|
243
|
+
|
|
244
|
+
click.echo()
|
|
245
|
+
|
|
246
|
+
# Show configuration summary
|
|
247
|
+
click.echo(click.style('📊 Configuration Summary', fg='cyan', bold=True))
|
|
248
|
+
click.echo(click.style('─' * 50, fg='cyan'))
|
|
249
|
+
click.echo(f' Project Name: {click.style(name, fg="green")}')
|
|
250
|
+
click.echo(f' Purpose: {purpose}')
|
|
251
|
+
click.echo(f' Version: {version}')
|
|
252
|
+
if repository:
|
|
253
|
+
click.echo(f' Repository: {repository}')
|
|
254
|
+
click.echo(f' Format: {click.style(format_choice, fg="green", bold=True)}')
|
|
255
|
+
if setup_ai and ai_choice:
|
|
256
|
+
click.echo(f' AI Assistant: {click.style(ai_choice, fg="green")} {_status_icon(True, "new") if not has_ai_instructions else ""}')
|
|
257
|
+
if add_to_gitignore:
|
|
258
|
+
click.echo(f' .gitignore: {click.style("Yes", fg="green")} {_status_icon(True, "new")}')
|
|
259
|
+
if create_examples:
|
|
260
|
+
click.echo(f' Example Files: {click.style("Yes", fg="green")} {_status_icon(True, "new")}')
|
|
261
|
+
click.echo(click.style('─' * 50, fg='cyan'))
|
|
262
|
+
click.echo()
|
|
263
|
+
|
|
264
|
+
if not non_interactive:
|
|
265
|
+
action = 'upgrade' if is_upgrade else 'create'
|
|
266
|
+
if not click.confirm(f'Proceed to {action} configuration?', default=True):
|
|
267
|
+
click.echo('Aborted.')
|
|
268
|
+
return
|
|
269
|
+
click.echo()
|
|
270
|
+
|
|
271
|
+
# Create/update configuration
|
|
272
|
+
action_verb = 'Updating' if is_upgrade else 'Creating'
|
|
273
|
+
click.echo(click.style(f'⚙️ {action_verb} configuration...', fg='blue'))
|
|
54
274
|
|
|
55
|
-
# Create default configuration
|
|
56
275
|
config = {
|
|
57
276
|
"version": "1.0",
|
|
58
|
-
"
|
|
277
|
+
"project": {
|
|
278
|
+
"name": name,
|
|
279
|
+
"purpose": purpose,
|
|
280
|
+
"version": version,
|
|
281
|
+
"repository": repository if repository else None
|
|
282
|
+
},
|
|
283
|
+
"format": format_choice,
|
|
59
284
|
"validation": {
|
|
60
285
|
"semantic": True,
|
|
61
286
|
"performance": True,
|
|
@@ -76,40 +301,252 @@ def init(format, config_only):
|
|
|
76
301
|
]
|
|
77
302
|
}
|
|
78
303
|
|
|
304
|
+
# Merge with existing config if upgrading
|
|
305
|
+
if is_upgrade and existing_config:
|
|
306
|
+
# Preserve any custom fields
|
|
307
|
+
for key in existing_config:
|
|
308
|
+
if key not in config:
|
|
309
|
+
config[key] = existing_config[key]
|
|
310
|
+
|
|
79
311
|
# Write configuration
|
|
80
312
|
with open(config_path, 'w') as f:
|
|
81
313
|
json.dump(config, f, indent=2)
|
|
82
314
|
|
|
83
|
-
|
|
315
|
+
verb = 'Updated' if is_upgrade else 'Created'
|
|
316
|
+
click.echo(click.style(f' ✓ {verb} .voodocs.json', fg='green'))
|
|
317
|
+
|
|
318
|
+
# Add to .gitignore if requested
|
|
319
|
+
if add_to_gitignore:
|
|
320
|
+
_add_to_gitignore(cwd, '.voodocs.json')
|
|
321
|
+
click.echo(click.style(' ✓ Added to .gitignore', fg='green'))
|
|
322
|
+
|
|
323
|
+
# Generate AI instructions
|
|
324
|
+
if setup_ai and ai_choice:
|
|
325
|
+
click.echo(click.style(f' ⚙️ Generating {ai_choice} instructions...', fg='blue'))
|
|
326
|
+
_generate_ai_instructions(cwd, ai_choice, format_choice)
|
|
327
|
+
click.echo(click.style(f' ✓ Created AI instructions', fg='green'))
|
|
84
328
|
|
|
85
|
-
|
|
86
|
-
|
|
329
|
+
# Create example files
|
|
330
|
+
if create_examples:
|
|
331
|
+
click.echo(click.style(' ⚙️ Creating example files...', fg='blue'))
|
|
87
332
|
examples_dir = cwd / 'voodocs-examples'
|
|
88
333
|
examples_dir.mkdir(exist_ok=True)
|
|
89
334
|
|
|
90
|
-
if
|
|
91
|
-
|
|
335
|
+
if format_choice == 'voodocs':
|
|
336
|
+
_create_voodocs_examples(examples_dir)
|
|
92
337
|
else:
|
|
93
|
-
|
|
338
|
+
_create_darkarts_examples(examples_dir)
|
|
94
339
|
|
|
95
|
-
click.echo(click.style(f'✓ Created
|
|
340
|
+
click.echo(click.style(f' ✓ Created examples in {examples_dir}/', fg='green'))
|
|
96
341
|
|
|
342
|
+
# Success!
|
|
97
343
|
click.echo()
|
|
98
|
-
|
|
344
|
+
if is_upgrade:
|
|
345
|
+
click.echo(click.style('╔══════════════════════════════════════════╗', fg='green', bold=True))
|
|
346
|
+
click.echo(click.style('║ ✅ VooDocs Upgrade Complete! ║', fg='green', bold=True))
|
|
347
|
+
click.echo(click.style('╚══════════════════════════════════════════╝', fg='green', bold=True))
|
|
348
|
+
else:
|
|
349
|
+
click.echo(click.style('╔══════════════════════════════════════════╗', fg='green', bold=True))
|
|
350
|
+
click.echo(click.style('║ 🎉 VooDocs Setup Complete! ║', fg='green', bold=True))
|
|
351
|
+
click.echo(click.style('╚══════════════════════════════════════════╝', fg='green', bold=True))
|
|
99
352
|
click.echo()
|
|
100
|
-
click.echo('Next steps:')
|
|
353
|
+
click.echo(click.style('Next steps:', fg='cyan', bold=True))
|
|
101
354
|
click.echo(' 1. Review .voodocs.json configuration')
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
355
|
+
if setup_ai and ai_choice:
|
|
356
|
+
ai_file = '.cursorrules' if ai_choice == 'cursor' else f'{ai_choice}-instructions.md'
|
|
357
|
+
click.echo(f' 2. Your AI assistant will use {ai_file}')
|
|
358
|
+
click.echo(' 3. Add annotations to your code')
|
|
359
|
+
click.echo(' 4. Run: voodocs validate .')
|
|
360
|
+
click.echo(' 5. Run: voodocs generate . ./docs')
|
|
105
361
|
click.echo()
|
|
106
|
-
|
|
362
|
+
if is_upgrade:
|
|
363
|
+
click.echo(click.style('💡 Tip:', fg='yellow') + ' Run ' + click.style('voodocs init --upgrade', fg='cyan') + ' again after future updates!')
|
|
364
|
+
click.echo()
|
|
365
|
+
click.echo(f'Documentation: {click.style("https://voodocs.com/docs", fg="blue", underline=True)}')
|
|
366
|
+
click.echo()
|
|
367
|
+
|
|
107
368
|
|
|
369
|
+
def _status_icon(exists: bool, label: str = None) -> str:
|
|
370
|
+
"""Return a status icon."""
|
|
371
|
+
if label == "new":
|
|
372
|
+
return click.style('🆕', fg='green')
|
|
373
|
+
return click.style('✓', fg='green') if exists else click.style('✗', fg='red')
|
|
108
374
|
|
|
109
|
-
|
|
375
|
+
|
|
376
|
+
def _get_value(config: Optional[Dict[str, Any]], path: str, default: Any) -> Any:
|
|
377
|
+
"""Get a value from nested config dict using dot notation."""
|
|
378
|
+
if not config:
|
|
379
|
+
return default
|
|
380
|
+
|
|
381
|
+
keys = path.split('.')
|
|
382
|
+
value = config
|
|
383
|
+
for key in keys:
|
|
384
|
+
if isinstance(value, dict) and key in value:
|
|
385
|
+
value = value[key]
|
|
386
|
+
else:
|
|
387
|
+
return default
|
|
388
|
+
|
|
389
|
+
return value if value is not None else default
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _check_ai_instructions(cwd: Path) -> bool:
|
|
393
|
+
"""Check if AI instructions exist."""
|
|
394
|
+
return (
|
|
395
|
+
(cwd / '.cursorrules').exists() or
|
|
396
|
+
(cwd / '.claude' / 'instructions.md').exists() or
|
|
397
|
+
(cwd / 'AI_INSTRUCTIONS.md').exists()
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def _get_ai_file_status(cwd: Path) -> str:
|
|
402
|
+
"""Get status of AI instruction files."""
|
|
403
|
+
files = []
|
|
404
|
+
if (cwd / '.cursorrules').exists():
|
|
405
|
+
files.append('.cursorrules')
|
|
406
|
+
if (cwd / '.claude' / 'instructions.md').exists():
|
|
407
|
+
files.append('.claude/instructions.md')
|
|
408
|
+
if (cwd / 'AI_INSTRUCTIONS.md').exists():
|
|
409
|
+
files.append('AI_INSTRUCTIONS.md')
|
|
410
|
+
|
|
411
|
+
return ', '.join(files) if files else 'none'
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _check_gitignore(cwd: Path, entry: str) -> bool:
|
|
415
|
+
"""Check if entry exists in .gitignore."""
|
|
416
|
+
gitignore = cwd / '.gitignore'
|
|
417
|
+
if not gitignore.exists():
|
|
418
|
+
return False
|
|
419
|
+
|
|
420
|
+
content = gitignore.read_text()
|
|
421
|
+
return entry in content
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _detect_project_name(cwd: Path) -> str:
|
|
425
|
+
"""Detect project name from directory or package.json."""
|
|
426
|
+
package_json = cwd / 'package.json'
|
|
427
|
+
if package_json.exists():
|
|
428
|
+
try:
|
|
429
|
+
with open(package_json) as f:
|
|
430
|
+
data = json.load(f)
|
|
431
|
+
if 'name' in data:
|
|
432
|
+
return data['name']
|
|
433
|
+
except:
|
|
434
|
+
pass
|
|
435
|
+
|
|
436
|
+
return cwd.name
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def _detect_version(cwd: Path) -> str:
|
|
440
|
+
"""Detect project version."""
|
|
441
|
+
package_json = cwd / 'package.json'
|
|
442
|
+
if package_json.exists():
|
|
443
|
+
try:
|
|
444
|
+
with open(package_json) as f:
|
|
445
|
+
data = json.load(f)
|
|
446
|
+
if 'version' in data:
|
|
447
|
+
return data['version']
|
|
448
|
+
except:
|
|
449
|
+
pass
|
|
450
|
+
|
|
451
|
+
pyproject = cwd / 'pyproject.toml'
|
|
452
|
+
if pyproject.exists():
|
|
453
|
+
try:
|
|
454
|
+
with open(pyproject) as f:
|
|
455
|
+
for line in f:
|
|
456
|
+
if line.startswith('version'):
|
|
457
|
+
return line.split('=')[1].strip().strip('"\'')
|
|
458
|
+
except:
|
|
459
|
+
pass
|
|
460
|
+
|
|
461
|
+
version_file = cwd / 'VERSION'
|
|
462
|
+
if version_file.exists():
|
|
463
|
+
try:
|
|
464
|
+
return version_file.read_text().strip()
|
|
465
|
+
except:
|
|
466
|
+
pass
|
|
467
|
+
|
|
468
|
+
return '1.0.0'
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def _detect_repository(cwd: Path) -> Optional[str]:
|
|
472
|
+
"""Detect repository URL from git config."""
|
|
473
|
+
try:
|
|
474
|
+
result = subprocess.run(
|
|
475
|
+
['git', 'config', '--get', 'remote.origin.url'],
|
|
476
|
+
capture_output=True,
|
|
477
|
+
text=True,
|
|
478
|
+
cwd=cwd
|
|
479
|
+
)
|
|
480
|
+
if result.returncode == 0:
|
|
481
|
+
url = result.stdout.strip()
|
|
482
|
+
if url.startswith('git@github.com:'):
|
|
483
|
+
url = url.replace('git@github.com:', 'https://github.com/')
|
|
484
|
+
if url.endswith('.git'):
|
|
485
|
+
url = url[:-4]
|
|
486
|
+
return url
|
|
487
|
+
except:
|
|
488
|
+
pass
|
|
489
|
+
|
|
490
|
+
return None
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def _detect_ai_environment() -> Optional[str]:
|
|
494
|
+
"""Detect which AI environment is being used."""
|
|
495
|
+
if os.environ.get('CURSOR_USER') or Path('.cursorrules').exists():
|
|
496
|
+
return 'cursor'
|
|
497
|
+
|
|
498
|
+
if os.environ.get('CLAUDE_API_KEY') or Path('.claude').exists():
|
|
499
|
+
return 'claude'
|
|
500
|
+
|
|
501
|
+
return None
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def _add_to_gitignore(cwd: Path, entry: str):
|
|
505
|
+
"""Add an entry to .gitignore."""
|
|
506
|
+
gitignore = cwd / '.gitignore'
|
|
507
|
+
|
|
508
|
+
if gitignore.exists():
|
|
509
|
+
content = gitignore.read_text()
|
|
510
|
+
if entry in content:
|
|
511
|
+
return
|
|
512
|
+
else:
|
|
513
|
+
content = ''
|
|
514
|
+
|
|
515
|
+
if content and not content.endswith('\n'):
|
|
516
|
+
content += '\n'
|
|
517
|
+
content += f'\n# VooDocs\n{entry}\n'
|
|
518
|
+
|
|
519
|
+
gitignore.write_text(content)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def _generate_ai_instructions(cwd: Path, ai_type: str, format_type: str):
|
|
523
|
+
"""Generate AI instructions file."""
|
|
524
|
+
cli_dir = Path(__file__).parent
|
|
525
|
+
template_path = cli_dir.parent / 'darkarts' / 'instructions' / f'{ai_type}.md'
|
|
526
|
+
|
|
527
|
+
if not template_path.exists():
|
|
528
|
+
template_path = cli_dir.parent / 'darkarts' / 'instructions' / 'default.md'
|
|
529
|
+
|
|
530
|
+
if not template_path.exists():
|
|
531
|
+
return
|
|
532
|
+
|
|
533
|
+
instructions = template_path.read_text()
|
|
534
|
+
|
|
535
|
+
if ai_type == 'cursor':
|
|
536
|
+
output_file = cwd / '.cursorrules'
|
|
537
|
+
elif ai_type == 'claude':
|
|
538
|
+
output_dir = cwd / '.claude'
|
|
539
|
+
output_dir.mkdir(exist_ok=True)
|
|
540
|
+
output_file = output_dir / 'instructions.md'
|
|
541
|
+
else:
|
|
542
|
+
output_file = cwd / 'AI_INSTRUCTIONS.md'
|
|
543
|
+
|
|
544
|
+
output_file.write_text(instructions)
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def _create_voodocs_examples(examples_dir: Path):
|
|
110
548
|
"""Create example files with @voodocs annotations."""
|
|
111
549
|
|
|
112
|
-
# TypeScript example
|
|
113
550
|
ts_example = '''/**@voodocs
|
|
114
551
|
module_purpose: "Example TypeScript module demonstrating @voodocs annotations"
|
|
115
552
|
dependencies: []
|
|
@@ -137,41 +574,11 @@ export function greet(name: string, age: number): string {
|
|
|
137
574
|
'''
|
|
138
575
|
|
|
139
576
|
(examples_dir / 'example.ts').write_text(ts_example)
|
|
140
|
-
|
|
141
|
-
# Python example
|
|
142
|
-
py_example = '''"""@voodocs
|
|
143
|
-
module_purpose: "Example Python module demonstrating @voodocs annotations"
|
|
144
|
-
dependencies: []
|
|
145
|
-
assumptions: ["Python 3.7+"]
|
|
146
|
-
"""
|
|
147
|
-
|
|
148
|
-
def calculate_total(prices: list[float], tax_rate: float) -> float:
|
|
149
|
-
"""@voodocs
|
|
150
|
-
preconditions: [
|
|
151
|
-
"prices is a non-empty list of positive numbers",
|
|
152
|
-
"tax_rate is between 0 and 1"
|
|
153
|
-
]
|
|
154
|
-
postconditions: [
|
|
155
|
-
"Returns the total with tax applied",
|
|
156
|
-
"Result is greater than or equal to sum of prices"
|
|
157
|
-
]
|
|
158
|
-
invariants: [
|
|
159
|
-
"Does not modify the prices list"
|
|
160
|
-
]
|
|
161
|
-
side_effects: []
|
|
162
|
-
complexity: "O(n) where n is the length of prices"
|
|
163
|
-
"""
|
|
164
|
-
subtotal = sum(prices)
|
|
165
|
-
return subtotal * (1 + tax_rate)
|
|
166
|
-
'''
|
|
167
|
-
|
|
168
|
-
(examples_dir / 'example.py').write_text(py_example)
|
|
169
577
|
|
|
170
578
|
|
|
171
|
-
def
|
|
579
|
+
def _create_darkarts_examples(examples_dir: Path):
|
|
172
580
|
"""Create example files with symbolic @darkarts annotations."""
|
|
173
581
|
|
|
174
|
-
# TypeScript example
|
|
175
582
|
ts_example = '''/**@darkarts
|
|
176
583
|
⊢{Example TypeScript module demonstrating symbolic @darkarts annotations}
|
|
177
584
|
∂{}
|
|
@@ -190,7 +597,7 @@ def create_darkarts_example(examples_dir: Path):
|
|
|
190
597
|
⊨{
|
|
191
598
|
Does ¬ modify input parameters
|
|
192
599
|
}
|
|
193
|
-
⚡{}
|
|
600
|
+
⚡{O(1)}
|
|
194
601
|
*/
|
|
195
602
|
export function greet(name: string, age: number): string {
|
|
196
603
|
return `Hello, ${name}! You are ${age} years old.`;
|
|
@@ -198,31 +605,3 @@ export function greet(name: string, age: number): string {
|
|
|
198
605
|
'''
|
|
199
606
|
|
|
200
607
|
(examples_dir / 'example.ts').write_text(ts_example)
|
|
201
|
-
|
|
202
|
-
# Python example
|
|
203
|
-
py_example = '''"""@darkarts
|
|
204
|
-
⊢{Example Python module demonstrating symbolic @darkarts annotations}
|
|
205
|
-
∂{}
|
|
206
|
-
⚠{Python 3.7+}
|
|
207
|
-
"""
|
|
208
|
-
|
|
209
|
-
def calculate_total(prices: list[float], tax_rate: float) -> float:
|
|
210
|
-
"""@darkarts
|
|
211
|
-
⊳{
|
|
212
|
-
prices is a non-empty list ∧ ∀ p ∈ prices: p > 0
|
|
213
|
-
tax_rate ∈ [0, 1]
|
|
214
|
-
}
|
|
215
|
-
⊲{
|
|
216
|
-
Returns the total with tax applied
|
|
217
|
-
result ≥ sum(prices)
|
|
218
|
-
}
|
|
219
|
-
⊨{
|
|
220
|
-
Does ¬ modify the prices list
|
|
221
|
-
}
|
|
222
|
-
⚡{O(n) where n = len(prices)}
|
|
223
|
-
"""
|
|
224
|
-
subtotal = sum(prices)
|
|
225
|
-
return subtotal * (1 + tax_rate)
|
|
226
|
-
'''
|
|
227
|
-
|
|
228
|
-
(examples_dir / 'example.py').write_text(py_example)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Claude AI Instructions for Symbolic DarkArts Annotations
|
|
2
|
+
|
|
3
|
+
**Version:** 2.0
|
|
4
|
+
**Date:** December 21, 2024
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Primary Goal
|
|
9
|
+
|
|
10
|
+
Your primary goal is to **write and maintain symbolic DarkArts annotations** for all new and existing code. This ensures that our documentation is always up-to-date, accurate, and machine-readable.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 2. Annotation Format: Symbolic DarkArts
|
|
15
|
+
|
|
16
|
+
**Always use the symbolic DarkArts format.** Do not use the natural language `@voodocs` format.
|
|
17
|
+
|
|
18
|
+
### Correct Format
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
/**@darkarts
|
|
22
|
+
⊢{Module purpose}
|
|
23
|
+
∂{Dependencies}
|
|
24
|
+
⚠{Assumptions}
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**@darkarts
|
|
28
|
+
⊳{Preconditions}
|
|
29
|
+
⊲{Postconditions}
|
|
30
|
+
⊨{Invariants}
|
|
31
|
+
⚡{Side effects / Complexity}
|
|
32
|
+
🔒{Security implications}
|
|
33
|
+
*/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Incorrect Format (Do Not Use)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
/**@voodocs
|
|
40
|
+
module_purpose: "..."
|
|
41
|
+
dependencies: [...]
|
|
42
|
+
*/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Key Rules
|
|
48
|
+
|
|
49
|
+
1. **Annotate Everything:** All modules, functions, classes, and interfaces must have a DarkArts annotation block.
|
|
50
|
+
2. **Use Symbolic Format Only:** Strictly adhere to the symbolic format (`⊢`, `∂`, `⚠`, `⊳`, `⊲`, `⊨`, `⚡`, `🔒`).
|
|
51
|
+
3. **Use Logic Symbols:** Use mathematical symbols for logic (`∧`, `∨`, `¬`, `∈`, `∃`, `∀`, `⇒`, `⇔`).
|
|
52
|
+
4. **Be Precise and Concise:** Annotations should be accurate and to the point.
|
|
53
|
+
5. **Validate Your Work:** After making changes, run `voodocs validate . --recursive` to ensure all annotations are correct.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Symbol Quick Reference
|
|
58
|
+
|
|
59
|
+
| Symbol | Meaning | Symbol | Meaning |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `⊢` | Module Purpose | `∧` | And |
|
|
62
|
+
| `∂` | Dependencies | `∨` | Or |
|
|
63
|
+
| `⚠` | Assumptions | `¬` | Not |
|
|
64
|
+
| `⊳` | Preconditions | `∈` | In |
|
|
65
|
+
| `⊲` | Postconditions | `∉` | Not In |
|
|
66
|
+
| `⊨` | Invariants | `∃` | Exists |
|
|
67
|
+
| `⚡` | Side Effects / Complexity | `∀` | For All |
|
|
68
|
+
| `🔒` | Security Implications | `⇒` | Implies |
|
|
69
|
+
| `⇔` | If and Only If | `⊤` | True |
|
|
70
|
+
| `⊥` | False | `∅` | Empty Set |
|
|
71
|
+
| `⊆` | Subset | `∪` | Union |
|
|
72
|
+
| `∩` | Intersection | | |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 5. Workflow
|
|
77
|
+
|
|
78
|
+
1. **When writing new code:** Add symbolic DarkArts annotations as you go.
|
|
79
|
+
2. **When modifying existing code:** Update the corresponding annotations to reflect your changes.
|
|
80
|
+
3. **Before committing:** Run `voodocs validate . --recursive` to catch any errors.
|
|
81
|
+
4. **If validation fails:** Run `voodocs fix . --recursive` to automatically fix common issues.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 6. Example: Adding a New Function
|
|
86
|
+
|
|
87
|
+
If you add a new function `getUserById`, you must add a symbolic annotation block:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
/**@darkarts
|
|
91
|
+
⊳{userId must be a valid UUID}
|
|
92
|
+
⊲{
|
|
93
|
+
Returns a user object if found
|
|
94
|
+
Returns null if ¬∃ user with that ID
|
|
95
|
+
}
|
|
96
|
+
⊨{Does ¬ modify the database}
|
|
97
|
+
⚡{O(1) lookup}
|
|
98
|
+
*/
|
|
99
|
+
export async function getUserById(userId: string): Promise<User | null> {
|
|
100
|
+
// ...
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 7. Example: Modifying a Module
|
|
107
|
+
|
|
108
|
+
If you add a new dependency to a module, update the `∂` field:
|
|
109
|
+
|
|
110
|
+
**Before:**
|
|
111
|
+
```typescript
|
|
112
|
+
/**@darkarts
|
|
113
|
+
⊢{User authentication service}
|
|
114
|
+
∂{jsonwebtoken}
|
|
115
|
+
*/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**After (added bcrypt):**
|
|
119
|
+
```typescript
|
|
120
|
+
/**@darkarts
|
|
121
|
+
⊢{User authentication service}
|
|
122
|
+
∂{
|
|
123
|
+
jsonwebtoken: For JWT creation
|
|
124
|
+
bcrypt: For password hashing
|
|
125
|
+
}
|
|
126
|
+
*/
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 8. Important Commands
|
|
132
|
+
|
|
133
|
+
- **Validate:** `voodocs validate . --recursive`
|
|
134
|
+
- **Fix:** `voodocs fix . --recursive`
|
|
135
|
+
- **Generate Docs:** `voodocs generate . ./docs --recursive`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
By following these instructions, you will help us maintain a high-quality, machine-readable, and self-validating codebase. Thank you for your contribution!
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Cursor AI Instructions for Symbolic DarkArts Annotations
|
|
2
|
+
|
|
3
|
+
**Version:** 2.0
|
|
4
|
+
**Date:** December 21, 2024
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Primary Goal
|
|
9
|
+
|
|
10
|
+
Your primary goal is to **write and maintain symbolic DarkArts annotations** for all new and existing code. This ensures that our documentation is always up-to-date, accurate, and machine-readable.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 2. Annotation Format: Symbolic DarkArts
|
|
15
|
+
|
|
16
|
+
**Always use the symbolic DarkArts format.** Do not use the natural language `@voodocs` format.
|
|
17
|
+
|
|
18
|
+
### Correct Format
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
/**@darkarts
|
|
22
|
+
⊢{Module purpose}
|
|
23
|
+
∂{Dependencies}
|
|
24
|
+
⚠{Assumptions}
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**@darkarts
|
|
28
|
+
⊳{Preconditions}
|
|
29
|
+
⊲{Postconditions}
|
|
30
|
+
⊨{Invariants}
|
|
31
|
+
⚡{Side effects / Complexity}
|
|
32
|
+
🔒{Security implications}
|
|
33
|
+
*/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Incorrect Format (Do Not Use)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
/**@voodocs
|
|
40
|
+
module_purpose: "..."
|
|
41
|
+
dependencies: [...]
|
|
42
|
+
*/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Key Rules
|
|
48
|
+
|
|
49
|
+
1. **Annotate Everything:** All modules, functions, classes, and interfaces must have a DarkArts annotation block.
|
|
50
|
+
2. **Use Symbolic Format Only:** Strictly adhere to the symbolic format (`⊢`, `∂`, `⚠`, `⊳`, `⊲`, `⊨`, `⚡`, `🔒`).
|
|
51
|
+
3. **Use Logic Symbols:** Use mathematical symbols for logic (`∧`, `∨`, `¬`, `∈`, `∃`, `∀`, `⇒`, `⇔`).
|
|
52
|
+
4. **Be Precise and Concise:** Annotations should be accurate and to the point.
|
|
53
|
+
5. **Validate Your Work:** After making changes, run `voodocs validate . --recursive` to ensure all annotations are correct.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Symbol Quick Reference
|
|
58
|
+
|
|
59
|
+
| Symbol | Meaning | Symbol | Meaning |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `⊢` | Module Purpose | `∧` | And |
|
|
62
|
+
| `∂` | Dependencies | `∨` | Or |
|
|
63
|
+
| `⚠` | Assumptions | `¬` | Not |
|
|
64
|
+
| `⊳` | Preconditions | `∈` | In |
|
|
65
|
+
| `⊲` | Postconditions | `∉` | Not In |
|
|
66
|
+
| `⊨` | Invariants | `∃` | Exists |
|
|
67
|
+
| `⚡` | Side Effects / Complexity | `∀` | For All |
|
|
68
|
+
| `🔒` | Security Implications | `⇒` | Implies |
|
|
69
|
+
| `⇔` | If and Only If | `⊤` | True |
|
|
70
|
+
| `⊥` | False | `∅` | Empty Set |
|
|
71
|
+
| `⊆` | Subset | `∪` | Union |
|
|
72
|
+
| `∩` | Intersection | | |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 5. Workflow
|
|
77
|
+
|
|
78
|
+
1. **When writing new code:** Add symbolic DarkArts annotations as you go.
|
|
79
|
+
2. **When modifying existing code:** Update the corresponding annotations to reflect your changes.
|
|
80
|
+
3. **Before committing:** Run `voodocs validate . --recursive` to catch any errors.
|
|
81
|
+
4. **If validation fails:** Run `voodocs fix . --recursive` to automatically fix common issues.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 6. Example: Adding a New Function
|
|
86
|
+
|
|
87
|
+
If you add a new function `getUserById`, you must add a symbolic annotation block:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
/**@darkarts
|
|
91
|
+
⊳{userId must be a valid UUID}
|
|
92
|
+
⊲{
|
|
93
|
+
Returns a user object if found
|
|
94
|
+
Returns null if ¬∃ user with that ID
|
|
95
|
+
}
|
|
96
|
+
⊨{Does ¬ modify the database}
|
|
97
|
+
⚡{O(1) lookup}
|
|
98
|
+
*/
|
|
99
|
+
export async function getUserById(userId: string): Promise<User | null> {
|
|
100
|
+
// ...
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 7. Example: Modifying a Module
|
|
107
|
+
|
|
108
|
+
If you add a new dependency to a module, update the `∂` field:
|
|
109
|
+
|
|
110
|
+
**Before:**
|
|
111
|
+
```typescript
|
|
112
|
+
/**@darkarts
|
|
113
|
+
⊢{User authentication service}
|
|
114
|
+
∂{jsonwebtoken}
|
|
115
|
+
*/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**After (added bcrypt):**
|
|
119
|
+
```typescript
|
|
120
|
+
/**@darkarts
|
|
121
|
+
⊢{User authentication service}
|
|
122
|
+
∂{
|
|
123
|
+
jsonwebtoken: For JWT creation
|
|
124
|
+
bcrypt: For password hashing
|
|
125
|
+
}
|
|
126
|
+
*/
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 8. Important Commands
|
|
132
|
+
|
|
133
|
+
- **Validate:** `voodocs validate . --recursive`
|
|
134
|
+
- **Fix:** `voodocs fix . --recursive`
|
|
135
|
+
- **Generate Docs:** `voodocs generate . ./docs --recursive`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
By following these instructions, you will help us maintain a high-quality, machine-readable, and self-validating codebase. Thank you for your contribution!
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# AI Instructions for Symbolic DarkArts Annotations
|
|
2
|
+
|
|
3
|
+
**Version:** 2.0
|
|
4
|
+
**Date:** December 21, 2024
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Primary Goal
|
|
9
|
+
|
|
10
|
+
Your primary goal is to **write and maintain symbolic DarkArts annotations** for all new and existing code. This ensures that our documentation is always up-to-date, accurate, and machine-readable.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 2. Annotation Format: Symbolic DarkArts
|
|
15
|
+
|
|
16
|
+
**Always use the symbolic DarkArts format.** Do not use the natural language `@voodocs` format.
|
|
17
|
+
|
|
18
|
+
### Correct Format
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
/**@darkarts
|
|
22
|
+
⊢{Module purpose}
|
|
23
|
+
∂{Dependencies}
|
|
24
|
+
⚠{Assumptions}
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**@darkarts
|
|
28
|
+
⊳{Preconditions}
|
|
29
|
+
⊲{Postconditions}
|
|
30
|
+
⊨{Invariants}
|
|
31
|
+
⚡{Side effects / Complexity}
|
|
32
|
+
🔒{Security implications}
|
|
33
|
+
*/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Incorrect Format (Do Not Use)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
/**@voodocs
|
|
40
|
+
module_purpose: "..."
|
|
41
|
+
dependencies: [...]
|
|
42
|
+
*/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3. Key Rules
|
|
48
|
+
|
|
49
|
+
1. **Annotate Everything:** All modules, functions, classes, and interfaces must have a DarkArts annotation block.
|
|
50
|
+
2. **Use Symbolic Format Only:** Strictly adhere to the symbolic format (`⊢`, `∂`, `⚠`, `⊳`, `⊲`, `⊨`, `⚡`, `🔒`).
|
|
51
|
+
3. **Use Logic Symbols:** Use mathematical symbols for logic (`∧`, `∨`, `¬`, `∈`, `∃`, `∀`, `⇒`, `⇔`).
|
|
52
|
+
4. **Be Precise and Concise:** Annotations should be accurate and to the point.
|
|
53
|
+
5. **Validate Your Work:** After making changes, run `voodocs validate . --recursive` to ensure all annotations are correct.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Symbol Quick Reference
|
|
58
|
+
|
|
59
|
+
| Symbol | Meaning | Symbol | Meaning |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `⊢` | Module Purpose | `∧` | And |
|
|
62
|
+
| `∂` | Dependencies | `∨` | Or |
|
|
63
|
+
| `⚠` | Assumptions | `¬` | Not |
|
|
64
|
+
| `⊳` | Preconditions | `∈` | In |
|
|
65
|
+
| `⊲` | Postconditions | `∉` | Not In |
|
|
66
|
+
| `⊨` | Invariants | `∃` | Exists |
|
|
67
|
+
| `⚡` | Side Effects / Complexity | `∀` | For All |
|
|
68
|
+
| `🔒` | Security Implications | `⇒` | Implies |
|
|
69
|
+
| `⇔` | If and Only If | `⊤` | True |
|
|
70
|
+
| `⊥` | False | `∅` | Empty Set |
|
|
71
|
+
| `⊆` | Subset | `∪` | Union |
|
|
72
|
+
| `∩` | Intersection | | |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 5. Workflow
|
|
77
|
+
|
|
78
|
+
1. **When writing new code:** Add symbolic DarkArts annotations as you go.
|
|
79
|
+
2. **When modifying existing code:** Update the corresponding annotations to reflect your changes.
|
|
80
|
+
3. **Before committing:** Run `voodocs validate . --recursive` to catch any errors.
|
|
81
|
+
4. **If validation fails:** Run `voodocs fix . --recursive` to automatically fix common issues.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 6. Example: Adding a New Function
|
|
86
|
+
|
|
87
|
+
If you add a new function `getUserById`, you must add a symbolic annotation block:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
/**@darkarts
|
|
91
|
+
⊳{userId must be a valid UUID}
|
|
92
|
+
⊲{
|
|
93
|
+
Returns a user object if found
|
|
94
|
+
Returns null if ¬∃ user with that ID
|
|
95
|
+
}
|
|
96
|
+
⊨{Does ¬ modify the database}
|
|
97
|
+
⚡{O(1) lookup}
|
|
98
|
+
*/
|
|
99
|
+
export async function getUserById(userId: string): Promise<User | null> {
|
|
100
|
+
// ...
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 7. Example: Modifying a Module
|
|
107
|
+
|
|
108
|
+
If you add a new dependency to a module, update the `∂` field:
|
|
109
|
+
|
|
110
|
+
**Before:**
|
|
111
|
+
```typescript
|
|
112
|
+
/**@darkarts
|
|
113
|
+
⊢{User authentication service}
|
|
114
|
+
∂{jsonwebtoken}
|
|
115
|
+
*/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**After (added bcrypt):**
|
|
119
|
+
```typescript
|
|
120
|
+
/**@darkarts
|
|
121
|
+
⊢{User authentication service}
|
|
122
|
+
∂{
|
|
123
|
+
jsonwebtoken: For JWT creation
|
|
124
|
+
bcrypt: For password hashing
|
|
125
|
+
}
|
|
126
|
+
*/
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 8. Important Commands
|
|
132
|
+
|
|
133
|
+
- **Validate:** `voodocs validate . --recursive`
|
|
134
|
+
- **Fix:** `voodocs fix . --recursive`
|
|
135
|
+
- **Generate Docs:** `voodocs generate . ./docs --recursive`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
By following these instructions, you will help us maintain a high-quality, machine-readable, and self-validating codebase. Thank you for your contribution!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voodocs/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "AI-Native Documentation System with Validation - The only documentation tool that validates your annotations and guarantees accuracy",
|
|
5
5
|
"main": "voodocs_cli.py",
|
|
6
6
|
"bin": {
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"lib/darkarts/context/",
|
|
59
59
|
"lib/darkarts/core/",
|
|
60
60
|
"lib/darkarts/validation/",
|
|
61
|
+
"lib/darkarts/instructions/",
|
|
61
62
|
"lib/darkarts/exceptions.py",
|
|
62
63
|
"lib/darkarts/telemetry.py",
|
|
63
64
|
"lib/darkarts/parsers/typescript/dist/",
|