@voodocs/cli 0.3.1 → 0.4.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/CHANGELOG.md +454 -0
- package/cli.py +32 -3
- package/lib/darkarts/annotations/DARKARTS_SYMBOLS.md +529 -0
- package/lib/darkarts/annotations/TRANSFORMATION_EXAMPLES.md +478 -0
- package/lib/darkarts/annotations/__init__.py +42 -0
- package/lib/darkarts/annotations/darkarts_parser.py +238 -0
- package/lib/darkarts/annotations/parser.py +186 -5
- package/lib/darkarts/annotations/symbols.py +244 -0
- package/lib/darkarts/annotations/translator.py +386 -0
- package/lib/darkarts/context/ai_instructions.py +8 -1
- package/lib/darkarts/context/ai_integrations.py +22 -1
- package/lib/darkarts/context/checker.py +291 -40
- package/lib/darkarts/context/commands.py +375 -267
- package/lib/darkarts/context/diagram.py +22 -1
- package/lib/darkarts/context/errors.py +164 -0
- package/lib/darkarts/context/models.py +23 -1
- package/lib/darkarts/context/module_utils.py +198 -0
- package/lib/darkarts/context/ui.py +337 -0
- package/lib/darkarts/context/validation.py +311 -0
- package/lib/darkarts/context/yaml_utils.py +130 -16
- package/lib/darkarts/exceptions.py +5 -0
- package/lib/darkarts/plugins/voodocs/instruction_generator.py +8 -1
- package/package.json +1 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢symbols:darkarts.vocabulary
|
|
3
|
+
∂{typing,enum}
|
|
4
|
+
⚠{unicode-support,symbols-unique}
|
|
5
|
+
⊨{∀symbol→unique-meaning,bidirectional-mapping}
|
|
6
|
+
🔒{no-implications}
|
|
7
|
+
⚡{O(1)-lookup}
|
|
8
|
+
|
|
9
|
+
DarkArts Symbol Vocabulary
|
|
10
|
+
|
|
11
|
+
Defines all symbols used in DarkArts documentation language.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Dict, List, Optional, Set
|
|
15
|
+
from enum import Enum
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SymbolCategory(Enum):
|
|
20
|
+
"""Categories of DarkArts symbols."""
|
|
21
|
+
META = "meta" # Documentation structure (⊢, ∂, ⚠, ⊨)
|
|
22
|
+
LOGIC = "logic" # Logical operators (∀, ∃, ∧, ∨, ¬, ⇒)
|
|
23
|
+
SET = "set" # Set theory (∈, ⊂, ∪, ∩, ∅)
|
|
24
|
+
COMPARISON = "comparison" # Comparisons (=, ≠, <, >, ≤, ≥)
|
|
25
|
+
NUMBER_SET = "number_set" # Number sets (ℕ, ℤ, ℝ, ℂ)
|
|
26
|
+
STATE = "state" # State/flow (++, --, ⊳, ⊲)
|
|
27
|
+
ARROW = "arrow" # Arrows (→, ←, ⇒, ⇔)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class Symbol:
|
|
32
|
+
"""Represents a DarkArts symbol."""
|
|
33
|
+
unicode: str # Unicode character
|
|
34
|
+
name: str # Human-readable name
|
|
35
|
+
category: SymbolCategory
|
|
36
|
+
meaning: str # What it means
|
|
37
|
+
ascii: Optional[str] = None # ASCII equivalent (if any)
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return f"{self.unicode} ({self.name})"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class DarkArtsVocabulary:
|
|
44
|
+
"""
|
|
45
|
+
Complete vocabulary of DarkArts symbols.
|
|
46
|
+
|
|
47
|
+
Provides bidirectional mapping between symbols and meanings.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self):
|
|
51
|
+
"""Initialize the symbol vocabulary."""
|
|
52
|
+
self.symbols: Dict[str, Symbol] = {}
|
|
53
|
+
self.by_category: Dict[SymbolCategory, List[Symbol]] = {}
|
|
54
|
+
self.by_name: Dict[str, Symbol] = {}
|
|
55
|
+
|
|
56
|
+
self._init_meta_symbols()
|
|
57
|
+
self._init_logic_symbols()
|
|
58
|
+
self._init_set_symbols()
|
|
59
|
+
self._init_comparison_symbols()
|
|
60
|
+
self._init_number_sets()
|
|
61
|
+
self._init_state_symbols()
|
|
62
|
+
self._init_arrow_symbols()
|
|
63
|
+
|
|
64
|
+
def _add_symbol(self, unicode: str, name: str, category: SymbolCategory,
|
|
65
|
+
meaning: str, ascii: Optional[str] = None):
|
|
66
|
+
"""Add a symbol to the vocabulary."""
|
|
67
|
+
symbol = Symbol(unicode, name, category, meaning, ascii)
|
|
68
|
+
self.symbols[unicode] = symbol
|
|
69
|
+
self.by_name[name] = symbol
|
|
70
|
+
|
|
71
|
+
if category not in self.by_category:
|
|
72
|
+
self.by_category[category] = []
|
|
73
|
+
self.by_category[category].append(symbol)
|
|
74
|
+
|
|
75
|
+
def _init_meta_symbols(self):
|
|
76
|
+
"""Initialize meta/documentation structure symbols."""
|
|
77
|
+
self._add_symbol('⊢', 'turnstile', SymbolCategory.META,
|
|
78
|
+
'Module/component declaration', '|-')
|
|
79
|
+
self._add_symbol('∂', 'partial', SymbolCategory.META,
|
|
80
|
+
'Dependencies', 'd')
|
|
81
|
+
self._add_symbol('⚠', 'warning', SymbolCategory.META,
|
|
82
|
+
'Assumptions/preconditions', '!')
|
|
83
|
+
self._add_symbol('⊨', 'models', SymbolCategory.META,
|
|
84
|
+
'Invariants (must always be true)', '|=')
|
|
85
|
+
self._add_symbol('🔒', 'lock', SymbolCategory.META,
|
|
86
|
+
'Security model', '[lock]')
|
|
87
|
+
self._add_symbol('⚡', 'lightning', SymbolCategory.META,
|
|
88
|
+
'Performance model', '[perf]')
|
|
89
|
+
self._add_symbol('📊', 'chart', SymbolCategory.META,
|
|
90
|
+
'Complexity analysis', '[chart]')
|
|
91
|
+
self._add_symbol('🎯', 'target', SymbolCategory.META,
|
|
92
|
+
'Objectives/goals', '[goal]')
|
|
93
|
+
self._add_symbol('⚙️', 'gear', SymbolCategory.META,
|
|
94
|
+
'Configuration', '[config]')
|
|
95
|
+
|
|
96
|
+
def _init_logic_symbols(self):
|
|
97
|
+
"""Initialize logical operator symbols."""
|
|
98
|
+
self._add_symbol('∀', 'forall', SymbolCategory.LOGIC,
|
|
99
|
+
'For all', 'forall')
|
|
100
|
+
self._add_symbol('∃', 'exists', SymbolCategory.LOGIC,
|
|
101
|
+
'There exists', 'exists')
|
|
102
|
+
self._add_symbol('∧', 'and', SymbolCategory.LOGIC,
|
|
103
|
+
'Logical AND', 'and')
|
|
104
|
+
self._add_symbol('∨', 'or', SymbolCategory.LOGIC,
|
|
105
|
+
'Logical OR', 'or')
|
|
106
|
+
self._add_symbol('¬', 'not', SymbolCategory.LOGIC,
|
|
107
|
+
'Logical NOT', 'not')
|
|
108
|
+
self._add_symbol('⇒', 'implies', SymbolCategory.LOGIC,
|
|
109
|
+
'Implies (if...then)', '=>')
|
|
110
|
+
self._add_symbol('⇐', 'implied_by', SymbolCategory.LOGIC,
|
|
111
|
+
'Implied by', '<=')
|
|
112
|
+
self._add_symbol('⇔', 'iff', SymbolCategory.LOGIC,
|
|
113
|
+
'If and only if', '<=>')
|
|
114
|
+
self._add_symbol('⊕', 'xor', SymbolCategory.LOGIC,
|
|
115
|
+
'Exclusive OR', 'xor')
|
|
116
|
+
self._add_symbol('⊤', 'top', SymbolCategory.LOGIC,
|
|
117
|
+
'Always true / Success', 'true')
|
|
118
|
+
self._add_symbol('⊥', 'bottom', SymbolCategory.LOGIC,
|
|
119
|
+
'Always false / Error', 'false')
|
|
120
|
+
|
|
121
|
+
def _init_set_symbols(self):
|
|
122
|
+
"""Initialize set theory symbols."""
|
|
123
|
+
self._add_symbol('∈', 'in', SymbolCategory.SET,
|
|
124
|
+
'Element of / Member of', 'in')
|
|
125
|
+
self._add_symbol('∉', 'notin', SymbolCategory.SET,
|
|
126
|
+
'Not element of', 'notin')
|
|
127
|
+
self._add_symbol('⊂', 'subset', SymbolCategory.SET,
|
|
128
|
+
'Proper subset', 'subset')
|
|
129
|
+
self._add_symbol('⊃', 'supset', SymbolCategory.SET,
|
|
130
|
+
'Proper superset', 'supset')
|
|
131
|
+
self._add_symbol('⊆', 'subseteq', SymbolCategory.SET,
|
|
132
|
+
'Subset or equal', 'subseteq')
|
|
133
|
+
self._add_symbol('⊇', 'supseteq', SymbolCategory.SET,
|
|
134
|
+
'Superset or equal', 'supseteq')
|
|
135
|
+
self._add_symbol('∪', 'union', SymbolCategory.SET,
|
|
136
|
+
'Set union', 'union')
|
|
137
|
+
self._add_symbol('∩', 'intersect', SymbolCategory.SET,
|
|
138
|
+
'Set intersection', 'intersect')
|
|
139
|
+
self._add_symbol('∅', 'emptyset', SymbolCategory.SET,
|
|
140
|
+
'Empty set', 'emptyset')
|
|
141
|
+
|
|
142
|
+
def _init_comparison_symbols(self):
|
|
143
|
+
"""Initialize comparison operator symbols."""
|
|
144
|
+
self._add_symbol('=', 'equals', SymbolCategory.COMPARISON,
|
|
145
|
+
'Equals', '=')
|
|
146
|
+
self._add_symbol('≠', 'ne', SymbolCategory.COMPARISON,
|
|
147
|
+
'Not equals', '!=')
|
|
148
|
+
self._add_symbol('<', 'lt', SymbolCategory.COMPARISON,
|
|
149
|
+
'Less than', '<')
|
|
150
|
+
self._add_symbol('>', 'gt', SymbolCategory.COMPARISON,
|
|
151
|
+
'Greater than', '>')
|
|
152
|
+
self._add_symbol('≤', 'le', SymbolCategory.COMPARISON,
|
|
153
|
+
'Less than or equal', '<=')
|
|
154
|
+
self._add_symbol('≥', 'ge', SymbolCategory.COMPARISON,
|
|
155
|
+
'Greater than or equal', '>=')
|
|
156
|
+
self._add_symbol('≈', 'approx', SymbolCategory.COMPARISON,
|
|
157
|
+
'Approximately equal', '~=')
|
|
158
|
+
self._add_symbol('≡', 'equiv', SymbolCategory.COMPARISON,
|
|
159
|
+
'Identical / Definitionally equal', '==')
|
|
160
|
+
|
|
161
|
+
def _init_number_sets(self):
|
|
162
|
+
"""Initialize number set symbols."""
|
|
163
|
+
self._add_symbol('ℕ', 'naturals', SymbolCategory.NUMBER_SET,
|
|
164
|
+
'Natural numbers', 'N')
|
|
165
|
+
self._add_symbol('ℤ', 'integers', SymbolCategory.NUMBER_SET,
|
|
166
|
+
'Integers', 'Z')
|
|
167
|
+
self._add_symbol('ℚ', 'rationals', SymbolCategory.NUMBER_SET,
|
|
168
|
+
'Rational numbers', 'Q')
|
|
169
|
+
self._add_symbol('ℝ', 'reals', SymbolCategory.NUMBER_SET,
|
|
170
|
+
'Real numbers', 'R')
|
|
171
|
+
self._add_symbol('ℂ', 'complex', SymbolCategory.NUMBER_SET,
|
|
172
|
+
'Complex numbers', 'C')
|
|
173
|
+
self._add_symbol('ℙ', 'primes', SymbolCategory.NUMBER_SET,
|
|
174
|
+
'Prime numbers', 'P')
|
|
175
|
+
|
|
176
|
+
def _init_state_symbols(self):
|
|
177
|
+
"""Initialize state/flow operator symbols."""
|
|
178
|
+
self._add_symbol('++', 'increment', SymbolCategory.STATE,
|
|
179
|
+
'Increment by 1', '++')
|
|
180
|
+
self._add_symbol('--', 'decrement', SymbolCategory.STATE,
|
|
181
|
+
'Decrement by 1', '--')
|
|
182
|
+
self._add_symbol('+=', 'add_assign', SymbolCategory.STATE,
|
|
183
|
+
'Add and assign', '+=')
|
|
184
|
+
self._add_symbol('-=', 'sub_assign', SymbolCategory.STATE,
|
|
185
|
+
'Subtract and assign', '-=')
|
|
186
|
+
self._add_symbol('⊳', 'precondition', SymbolCategory.STATE,
|
|
187
|
+
'Precondition (must hold before)', '|>')
|
|
188
|
+
self._add_symbol('⊲', 'postcondition', SymbolCategory.STATE,
|
|
189
|
+
'Postcondition (must hold after)', '<|')
|
|
190
|
+
|
|
191
|
+
def _init_arrow_symbols(self):
|
|
192
|
+
"""Initialize arrow symbols."""
|
|
193
|
+
self._add_symbol('→', 'arrow_right', SymbolCategory.ARROW,
|
|
194
|
+
'Maps to / Leads to', '->')
|
|
195
|
+
self._add_symbol('←', 'arrow_left', SymbolCategory.ARROW,
|
|
196
|
+
'Comes from', '<-')
|
|
197
|
+
self._add_symbol('↔', 'arrow_both', SymbolCategory.ARROW,
|
|
198
|
+
'Bidirectional', '<->')
|
|
199
|
+
self._add_symbol('↦', 'mapsto', SymbolCategory.ARROW,
|
|
200
|
+
'Element maps to', '|->')
|
|
201
|
+
|
|
202
|
+
def get_symbol(self, unicode: str) -> Optional[Symbol]:
|
|
203
|
+
"""Get symbol by Unicode character."""
|
|
204
|
+
return self.symbols.get(unicode)
|
|
205
|
+
|
|
206
|
+
def get_by_name(self, name: str) -> Optional[Symbol]:
|
|
207
|
+
"""Get symbol by name."""
|
|
208
|
+
return self.by_name.get(name)
|
|
209
|
+
|
|
210
|
+
def get_category(self, category: SymbolCategory) -> List[Symbol]:
|
|
211
|
+
"""Get all symbols in a category."""
|
|
212
|
+
return self.by_category.get(category, [])
|
|
213
|
+
|
|
214
|
+
def is_symbol(self, char: str) -> bool:
|
|
215
|
+
"""Check if character is a DarkArts symbol."""
|
|
216
|
+
return char in self.symbols
|
|
217
|
+
|
|
218
|
+
def get_all_symbols(self) -> List[Symbol]:
|
|
219
|
+
"""Get all symbols."""
|
|
220
|
+
return list(self.symbols.values())
|
|
221
|
+
|
|
222
|
+
def get_meta_symbols(self) -> Set[str]:
|
|
223
|
+
"""Get set of meta symbols (⊢, ∂, ⚠, ⊨, etc.)."""
|
|
224
|
+
return {s.unicode for s in self.get_category(SymbolCategory.META)}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Global vocabulary instance
|
|
228
|
+
VOCABULARY = DarkArtsVocabulary()
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# Convenience functions
|
|
232
|
+
def get_symbol(unicode: str) -> Optional[Symbol]:
|
|
233
|
+
"""Get symbol by Unicode character."""
|
|
234
|
+
return VOCABULARY.get_symbol(unicode)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def is_darkarts_symbol(char: str) -> bool:
|
|
238
|
+
"""Check if character is a DarkArts symbol."""
|
|
239
|
+
return VOCABULARY.is_symbol(char)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def get_meta_symbols() -> Set[str]:
|
|
243
|
+
"""Get set of meta symbols."""
|
|
244
|
+
return VOCABULARY.get_meta_symbols()
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢translator:darkarts↔natural-lang
|
|
3
|
+
∂{re,typing,symbols,darkarts_parser}
|
|
4
|
+
⚠{bidirectional,preserves-meaning}
|
|
5
|
+
⊨{∀translate→reversible,readable,accurate}
|
|
6
|
+
🔒{no-implications}
|
|
7
|
+
⚡{O(n)|n=text-length}
|
|
8
|
+
|
|
9
|
+
DarkArts Bidirectional Translator
|
|
10
|
+
|
|
11
|
+
Translates between DarkArts symbolic notation and natural language.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
from typing import Dict, List, Optional
|
|
16
|
+
from .symbols import VOCABULARY
|
|
17
|
+
from .darkarts_parser import DarkArtsAnnotation, DarkArtsParser
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class DarkArtsTranslator:
|
|
21
|
+
"""
|
|
22
|
+
Bidirectional translator between DarkArts symbols and natural language.
|
|
23
|
+
|
|
24
|
+
Supports:
|
|
25
|
+
- Symbols → Natural Language (for humans)
|
|
26
|
+
- Natural Language → Symbols (for writing)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
"""Initialize the translator."""
|
|
31
|
+
self.vocab = VOCABULARY
|
|
32
|
+
|
|
33
|
+
# Symbol → English mappings
|
|
34
|
+
self.symbol_to_english = {
|
|
35
|
+
'⊢': 'Module',
|
|
36
|
+
'∂': 'Dependencies',
|
|
37
|
+
'⚠': 'Assumptions',
|
|
38
|
+
'⊨': 'Invariants',
|
|
39
|
+
'🔒': 'Security Model',
|
|
40
|
+
'⚡': 'Performance',
|
|
41
|
+
'📊': 'Complexity',
|
|
42
|
+
'🎯': 'Objectives',
|
|
43
|
+
'⚙️': 'Configuration',
|
|
44
|
+
'∀': 'for all',
|
|
45
|
+
'∃': 'there exists',
|
|
46
|
+
'∧': 'and',
|
|
47
|
+
'∨': 'or',
|
|
48
|
+
'¬': 'not',
|
|
49
|
+
'⇒': 'implies',
|
|
50
|
+
'⇐': 'implied by',
|
|
51
|
+
'⇔': 'if and only if',
|
|
52
|
+
'∈': 'in',
|
|
53
|
+
'∉': 'not in',
|
|
54
|
+
'⊂': 'subset of',
|
|
55
|
+
'⊆': 'subset or equal to',
|
|
56
|
+
'∪': 'union',
|
|
57
|
+
'∩': 'intersection',
|
|
58
|
+
'∅': 'empty set',
|
|
59
|
+
'→': 'leads to',
|
|
60
|
+
'←': 'comes from',
|
|
61
|
+
'↔': 'bidirectional',
|
|
62
|
+
'⊤': 'success',
|
|
63
|
+
'⊥': 'failure',
|
|
64
|
+
'≤': 'less than or equal to',
|
|
65
|
+
'≥': 'greater than or equal to',
|
|
66
|
+
'≠': 'not equal to',
|
|
67
|
+
'≈': 'approximately',
|
|
68
|
+
'≡': 'identical to',
|
|
69
|
+
'++': 'increment',
|
|
70
|
+
'--': 'decrement',
|
|
71
|
+
'⊳': 'precondition',
|
|
72
|
+
'⊲': 'postcondition',
|
|
73
|
+
'ℕ': 'natural numbers',
|
|
74
|
+
'ℤ': 'integers',
|
|
75
|
+
'ℚ': 'rationals',
|
|
76
|
+
'ℝ': 'real numbers',
|
|
77
|
+
'ℂ': 'complex numbers',
|
|
78
|
+
'ℙ': 'prime numbers',
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# English → Symbol mappings (reverse)
|
|
82
|
+
self.english_to_symbol = {v: k for k, v in self.symbol_to_english.items()}
|
|
83
|
+
|
|
84
|
+
# Add common variations
|
|
85
|
+
self.english_to_symbol.update({
|
|
86
|
+
'for every': '∀',
|
|
87
|
+
'for each': '∀',
|
|
88
|
+
'exists': '∃',
|
|
89
|
+
'then': '⇒',
|
|
90
|
+
'if': '⇒',
|
|
91
|
+
'iff': '⇔',
|
|
92
|
+
'element of': '∈',
|
|
93
|
+
'member of': '∈',
|
|
94
|
+
'not element of': '∉',
|
|
95
|
+
'true': '⊤',
|
|
96
|
+
'false': '⊥',
|
|
97
|
+
'error': '⊥',
|
|
98
|
+
'less or equal': '≤',
|
|
99
|
+
'greater or equal': '≥',
|
|
100
|
+
'not equal': '≠',
|
|
101
|
+
'approximately equal': '≈',
|
|
102
|
+
'equal': '=',
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
def symbols_to_natural(self, annotation: DarkArtsAnnotation) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Translate DarkArts annotation to natural language.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
annotation: Parsed DarkArts annotation
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Natural language description
|
|
114
|
+
"""
|
|
115
|
+
lines = []
|
|
116
|
+
|
|
117
|
+
# Module
|
|
118
|
+
if annotation.module:
|
|
119
|
+
lines.append(f"**Module**: {annotation.module}")
|
|
120
|
+
lines.append("")
|
|
121
|
+
|
|
122
|
+
# Dependencies
|
|
123
|
+
if annotation.dependencies:
|
|
124
|
+
lines.append("**Dependencies**:")
|
|
125
|
+
for dep in annotation.dependencies:
|
|
126
|
+
# Check if dep has description (format: "name:description")
|
|
127
|
+
if ':' in dep:
|
|
128
|
+
name, desc = dep.split(':', 1)
|
|
129
|
+
lines.append(f" - {name}: {desc}")
|
|
130
|
+
else:
|
|
131
|
+
lines.append(f" - {dep}")
|
|
132
|
+
lines.append("")
|
|
133
|
+
|
|
134
|
+
# Assumptions
|
|
135
|
+
if annotation.assumptions:
|
|
136
|
+
lines.append("**Assumptions**:")
|
|
137
|
+
for assumption in annotation.assumptions:
|
|
138
|
+
translated = self._translate_expression(assumption)
|
|
139
|
+
lines.append(f" - {translated}")
|
|
140
|
+
lines.append("")
|
|
141
|
+
|
|
142
|
+
# Invariants
|
|
143
|
+
if annotation.invariants:
|
|
144
|
+
lines.append("**Invariants**:")
|
|
145
|
+
for invariant in annotation.invariants:
|
|
146
|
+
translated = self._translate_expression(invariant)
|
|
147
|
+
lines.append(f" - {translated}")
|
|
148
|
+
lines.append("")
|
|
149
|
+
|
|
150
|
+
# Security
|
|
151
|
+
if annotation.security:
|
|
152
|
+
lines.append(f"**Security Model**: {self._translate_expression(annotation.security)}")
|
|
153
|
+
lines.append("")
|
|
154
|
+
|
|
155
|
+
# Performance
|
|
156
|
+
if annotation.performance:
|
|
157
|
+
lines.append(f"**Performance**: {self._translate_expression(annotation.performance)}")
|
|
158
|
+
lines.append("")
|
|
159
|
+
|
|
160
|
+
# Complexity
|
|
161
|
+
if annotation.complexity:
|
|
162
|
+
lines.append(f"**Complexity**: {self._translate_expression(annotation.complexity)}")
|
|
163
|
+
lines.append("")
|
|
164
|
+
|
|
165
|
+
# Objectives
|
|
166
|
+
if annotation.objectives:
|
|
167
|
+
lines.append(f"**Objectives**: {self._translate_expression(annotation.objectives)}")
|
|
168
|
+
lines.append("")
|
|
169
|
+
|
|
170
|
+
# Configuration
|
|
171
|
+
if annotation.configuration:
|
|
172
|
+
lines.append(f"**Configuration**: {self._translate_expression(annotation.configuration)}")
|
|
173
|
+
lines.append("")
|
|
174
|
+
|
|
175
|
+
return '\n'.join(lines).strip()
|
|
176
|
+
|
|
177
|
+
def _translate_expression(self, expr: str) -> str:
|
|
178
|
+
"""
|
|
179
|
+
Translate a symbolic expression to natural language.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
expr: Symbolic expression
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Natural language translation
|
|
186
|
+
"""
|
|
187
|
+
result = expr
|
|
188
|
+
|
|
189
|
+
# Replace symbols with English
|
|
190
|
+
for symbol, english in self.symbol_to_english.items():
|
|
191
|
+
result = result.replace(symbol, f" {english} ")
|
|
192
|
+
|
|
193
|
+
# Clean up spacing
|
|
194
|
+
result = re.sub(r'\s+', ' ', result).strip()
|
|
195
|
+
|
|
196
|
+
# Capitalize first letter
|
|
197
|
+
if result:
|
|
198
|
+
result = result[0].upper() + result[1:]
|
|
199
|
+
|
|
200
|
+
return result
|
|
201
|
+
|
|
202
|
+
def natural_to_symbols(self, text: str) -> str:
|
|
203
|
+
"""
|
|
204
|
+
Translate natural language to DarkArts symbols.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
text: Natural language description
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Symbolic notation
|
|
211
|
+
"""
|
|
212
|
+
result = text.lower()
|
|
213
|
+
|
|
214
|
+
# Replace English phrases with symbols
|
|
215
|
+
# Sort by length (longest first) to avoid partial matches
|
|
216
|
+
phrases = sorted(self.english_to_symbol.items(),
|
|
217
|
+
key=lambda x: len(x[0]), reverse=True)
|
|
218
|
+
|
|
219
|
+
for english, symbol in phrases:
|
|
220
|
+
result = result.replace(english, symbol)
|
|
221
|
+
|
|
222
|
+
return result
|
|
223
|
+
|
|
224
|
+
def translate_file(self, file_path: str, to_natural: bool = True) -> str:
|
|
225
|
+
"""
|
|
226
|
+
Translate all @darkarts annotations in a file.
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
file_path: Path to source file
|
|
230
|
+
to_natural: If True, translate to natural language;
|
|
231
|
+
if False, translate to symbols
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Translated content
|
|
235
|
+
"""
|
|
236
|
+
parser = DarkArtsParser()
|
|
237
|
+
annotations = parser.parse_file(file_path)
|
|
238
|
+
|
|
239
|
+
if to_natural:
|
|
240
|
+
# Translate to natural language
|
|
241
|
+
results = []
|
|
242
|
+
for i, annotation in enumerate(annotations, 1):
|
|
243
|
+
results.append(f"## Annotation {i}\n")
|
|
244
|
+
results.append(self.symbols_to_natural(annotation))
|
|
245
|
+
results.append("\n---\n")
|
|
246
|
+
return '\n'.join(results)
|
|
247
|
+
else:
|
|
248
|
+
# Already in symbols, just return raw text
|
|
249
|
+
return '\n\n'.join(a.raw_text for a in annotations)
|
|
250
|
+
|
|
251
|
+
def translate_annotation_text(self, text: str) -> str:
|
|
252
|
+
"""
|
|
253
|
+
Translate a @darkarts annotation text to natural language.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
text: Annotation text (without @darkarts marker)
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
Natural language translation
|
|
260
|
+
"""
|
|
261
|
+
parser = DarkArtsParser()
|
|
262
|
+
annotation = parser.parse_annotation(text)
|
|
263
|
+
return self.symbols_to_natural(annotation)
|
|
264
|
+
|
|
265
|
+
def create_darkarts_from_voodocs(self, voodocs_dict: Dict) -> str:
|
|
266
|
+
"""
|
|
267
|
+
Create @darkarts annotation from @voodocs dictionary.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
voodocs_dict: Dictionary with keys like 'module_purpose',
|
|
271
|
+
'dependencies', 'assumptions', 'invariants', etc.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
DarkArts annotation text
|
|
275
|
+
"""
|
|
276
|
+
lines = ['"""@darkarts']
|
|
277
|
+
|
|
278
|
+
# Module
|
|
279
|
+
if 'module_purpose' in voodocs_dict:
|
|
280
|
+
purpose = voodocs_dict['module_purpose']
|
|
281
|
+
# Extract key parts (simplified)
|
|
282
|
+
lines.append(f"⊢{purpose}")
|
|
283
|
+
|
|
284
|
+
# Dependencies
|
|
285
|
+
if 'dependencies' in voodocs_dict:
|
|
286
|
+
deps = voodocs_dict['dependencies']
|
|
287
|
+
if isinstance(deps, list):
|
|
288
|
+
# Simplify dependencies
|
|
289
|
+
simplified = []
|
|
290
|
+
for dep in deps:
|
|
291
|
+
if ':' in dep:
|
|
292
|
+
name, _ = dep.split(':', 1)
|
|
293
|
+
simplified.append(name.strip())
|
|
294
|
+
else:
|
|
295
|
+
simplified.append(dep.strip())
|
|
296
|
+
lines.append(f"∂{{{','.join(simplified)}}}")
|
|
297
|
+
|
|
298
|
+
# Assumptions
|
|
299
|
+
if 'assumptions' in voodocs_dict:
|
|
300
|
+
assumptions = voodocs_dict['assumptions']
|
|
301
|
+
if isinstance(assumptions, list):
|
|
302
|
+
# Simplify assumptions
|
|
303
|
+
simplified = [self._simplify_assumption(a) for a in assumptions]
|
|
304
|
+
lines.append(f"⚠{{{','.join(simplified)}}}")
|
|
305
|
+
|
|
306
|
+
# Invariants
|
|
307
|
+
if 'invariants' in voodocs_dict:
|
|
308
|
+
invariants = voodocs_dict['invariants']
|
|
309
|
+
if isinstance(invariants, list):
|
|
310
|
+
# Convert to symbolic notation
|
|
311
|
+
symbolic = [self._convert_invariant(inv) for inv in invariants]
|
|
312
|
+
lines.append(f"⊨{{{','.join(symbolic)}}}")
|
|
313
|
+
|
|
314
|
+
# Security
|
|
315
|
+
if 'security_model' in voodocs_dict:
|
|
316
|
+
security = self._simplify_text(voodocs_dict['security_model'])
|
|
317
|
+
lines.append(f"🔒{{{security}}}")
|
|
318
|
+
|
|
319
|
+
# Performance
|
|
320
|
+
if 'performance_model' in voodocs_dict:
|
|
321
|
+
perf = voodocs_dict['performance_model']
|
|
322
|
+
lines.append(f"⚡{{{perf}}}")
|
|
323
|
+
|
|
324
|
+
lines.append('"""')
|
|
325
|
+
return '\n'.join(lines)
|
|
326
|
+
|
|
327
|
+
def _simplify_assumption(self, assumption: str) -> str:
|
|
328
|
+
"""Simplify an assumption to compact form."""
|
|
329
|
+
# Remove common prefixes
|
|
330
|
+
assumption = assumption.lower()
|
|
331
|
+
for prefix in ['assume', 'assumes', 'assuming', 'we assume']:
|
|
332
|
+
if assumption.startswith(prefix):
|
|
333
|
+
assumption = assumption[len(prefix):].strip()
|
|
334
|
+
|
|
335
|
+
# Convert to symbolic notation where possible
|
|
336
|
+
assumption = self.natural_to_symbols(assumption)
|
|
337
|
+
|
|
338
|
+
return assumption
|
|
339
|
+
|
|
340
|
+
def _convert_invariant(self, invariant: str) -> str:
|
|
341
|
+
"""Convert an invariant to symbolic notation."""
|
|
342
|
+
# Convert "must" patterns
|
|
343
|
+
invariant = invariant.lower()
|
|
344
|
+
|
|
345
|
+
# "all X must Y" → "∀X→Y"
|
|
346
|
+
invariant = re.sub(r'all (\w+) must (\w+)', r'∀\1→\2', invariant)
|
|
347
|
+
|
|
348
|
+
# "X must Y" → "X→Y"
|
|
349
|
+
invariant = re.sub(r'(\w+) must (\w+)', r'\1→\2', invariant)
|
|
350
|
+
|
|
351
|
+
# Convert common phrases to symbols
|
|
352
|
+
invariant = self.natural_to_symbols(invariant)
|
|
353
|
+
|
|
354
|
+
return invariant
|
|
355
|
+
|
|
356
|
+
def _simplify_text(self, text: str) -> str:
|
|
357
|
+
"""Simplify text to compact form."""
|
|
358
|
+
# Remove articles
|
|
359
|
+
text = re.sub(r'\b(a|an|the)\b', '', text, flags=re.IGNORECASE)
|
|
360
|
+
|
|
361
|
+
# Remove extra spaces
|
|
362
|
+
text = re.sub(r'\s+', ' ', text).strip()
|
|
363
|
+
|
|
364
|
+
# Convert to symbols
|
|
365
|
+
text = self.natural_to_symbols(text)
|
|
366
|
+
|
|
367
|
+
return text
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
# Convenience functions
|
|
371
|
+
def translate_to_natural(annotation: DarkArtsAnnotation) -> str:
|
|
372
|
+
"""Translate DarkArts annotation to natural language."""
|
|
373
|
+
translator = DarkArtsTranslator()
|
|
374
|
+
return translator.symbols_to_natural(annotation)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def translate_to_symbols(text: str) -> str:
|
|
378
|
+
"""Translate natural language to DarkArts symbols."""
|
|
379
|
+
translator = DarkArtsTranslator()
|
|
380
|
+
return translator.natural_to_symbols(text)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def convert_voodocs_to_darkarts(voodocs_dict: Dict) -> str:
|
|
384
|
+
"""Convert @voodocs dictionary to @darkarts annotation."""
|
|
385
|
+
translator = DarkArtsTranslator()
|
|
386
|
+
return translator.create_darkarts_from_voodocs(voodocs_dict)
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢ai-instructions:ctx.templates
|
|
3
|
+
∂{typing}
|
|
4
|
+
⚠{ai:cursor∨claude,project:voodocs-enabled,templates:markdown}
|
|
5
|
+
⊨{∀gen→valid-markdown,∀gen→include-cmds,∀gen→teach-best-practices}
|
|
6
|
+
🔒{no-implications}
|
|
7
|
+
⚡{O(1)|template-generation}
|
|
8
|
+
|
|
2
9
|
AI instruction templates for VooDocs Context System.
|
|
3
10
|
|
|
4
11
|
This module provides templates for generating AI assistant instructions
|
|
@@ -1,4 +1,25 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""@voodocs
|
|
2
|
+
module_purpose: "Native AI assistant integrations (Claude, Cursor, Copilot, Windsurf, Cline)"
|
|
3
|
+
dependencies: [
|
|
4
|
+
"pathlib: File path handling",
|
|
5
|
+
"typing: Type hints"
|
|
6
|
+
]
|
|
7
|
+
assumptions: [
|
|
8
|
+
"AI config directories follow standard conventions (.claude/skills/, .cursor/rules/, etc.)",
|
|
9
|
+
"Project root is current working directory",
|
|
10
|
+
"File system allows directory creation",
|
|
11
|
+
"UTF-8 encoding is supported"
|
|
12
|
+
]
|
|
13
|
+
invariants: [
|
|
14
|
+
"All generated configs must be valid for their respective AIs",
|
|
15
|
+
"Detection must not modify any files",
|
|
16
|
+
"Generated content must be UTF-8 encoded",
|
|
17
|
+
"File paths must use forward slashes for cross-platform compatibility",
|
|
18
|
+
"Each AI integration must return Dict[str, str] mapping paths to content"
|
|
19
|
+
]
|
|
20
|
+
security_model: "Read-only detection, write only when explicitly called by user commands"
|
|
21
|
+
performance_model: "O(1) for detection, O(k) for generation where k=number of AI assistants"
|
|
22
|
+
|
|
2
23
|
AI-specific integration templates for VooDocs Context System.
|
|
3
24
|
|
|
4
25
|
This module provides native integration with different AI assistants:
|