@voodocs/cli 2.5.0 → 2.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/lib/cli/__init__.py +7 -1
- package/lib/cli/analyze.py +156 -98
- package/lib/cli/convert.py +131 -0
- package/lib/darkarts/priority_analyzer/__init__.py +0 -0
- package/lib/darkarts/priority_analyzer/analyzer.py +301 -0
- package/lib/darkarts/priority_analyzer/complexity.py +271 -0
- package/lib/darkarts/priority_analyzer/dependencies.py +275 -0
- package/lib/darkarts/priority_analyzer/security.py +200 -0
- package/lib/darkarts/voodocs_lite_dict.py +216 -0
- package/lib/darkarts/voodocs_lite_dict_v2.py +198 -0
- package/lib/darkarts/voodocs_lite_parser.py +343 -0
- package/package.json +5 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
VooDocs Lite - Ultra-Aggressive Abbreviation Dictionary v2
|
|
3
|
+
|
|
4
|
+
Provides maximum compression by:
|
|
5
|
+
1. Removing articles (a, an, the)
|
|
6
|
+
2. Removing unnecessary words
|
|
7
|
+
3. Using aggressive abbreviations
|
|
8
|
+
4. Using symbols instead of words
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Core abbreviations
|
|
12
|
+
CORE_ABBR = {
|
|
13
|
+
# Entities
|
|
14
|
+
'user': 'u',
|
|
15
|
+
'users': 'us',
|
|
16
|
+
'database': 'db',
|
|
17
|
+
'token': 'tok',
|
|
18
|
+
'password': 'pw',
|
|
19
|
+
'authentication': 'auth',
|
|
20
|
+
'authorization': 'authz',
|
|
21
|
+
'service': 'svc',
|
|
22
|
+
'function': 'fn',
|
|
23
|
+
'identifier': 'id',
|
|
24
|
+
'configuration': 'cfg',
|
|
25
|
+
'parameter': 'p',
|
|
26
|
+
'argument': 'a',
|
|
27
|
+
'variable': 'v',
|
|
28
|
+
'constant': 'c',
|
|
29
|
+
'timestamp': 'ts',
|
|
30
|
+
'expiration': 'exp',
|
|
31
|
+
'response': 'r',
|
|
32
|
+
'request': 'q',
|
|
33
|
+
'error': 'e',
|
|
34
|
+
'exception': 'x',
|
|
35
|
+
|
|
36
|
+
# Actions (ultra-short)
|
|
37
|
+
'initialize': 'init',
|
|
38
|
+
'validate': 'val',
|
|
39
|
+
'verify': 'ver',
|
|
40
|
+
'generate': 'gen',
|
|
41
|
+
'create': 'cr',
|
|
42
|
+
'update': 'upd',
|
|
43
|
+
'delete': 'del',
|
|
44
|
+
'modify': 'mod',
|
|
45
|
+
'retrieve': 'get',
|
|
46
|
+
'query': 'qry',
|
|
47
|
+
'check': 'chk',
|
|
48
|
+
'returns': 'ret',
|
|
49
|
+
'contains': 'has',
|
|
50
|
+
|
|
51
|
+
# Blockchain
|
|
52
|
+
'address': 'addr',
|
|
53
|
+
'contract': 'ctr',
|
|
54
|
+
'transaction': 'tx',
|
|
55
|
+
'block': 'blk',
|
|
56
|
+
'balance': 'bal',
|
|
57
|
+
'amount': 'amt',
|
|
58
|
+
'subdomain': 'sub',
|
|
59
|
+
'registry': 'reg',
|
|
60
|
+
'owner': 'own',
|
|
61
|
+
|
|
62
|
+
# Common words
|
|
63
|
+
'with': 'w/',
|
|
64
|
+
'without': 'wo/',
|
|
65
|
+
'management': 'mgmt',
|
|
66
|
+
'system': 'sys',
|
|
67
|
+
'operations': 'ops',
|
|
68
|
+
'result': 'res',
|
|
69
|
+
'value': 'val',
|
|
70
|
+
'length': 'len',
|
|
71
|
+
'count': 'cnt',
|
|
72
|
+
'maximum': 'max',
|
|
73
|
+
'minimum': 'min',
|
|
74
|
+
'average': 'avg',
|
|
75
|
+
'information': 'info',
|
|
76
|
+
'specification': 'spec',
|
|
77
|
+
'implementation': 'impl',
|
|
78
|
+
'reference': 'ref',
|
|
79
|
+
'definition': 'def',
|
|
80
|
+
'description': 'desc',
|
|
81
|
+
|
|
82
|
+
# Types
|
|
83
|
+
'string': 'str',
|
|
84
|
+
'number': 'num',
|
|
85
|
+
'integer': 'int',
|
|
86
|
+
'boolean': 'bool',
|
|
87
|
+
'array': 'arr',
|
|
88
|
+
'object': 'obj',
|
|
89
|
+
|
|
90
|
+
# Boolean/Values
|
|
91
|
+
'true': 'T',
|
|
92
|
+
'false': 'F',
|
|
93
|
+
'null': 'N',
|
|
94
|
+
'undefined': 'U',
|
|
95
|
+
'empty': 'E',
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Words to remove entirely
|
|
99
|
+
REMOVE_WORDS = {'a', 'an', 'the', 'is', 'are', 'be', 'been', 'being', 'was', 'were', 'will', 'would', 'should', 'could', 'may', 'might', 'can', 'must'}
|
|
100
|
+
|
|
101
|
+
# Symbol replacements
|
|
102
|
+
SYMBOL_REPLACEMENTS = {
|
|
103
|
+
' and ': '&',
|
|
104
|
+
' or ': '|',
|
|
105
|
+
' not ': '!',
|
|
106
|
+
'greater than or equal': '>=',
|
|
107
|
+
'less than or equal': '<=',
|
|
108
|
+
'greater than': '>',
|
|
109
|
+
'less than': '<',
|
|
110
|
+
'equal to': '=',
|
|
111
|
+
'not equal': '!=',
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def ultra_compress(text: str) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Ultra-aggressive compression.
|
|
118
|
+
|
|
119
|
+
Steps:
|
|
120
|
+
1. Replace symbols
|
|
121
|
+
2. Remove articles and unnecessary words
|
|
122
|
+
3. Apply abbreviations
|
|
123
|
+
4. Remove extra whitespace
|
|
124
|
+
"""
|
|
125
|
+
# Step 1: Symbol replacements (longest first)
|
|
126
|
+
for phrase, symbol in sorted(SYMBOL_REPLACEMENTS.items(), key=lambda x: -len(x[0])):
|
|
127
|
+
text = text.replace(phrase, symbol)
|
|
128
|
+
|
|
129
|
+
# Step 2: Split into words
|
|
130
|
+
words = text.split()
|
|
131
|
+
|
|
132
|
+
# Step 3: Process each word
|
|
133
|
+
compressed_words = []
|
|
134
|
+
for word in words:
|
|
135
|
+
# Check for punctuation
|
|
136
|
+
punct = ''
|
|
137
|
+
if word and word[-1] in '.,;:!?':
|
|
138
|
+
punct = word[-1]
|
|
139
|
+
word = word[:-1]
|
|
140
|
+
|
|
141
|
+
# Convert to lowercase for matching
|
|
142
|
+
word_lower = word.lower()
|
|
143
|
+
|
|
144
|
+
# Skip if in remove list
|
|
145
|
+
if word_lower in REMOVE_WORDS:
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
# Apply abbreviation if exists
|
|
149
|
+
if word_lower in CORE_ABBR:
|
|
150
|
+
compressed_words.append(CORE_ABBR[word_lower] + punct)
|
|
151
|
+
else:
|
|
152
|
+
compressed_words.append(word + punct)
|
|
153
|
+
|
|
154
|
+
# Step 4: Join and clean up
|
|
155
|
+
result = ' '.join(compressed_words)
|
|
156
|
+
|
|
157
|
+
# Remove spaces around symbols
|
|
158
|
+
result = result.replace(' & ', '&')
|
|
159
|
+
result = result.replace(' | ', '|')
|
|
160
|
+
result = result.replace(' >= ', '>=')
|
|
161
|
+
result = result.replace(' <= ', '<=')
|
|
162
|
+
result = result.replace(' != ', '!=')
|
|
163
|
+
|
|
164
|
+
return result
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def ultra_expand(text: str) -> str:
|
|
168
|
+
"""
|
|
169
|
+
Expand ultra-compressed text back to full form.
|
|
170
|
+
"""
|
|
171
|
+
# Reverse mapping
|
|
172
|
+
ABBR_TO_FULL = {v: k for k, v in CORE_ABBR.items()}
|
|
173
|
+
|
|
174
|
+
# Step 1: Add spaces around symbols
|
|
175
|
+
text = text.replace('&', ' and ')
|
|
176
|
+
text = text.replace('|', ' or ')
|
|
177
|
+
text = text.replace('>=', ' greater than or equal ')
|
|
178
|
+
text = text.replace('<=', ' less than or equal ')
|
|
179
|
+
text = text.replace('!=', ' not equal ')
|
|
180
|
+
|
|
181
|
+
# Step 2: Split and expand
|
|
182
|
+
words = text.split()
|
|
183
|
+
expanded_words = []
|
|
184
|
+
|
|
185
|
+
for word in words:
|
|
186
|
+
# Check for punctuation
|
|
187
|
+
punct = ''
|
|
188
|
+
if word and word[-1] in '.,;:!?':
|
|
189
|
+
punct = word[-1]
|
|
190
|
+
word = word[:-1]
|
|
191
|
+
|
|
192
|
+
# Expand if abbreviation exists
|
|
193
|
+
if word in ABBR_TO_FULL:
|
|
194
|
+
expanded_words.append(ABBR_TO_FULL[word] + punct)
|
|
195
|
+
else:
|
|
196
|
+
expanded_words.append(word + punct)
|
|
197
|
+
|
|
198
|
+
return ' '.join(expanded_words)
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"""
|
|
2
|
+
VooDocs Lite Parser
|
|
3
|
+
|
|
4
|
+
Parses VooDocs Lite format and converts between Lite and Standard formats.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import re
|
|
8
|
+
from typing import Dict, Optional
|
|
9
|
+
from .voodocs_lite_dict import (
|
|
10
|
+
expand_text,
|
|
11
|
+
compress_text,
|
|
12
|
+
get_lite_symbol,
|
|
13
|
+
get_standard_symbol,
|
|
14
|
+
LITE_TO_STANDARD,
|
|
15
|
+
STANDARD_TO_LITE,
|
|
16
|
+
)
|
|
17
|
+
from .voodocs_lite_dict_v2 import ultra_compress, ultra_expand
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class VooDocsLiteParser:
|
|
21
|
+
"""Parser for VooDocs Lite format."""
|
|
22
|
+
|
|
23
|
+
# Lite format patterns
|
|
24
|
+
LITE_PATTERNS = {
|
|
25
|
+
'purpose': r'^>\s*(.+)$',
|
|
26
|
+
'dependencies': r'^@\s*(.+)$',
|
|
27
|
+
'assumptions': r'^!\s*(.+)$',
|
|
28
|
+
'preconditions': r'^<\s*(.+)$',
|
|
29
|
+
'postconditions': r'^>\s*(.+)$', # Same as purpose, context-dependent
|
|
30
|
+
'invariants': r'^=\s*(.+)$',
|
|
31
|
+
'complexity': r'^~\s*(.+)$',
|
|
32
|
+
'security': r'^#\s*(.+)$',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Standard format patterns
|
|
36
|
+
STANDARD_PATTERNS = {
|
|
37
|
+
'purpose': r'⊢\{([^}]+)\}',
|
|
38
|
+
'dependencies': r'∂\{([^}]+)\}',
|
|
39
|
+
'assumptions': r'⚠\{([^}]+)\}',
|
|
40
|
+
'preconditions': r'⊳\{([^}]+)\}',
|
|
41
|
+
'postconditions': r'⊲\{([^}]+)\}',
|
|
42
|
+
'invariants': r'⊨\{([^}]+)\}',
|
|
43
|
+
'complexity': r'⚡\{([^}]+)\}',
|
|
44
|
+
'security': r'🔒\{([^}]+)\}',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def parse_lite(cls, content: str) -> Dict[str, any]:
|
|
49
|
+
"""
|
|
50
|
+
Parse VooDocs Lite format annotation.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
content: Lite format annotation text
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Dictionary with parsed fields
|
|
57
|
+
"""
|
|
58
|
+
result = {
|
|
59
|
+
'purpose': None,
|
|
60
|
+
'dependencies': [],
|
|
61
|
+
'assumptions': [],
|
|
62
|
+
'preconditions': [],
|
|
63
|
+
'postconditions': [],
|
|
64
|
+
'invariants': [],
|
|
65
|
+
'complexity': None,
|
|
66
|
+
'security': [],
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
lines = content.strip().split('\n')
|
|
70
|
+
|
|
71
|
+
for line in lines:
|
|
72
|
+
line = line.strip()
|
|
73
|
+
if not line:
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
# Check each pattern
|
|
77
|
+
if line.startswith('>'):
|
|
78
|
+
# Could be purpose or postcondition
|
|
79
|
+
# If we already have purpose, it's postcondition
|
|
80
|
+
match = re.match(cls.LITE_PATTERNS['purpose'], line)
|
|
81
|
+
if match:
|
|
82
|
+
value = match.group(1).strip()
|
|
83
|
+
if result['purpose'] is None:
|
|
84
|
+
result['purpose'] = value
|
|
85
|
+
else:
|
|
86
|
+
result['postconditions'].append(value)
|
|
87
|
+
|
|
88
|
+
elif line.startswith('@'):
|
|
89
|
+
match = re.match(cls.LITE_PATTERNS['dependencies'], line)
|
|
90
|
+
if match:
|
|
91
|
+
deps = match.group(1).strip()
|
|
92
|
+
# Split by comma
|
|
93
|
+
result['dependencies'] = [d.strip() for d in deps.split(',')]
|
|
94
|
+
|
|
95
|
+
elif line.startswith('!'):
|
|
96
|
+
match = re.match(cls.LITE_PATTERNS['assumptions'], line)
|
|
97
|
+
if match:
|
|
98
|
+
result['assumptions'].append(match.group(1).strip())
|
|
99
|
+
|
|
100
|
+
elif line.startswith('<'):
|
|
101
|
+
match = re.match(cls.LITE_PATTERNS['preconditions'], line)
|
|
102
|
+
if match:
|
|
103
|
+
result['preconditions'].append(match.group(1).strip())
|
|
104
|
+
|
|
105
|
+
elif line.startswith('='):
|
|
106
|
+
match = re.match(cls.LITE_PATTERNS['invariants'], line)
|
|
107
|
+
if match:
|
|
108
|
+
result['invariants'].append(match.group(1).strip())
|
|
109
|
+
|
|
110
|
+
elif line.startswith('~'):
|
|
111
|
+
match = re.match(cls.LITE_PATTERNS['complexity'], line)
|
|
112
|
+
if match:
|
|
113
|
+
result['complexity'] = match.group(1).strip()
|
|
114
|
+
|
|
115
|
+
elif line.startswith('#'):
|
|
116
|
+
match = re.match(cls.LITE_PATTERNS['security'], line)
|
|
117
|
+
if match:
|
|
118
|
+
result['security'].append(match.group(1).strip())
|
|
119
|
+
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def parse_standard(cls, content: str) -> Dict[str, any]:
|
|
124
|
+
"""
|
|
125
|
+
Parse standard VooDocs format annotation.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
content: Standard format annotation text
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Dictionary with parsed fields
|
|
132
|
+
"""
|
|
133
|
+
result = {
|
|
134
|
+
'purpose': None,
|
|
135
|
+
'dependencies': [],
|
|
136
|
+
'assumptions': [],
|
|
137
|
+
'preconditions': [],
|
|
138
|
+
'postconditions': [],
|
|
139
|
+
'invariants': [],
|
|
140
|
+
'complexity': None,
|
|
141
|
+
'security': [],
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Extract each field
|
|
145
|
+
for field, pattern in cls.STANDARD_PATTERNS.items():
|
|
146
|
+
matches = re.findall(pattern, content)
|
|
147
|
+
|
|
148
|
+
if field in ['purpose', 'complexity']:
|
|
149
|
+
# Single value fields
|
|
150
|
+
if matches:
|
|
151
|
+
result[field] = matches[0].strip()
|
|
152
|
+
elif field == 'dependencies':
|
|
153
|
+
# Comma-separated list
|
|
154
|
+
if matches:
|
|
155
|
+
deps = matches[0].strip()
|
|
156
|
+
result[field] = [d.strip() for d in deps.split(',')]
|
|
157
|
+
else:
|
|
158
|
+
# Multiple value fields
|
|
159
|
+
result[field] = [m.strip() for m in matches]
|
|
160
|
+
|
|
161
|
+
return result
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def lite_to_standard(cls, lite_content: str, expand_abbreviations: bool = True) -> str:
|
|
165
|
+
"""
|
|
166
|
+
Convert Lite format to Standard format.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
lite_content: Lite format annotation
|
|
170
|
+
expand_abbreviations: Whether to expand abbreviations
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Standard format annotation
|
|
174
|
+
"""
|
|
175
|
+
parsed = cls.parse_lite(lite_content)
|
|
176
|
+
|
|
177
|
+
lines = []
|
|
178
|
+
|
|
179
|
+
# Purpose
|
|
180
|
+
if parsed['purpose']:
|
|
181
|
+
text = parsed['purpose']
|
|
182
|
+
if expand_abbreviations:
|
|
183
|
+
text = expand_text(text)
|
|
184
|
+
lines.append(f"⊢{{{text}}}")
|
|
185
|
+
|
|
186
|
+
# Dependencies
|
|
187
|
+
if parsed['dependencies']:
|
|
188
|
+
deps = ', '.join(parsed['dependencies'])
|
|
189
|
+
if expand_abbreviations:
|
|
190
|
+
deps = expand_text(deps)
|
|
191
|
+
lines.append(f"∂{{{deps}}}")
|
|
192
|
+
|
|
193
|
+
# Assumptions
|
|
194
|
+
if parsed['assumptions']:
|
|
195
|
+
for assumption in parsed['assumptions']:
|
|
196
|
+
text = assumption
|
|
197
|
+
if expand_abbreviations:
|
|
198
|
+
text = expand_text(text)
|
|
199
|
+
lines.append(f"⚠{{{text}}}")
|
|
200
|
+
|
|
201
|
+
# Preconditions
|
|
202
|
+
if parsed['preconditions']:
|
|
203
|
+
for precond in parsed['preconditions']:
|
|
204
|
+
text = precond
|
|
205
|
+
if expand_abbreviations:
|
|
206
|
+
text = expand_text(text)
|
|
207
|
+
lines.append(f"⊳{{{text}}}")
|
|
208
|
+
|
|
209
|
+
# Postconditions
|
|
210
|
+
if parsed['postconditions']:
|
|
211
|
+
for postcond in parsed['postconditions']:
|
|
212
|
+
text = postcond
|
|
213
|
+
if expand_abbreviations:
|
|
214
|
+
text = expand_text(text)
|
|
215
|
+
lines.append(f"⊲{{{text}}}")
|
|
216
|
+
|
|
217
|
+
# Invariants
|
|
218
|
+
if parsed['invariants']:
|
|
219
|
+
for invariant in parsed['invariants']:
|
|
220
|
+
text = invariant
|
|
221
|
+
if expand_abbreviations:
|
|
222
|
+
text = expand_text(text)
|
|
223
|
+
lines.append(f"⊨{{{text}}}")
|
|
224
|
+
|
|
225
|
+
# Complexity
|
|
226
|
+
if parsed['complexity']:
|
|
227
|
+
text = parsed['complexity']
|
|
228
|
+
# Don't expand complexity (O(n) should stay as-is)
|
|
229
|
+
lines.append(f"⚡{{{text}}}")
|
|
230
|
+
|
|
231
|
+
# Security
|
|
232
|
+
if parsed['security']:
|
|
233
|
+
for security in parsed['security']:
|
|
234
|
+
text = security
|
|
235
|
+
if expand_abbreviations:
|
|
236
|
+
text = expand_text(text)
|
|
237
|
+
lines.append(f"🔒{{{text}}}")
|
|
238
|
+
|
|
239
|
+
return '\n'.join(lines)
|
|
240
|
+
|
|
241
|
+
@classmethod
|
|
242
|
+
def standard_to_lite(cls, standard_content: str, compress_abbreviations: bool = True) -> str:
|
|
243
|
+
"""
|
|
244
|
+
Convert Standard format to Lite format.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
standard_content: Standard format annotation
|
|
248
|
+
compress_abbreviations: Whether to compress to abbreviations
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Lite format annotation
|
|
252
|
+
"""
|
|
253
|
+
parsed = cls.parse_standard(standard_content)
|
|
254
|
+
|
|
255
|
+
lines = []
|
|
256
|
+
|
|
257
|
+
# Purpose
|
|
258
|
+
if parsed['purpose']:
|
|
259
|
+
text = parsed['purpose']
|
|
260
|
+
if compress_abbreviations:
|
|
261
|
+
text = ultra_compress(text)
|
|
262
|
+
lines.append(f">{text}")
|
|
263
|
+
|
|
264
|
+
# Dependencies
|
|
265
|
+
if parsed['dependencies']:
|
|
266
|
+
deps = ','.join(parsed['dependencies'])
|
|
267
|
+
if compress_abbreviations:
|
|
268
|
+
deps = ultra_compress(deps)
|
|
269
|
+
lines.append(f"@{deps}")
|
|
270
|
+
|
|
271
|
+
# Assumptions
|
|
272
|
+
if parsed['assumptions']:
|
|
273
|
+
for assumption in parsed['assumptions']:
|
|
274
|
+
text = assumption
|
|
275
|
+
if compress_abbreviations:
|
|
276
|
+
text = ultra_compress(text)
|
|
277
|
+
lines.append(f"!{text}")
|
|
278
|
+
|
|
279
|
+
# Preconditions
|
|
280
|
+
if parsed['preconditions']:
|
|
281
|
+
for precond in parsed['preconditions']:
|
|
282
|
+
text = precond
|
|
283
|
+
if compress_abbreviations:
|
|
284
|
+
text = ultra_compress(text)
|
|
285
|
+
lines.append(f"<{text}")
|
|
286
|
+
|
|
287
|
+
# Postconditions
|
|
288
|
+
if parsed['postconditions']:
|
|
289
|
+
for postcond in parsed['postconditions']:
|
|
290
|
+
text = postcond
|
|
291
|
+
if compress_abbreviations:
|
|
292
|
+
text = ultra_compress(text)
|
|
293
|
+
lines.append(f">{text}")
|
|
294
|
+
|
|
295
|
+
# Invariants
|
|
296
|
+
if parsed['invariants']:
|
|
297
|
+
for invariant in parsed['invariants']:
|
|
298
|
+
text = invariant
|
|
299
|
+
if compress_abbreviations:
|
|
300
|
+
text = ultra_compress(text)
|
|
301
|
+
lines.append(f"={text}")
|
|
302
|
+
|
|
303
|
+
# Complexity
|
|
304
|
+
if parsed['complexity']:
|
|
305
|
+
text = parsed['complexity']
|
|
306
|
+
# Don't compress complexity
|
|
307
|
+
lines.append(f"~{text}")
|
|
308
|
+
|
|
309
|
+
# Security
|
|
310
|
+
if parsed['security']:
|
|
311
|
+
for security in parsed['security']:
|
|
312
|
+
text = security
|
|
313
|
+
if compress_abbreviations:
|
|
314
|
+
text = ultra_compress(text)
|
|
315
|
+
lines.append(f"#{text}")
|
|
316
|
+
|
|
317
|
+
return '\n'.join(lines)
|
|
318
|
+
|
|
319
|
+
@classmethod
|
|
320
|
+
def detect_format(cls, content: str) -> str:
|
|
321
|
+
"""
|
|
322
|
+
Detect whether content is Lite or Standard format.
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
'lite', 'standard', or 'unknown'
|
|
326
|
+
"""
|
|
327
|
+
# Check for Lite symbols at start of lines
|
|
328
|
+
lite_indicators = ['>', '@', '!', '<', '=', '~', '#']
|
|
329
|
+
has_lite = any(line.strip().startswith(sym) for sym in lite_indicators for line in content.split('\n'))
|
|
330
|
+
|
|
331
|
+
# Check for Standard symbols
|
|
332
|
+
standard_indicators = ['⊢', '∂', '⚠', '⊳', '⊲', '⊨', '⚡', '🔒']
|
|
333
|
+
has_standard = any(sym in content for sym in standard_indicators)
|
|
334
|
+
|
|
335
|
+
if has_lite and not has_standard:
|
|
336
|
+
return 'lite'
|
|
337
|
+
elif has_standard and not has_lite:
|
|
338
|
+
return 'standard'
|
|
339
|
+
elif has_lite and has_standard:
|
|
340
|
+
# Mixed format, prefer standard
|
|
341
|
+
return 'standard'
|
|
342
|
+
else:
|
|
343
|
+
return 'unknown'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voodocs/cli",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "AI-Native Symbolic Documentation System - The world's first documentation tool using mathematical notation with semantic validation",
|
|
5
5
|
"main": "voodocs_cli.py",
|
|
6
6
|
"bin": {
|
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
"lib/darkarts/exceptions.py",
|
|
65
65
|
"lib/darkarts/telemetry.py",
|
|
66
66
|
"lib/darkarts/companion_files.py",
|
|
67
|
+
"lib/darkarts/voodocs_lite_dict.py",
|
|
68
|
+
"lib/darkarts/voodocs_lite_dict_v2.py",
|
|
69
|
+
"lib/darkarts/voodocs_lite_parser.py",
|
|
70
|
+
"lib/darkarts/priority_analyzer/",
|
|
67
71
|
"lib/darkarts/parsers/typescript/dist/",
|
|
68
72
|
"lib/darkarts/parsers/typescript/src/",
|
|
69
73
|
"lib/darkarts/parsers/typescript/package.json",
|