claude-self-reflect 3.2.4 → 3.3.1
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/.claude/agents/claude-self-reflect-test.md +992 -510
- package/.claude/agents/reflection-specialist.md +59 -3
- package/README.md +14 -5
- package/installer/cli.js +16 -0
- package/installer/postinstall.js +14 -0
- package/installer/statusline-setup.js +289 -0
- package/mcp-server/run-mcp.sh +73 -5
- package/mcp-server/src/app_context.py +64 -0
- package/mcp-server/src/config.py +57 -0
- package/mcp-server/src/connection_pool.py +286 -0
- package/mcp-server/src/decay_manager.py +106 -0
- package/mcp-server/src/embedding_manager.py +64 -40
- package/mcp-server/src/embeddings_old.py +141 -0
- package/mcp-server/src/models.py +64 -0
- package/mcp-server/src/parallel_search.py +305 -0
- package/mcp-server/src/project_resolver.py +5 -0
- package/mcp-server/src/reflection_tools.py +211 -0
- package/mcp-server/src/rich_formatting.py +196 -0
- package/mcp-server/src/search_tools.py +874 -0
- package/mcp-server/src/server.py +127 -1720
- package/mcp-server/src/temporal_design.py +132 -0
- package/mcp-server/src/temporal_tools.py +604 -0
- package/mcp-server/src/temporal_utils.py +384 -0
- package/mcp-server/src/utils.py +150 -67
- package/package.json +15 -1
- package/scripts/add-timestamp-indexes.py +134 -0
- package/scripts/ast_grep_final_analyzer.py +325 -0
- package/scripts/ast_grep_unified_registry.py +556 -0
- package/scripts/check-collections.py +29 -0
- package/scripts/csr-status +366 -0
- package/scripts/debug-august-parsing.py +76 -0
- package/scripts/debug-import-single.py +91 -0
- package/scripts/debug-project-resolver.py +82 -0
- package/scripts/debug-temporal-tools.py +135 -0
- package/scripts/delta-metadata-update.py +547 -0
- package/scripts/import-conversations-unified.py +157 -25
- package/scripts/precompact-hook.sh +33 -0
- package/scripts/session_quality_tracker.py +481 -0
- package/scripts/streaming-watcher.py +1578 -0
- package/scripts/update_patterns.py +334 -0
- package/scripts/utils.py +39 -0
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Unified AST-GREP Pattern Registry
|
|
4
|
+
Combines custom patterns with official catalog patterns
|
|
5
|
+
MANDATORY: Uses AST patterns only, no regex
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, List, Any
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# Setup logger
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
logging.basicConfig(level=logging.INFO)
|
|
16
|
+
|
|
17
|
+
class UnifiedASTGrepRegistry:
|
|
18
|
+
"""
|
|
19
|
+
Unified registry combining:
|
|
20
|
+
1. Custom AST patterns for Python
|
|
21
|
+
2. Official catalog patterns from AST-GREP
|
|
22
|
+
3. TypeScript/JavaScript patterns
|
|
23
|
+
All patterns are AST-based, not regex.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.patterns = self._load_unified_patterns()
|
|
28
|
+
|
|
29
|
+
# Merge auto-updated catalog if present
|
|
30
|
+
json_path = Path(__file__).parent / "unified_registry.json"
|
|
31
|
+
if json_path.exists():
|
|
32
|
+
try:
|
|
33
|
+
with open(json_path, 'r') as f:
|
|
34
|
+
data = json.load(f)
|
|
35
|
+
# Merge catalog patterns into existing patterns
|
|
36
|
+
catalog_patterns = data.get("patterns", {})
|
|
37
|
+
for category, patterns in catalog_patterns.items():
|
|
38
|
+
if category not in self.patterns:
|
|
39
|
+
self.patterns[category] = []
|
|
40
|
+
# Add patterns that don't already exist
|
|
41
|
+
existing_ids = {p['id'] for p in self.patterns[category]}
|
|
42
|
+
for pattern in patterns:
|
|
43
|
+
if pattern.get('id') not in existing_ids:
|
|
44
|
+
self.patterns[category].append(pattern)
|
|
45
|
+
except Exception as e:
|
|
46
|
+
# Continue with static patterns if catalog load fails
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
def _load_unified_patterns(self) -> Dict[str, List[Dict[str, Any]]]:
|
|
50
|
+
"""Load unified patterns from multiple sources."""
|
|
51
|
+
patterns = {}
|
|
52
|
+
|
|
53
|
+
# Python patterns (custom)
|
|
54
|
+
patterns.update(self._load_python_patterns())
|
|
55
|
+
|
|
56
|
+
# TypeScript patterns (from catalog)
|
|
57
|
+
patterns.update(self._load_typescript_patterns())
|
|
58
|
+
|
|
59
|
+
# JavaScript patterns (shared with TS)
|
|
60
|
+
patterns.update(self._load_javascript_patterns())
|
|
61
|
+
|
|
62
|
+
return patterns
|
|
63
|
+
|
|
64
|
+
def _load_python_patterns(self) -> Dict[str, List[Dict[str, Any]]]:
|
|
65
|
+
"""Python-specific AST patterns."""
|
|
66
|
+
return {
|
|
67
|
+
"python_async": [
|
|
68
|
+
{
|
|
69
|
+
"id": "async-function",
|
|
70
|
+
"pattern": "async def $FUNC($$$): $$$",
|
|
71
|
+
"description": "Async function definition",
|
|
72
|
+
"quality": "good",
|
|
73
|
+
"weight": 2,
|
|
74
|
+
"language": "python"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "async-with",
|
|
78
|
+
"pattern": "async with $RESOURCE: $$$",
|
|
79
|
+
"description": "Async context manager",
|
|
80
|
+
"quality": "good",
|
|
81
|
+
"weight": 3,
|
|
82
|
+
"language": "python"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "await-gather",
|
|
86
|
+
"pattern": "await asyncio.gather($$$)",
|
|
87
|
+
"description": "Parallel async execution",
|
|
88
|
+
"quality": "good",
|
|
89
|
+
"weight": 4,
|
|
90
|
+
"language": "python"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "await-call",
|
|
94
|
+
"pattern": "await $FUNC($$$)",
|
|
95
|
+
"description": "Awaited async call",
|
|
96
|
+
"quality": "neutral",
|
|
97
|
+
"weight": 1,
|
|
98
|
+
"language": "python"
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"python_error_handling": [
|
|
102
|
+
{
|
|
103
|
+
"id": "specific-except",
|
|
104
|
+
"pattern": "except $ERROR: $$$",
|
|
105
|
+
"description": "Specific exception handling",
|
|
106
|
+
"quality": "good",
|
|
107
|
+
"weight": 3,
|
|
108
|
+
"language": "python"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "broad-except",
|
|
112
|
+
"pattern": "except: $$$",
|
|
113
|
+
"description": "Bare except clause",
|
|
114
|
+
"quality": "bad",
|
|
115
|
+
"weight": -3,
|
|
116
|
+
"language": "python"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "try-finally",
|
|
120
|
+
"pattern": "try: $TRY finally: $FINALLY",
|
|
121
|
+
"description": "Try-finally block",
|
|
122
|
+
"quality": "good",
|
|
123
|
+
"weight": 2,
|
|
124
|
+
"language": "python"
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
"python_logging": [
|
|
128
|
+
{
|
|
129
|
+
"id": "logger-call",
|
|
130
|
+
"pattern": "logger.$METHOD($$$)",
|
|
131
|
+
"description": "Logger usage",
|
|
132
|
+
"quality": "good",
|
|
133
|
+
"weight": 2,
|
|
134
|
+
"language": "python"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "print-call",
|
|
138
|
+
"pattern": "print($$$)",
|
|
139
|
+
"description": "Print statement",
|
|
140
|
+
"quality": "bad",
|
|
141
|
+
"weight": -1,
|
|
142
|
+
"language": "python"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "debug-print-f-sq",
|
|
146
|
+
"pattern": "print(f'$A')",
|
|
147
|
+
"description": "F-string print (single quote)",
|
|
148
|
+
"quality": "bad",
|
|
149
|
+
"weight": -2,
|
|
150
|
+
"language": "python"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"id": "debug-print-f-dq",
|
|
154
|
+
"pattern": "print(f\"$A\")",
|
|
155
|
+
"description": "F-string print (double quote)",
|
|
156
|
+
"quality": "bad",
|
|
157
|
+
"weight": -2,
|
|
158
|
+
"language": "python"
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"python_typing": [
|
|
162
|
+
{
|
|
163
|
+
"id": "typed-function",
|
|
164
|
+
"pattern": "def $FUNC($$$) -> $RETURN: $$$",
|
|
165
|
+
"description": "Function with return type",
|
|
166
|
+
"quality": "good",
|
|
167
|
+
"weight": 3,
|
|
168
|
+
"language": "python"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "typed-async",
|
|
172
|
+
"pattern": "async def $FUNC($$$) -> $RETURN: $$$",
|
|
173
|
+
"description": "Async function with return type",
|
|
174
|
+
"quality": "good",
|
|
175
|
+
"weight": 4,
|
|
176
|
+
"language": "python"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "type-annotation",
|
|
180
|
+
"pattern": "$VAR: $TYPE = $$$",
|
|
181
|
+
"description": "Variable type annotation",
|
|
182
|
+
"quality": "good",
|
|
183
|
+
"weight": 2,
|
|
184
|
+
"language": "python"
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
"python_antipatterns": [
|
|
188
|
+
{
|
|
189
|
+
"id": "sync-sleep",
|
|
190
|
+
"pattern": "time.sleep($$$)",
|
|
191
|
+
"description": "Blocking sleep in async context",
|
|
192
|
+
"quality": "bad",
|
|
193
|
+
"weight": -5,
|
|
194
|
+
"language": "python"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"id": "sync-open",
|
|
198
|
+
"pattern": "open($$$)",
|
|
199
|
+
"description": "Sync file open (should use aiofiles)",
|
|
200
|
+
"quality": "bad",
|
|
201
|
+
"weight": -3,
|
|
202
|
+
"language": "python"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "requests-call",
|
|
206
|
+
"pattern": "requests.$METHOD($$$)",
|
|
207
|
+
"description": "Sync HTTP request (should use aiohttp)",
|
|
208
|
+
"quality": "bad",
|
|
209
|
+
"weight": -4,
|
|
210
|
+
"language": "python"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "global-var",
|
|
214
|
+
"pattern": "global $VAR",
|
|
215
|
+
"description": "Global variable usage",
|
|
216
|
+
"quality": "bad",
|
|
217
|
+
"weight": -2,
|
|
218
|
+
"language": "python"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"id": "mutable-default",
|
|
222
|
+
"pattern": "def $FUNC($$$, $ARG=[]): $$$",
|
|
223
|
+
"description": "Mutable default argument",
|
|
224
|
+
"quality": "bad",
|
|
225
|
+
"weight": -4,
|
|
226
|
+
"language": "python"
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
"python_qdrant": [
|
|
230
|
+
{
|
|
231
|
+
"id": "qdrant-search",
|
|
232
|
+
"pattern": "$CLIENT.search($$$)",
|
|
233
|
+
"description": "Qdrant search operation",
|
|
234
|
+
"quality": "neutral",
|
|
235
|
+
"weight": 1,
|
|
236
|
+
"language": "python"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "qdrant-upsert",
|
|
240
|
+
"pattern": "$CLIENT.upsert($$$)",
|
|
241
|
+
"description": "Qdrant upsert operation",
|
|
242
|
+
"quality": "neutral",
|
|
243
|
+
"weight": 1,
|
|
244
|
+
"language": "python"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "collection-create",
|
|
248
|
+
"pattern": "create_collection($$$)",
|
|
249
|
+
"description": "Collection creation",
|
|
250
|
+
"quality": "neutral",
|
|
251
|
+
"weight": 1,
|
|
252
|
+
"language": "python"
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
"python_mcp": [
|
|
256
|
+
{
|
|
257
|
+
"id": "mcp-tool",
|
|
258
|
+
"pattern": "@server.tool\nasync def $TOOL($$$): $$$",
|
|
259
|
+
"description": "MCP tool definition",
|
|
260
|
+
"quality": "good",
|
|
261
|
+
"weight": 5,
|
|
262
|
+
"language": "python"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"id": "mcp-resource",
|
|
266
|
+
"pattern": "@server.resource($$$)\nasync def $RESOURCE($$$): $$$",
|
|
267
|
+
"description": "MCP resource definition",
|
|
268
|
+
"quality": "good",
|
|
269
|
+
"weight": 5,
|
|
270
|
+
"language": "python"
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
def _load_typescript_patterns(self) -> Dict[str, List[Dict[str, Any]]]:
|
|
276
|
+
"""TypeScript-specific patterns from catalog."""
|
|
277
|
+
return {
|
|
278
|
+
"typescript_async": [
|
|
279
|
+
{
|
|
280
|
+
"id": "no-await-in-promise-all",
|
|
281
|
+
"pattern": "await $A",
|
|
282
|
+
"inside": "Promise.all($_)",
|
|
283
|
+
"description": "No await in Promise.all array",
|
|
284
|
+
"quality": "bad",
|
|
285
|
+
"weight": -4,
|
|
286
|
+
"language": "typescript",
|
|
287
|
+
"fix": "$A"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"id": "async-function-ts",
|
|
291
|
+
"pattern": "async function $FUNC($$$) { $$$ }",
|
|
292
|
+
"description": "Async function",
|
|
293
|
+
"quality": "good",
|
|
294
|
+
"weight": 2,
|
|
295
|
+
"language": "typescript"
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"id": "async-arrow",
|
|
299
|
+
"pattern": "async ($$$) => { $$$ }",
|
|
300
|
+
"description": "Async arrow function",
|
|
301
|
+
"quality": "good",
|
|
302
|
+
"weight": 2,
|
|
303
|
+
"language": "typescript"
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
"typescript_console": [
|
|
307
|
+
{
|
|
308
|
+
"id": "no-console-log",
|
|
309
|
+
"pattern": "console.log($$$)",
|
|
310
|
+
"description": "Console.log usage",
|
|
311
|
+
"quality": "bad",
|
|
312
|
+
"weight": -2,
|
|
313
|
+
"language": "typescript",
|
|
314
|
+
"fix": ""
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"id": "no-console-debug",
|
|
318
|
+
"pattern": "console.debug($$$)",
|
|
319
|
+
"description": "Console.debug usage",
|
|
320
|
+
"quality": "bad",
|
|
321
|
+
"weight": -2,
|
|
322
|
+
"language": "typescript",
|
|
323
|
+
"fix": ""
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"id": "console-error-in-catch",
|
|
327
|
+
"pattern": "console.error($$$)",
|
|
328
|
+
"inside": "catch ($_) { $$$ }",
|
|
329
|
+
"description": "Console.error in catch (OK)",
|
|
330
|
+
"quality": "neutral",
|
|
331
|
+
"weight": 0,
|
|
332
|
+
"language": "typescript"
|
|
333
|
+
}
|
|
334
|
+
],
|
|
335
|
+
"typescript_react": [
|
|
336
|
+
{
|
|
337
|
+
"id": "useState-hook",
|
|
338
|
+
"pattern": "const [$STATE, $SETTER] = useState($$$)",
|
|
339
|
+
"description": "React useState hook",
|
|
340
|
+
"quality": "good",
|
|
341
|
+
"weight": 2,
|
|
342
|
+
"language": "typescript"
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"id": "useEffect-hook",
|
|
346
|
+
"pattern": "useEffect(() => { $$$ }, $DEPS)",
|
|
347
|
+
"description": "React useEffect hook",
|
|
348
|
+
"quality": "neutral",
|
|
349
|
+
"weight": 1,
|
|
350
|
+
"language": "typescript"
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"id": "useEffect-no-deps",
|
|
354
|
+
"pattern": "useEffect(() => { $$$ })",
|
|
355
|
+
"description": "useEffect without dependencies",
|
|
356
|
+
"quality": "bad",
|
|
357
|
+
"weight": -3,
|
|
358
|
+
"language": "typescript"
|
|
359
|
+
}
|
|
360
|
+
],
|
|
361
|
+
"typescript_imports": [
|
|
362
|
+
{
|
|
363
|
+
"id": "barrel-import",
|
|
364
|
+
"pattern": "import { $$$ } from '$MODULE'",
|
|
365
|
+
"description": "Named import",
|
|
366
|
+
"quality": "neutral",
|
|
367
|
+
"weight": 0,
|
|
368
|
+
"language": "typescript"
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
"id": "default-import",
|
|
372
|
+
"pattern": "import $NAME from '$MODULE'",
|
|
373
|
+
"description": "Default import",
|
|
374
|
+
"quality": "neutral",
|
|
375
|
+
"weight": 0,
|
|
376
|
+
"language": "typescript"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"id": "import-all",
|
|
380
|
+
"pattern": "import * as $NAME from '$MODULE'",
|
|
381
|
+
"description": "Import all",
|
|
382
|
+
"quality": "neutral",
|
|
383
|
+
"weight": -1,
|
|
384
|
+
"language": "typescript"
|
|
385
|
+
}
|
|
386
|
+
]
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
def _load_javascript_patterns(self) -> Dict[str, List[Dict[str, Any]]]:
|
|
390
|
+
"""JavaScript patterns (subset of TypeScript)."""
|
|
391
|
+
return {
|
|
392
|
+
"javascript_async": [
|
|
393
|
+
{
|
|
394
|
+
"id": "callback-hell",
|
|
395
|
+
"pattern": "$FUNC($$$, function($$$) { $$$ })",
|
|
396
|
+
"description": "Callback pattern (consider promises)",
|
|
397
|
+
"quality": "bad",
|
|
398
|
+
"weight": -2,
|
|
399
|
+
"language": "javascript"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"id": "promise-then",
|
|
403
|
+
"pattern": "$PROMISE.then($$$)",
|
|
404
|
+
"description": "Promise then chain",
|
|
405
|
+
"quality": "neutral",
|
|
406
|
+
"weight": 0,
|
|
407
|
+
"language": "javascript"
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"id": "async-await",
|
|
411
|
+
"pattern": "await $PROMISE",
|
|
412
|
+
"description": "Async/await usage",
|
|
413
|
+
"quality": "good",
|
|
414
|
+
"weight": 2,
|
|
415
|
+
"language": "javascript"
|
|
416
|
+
}
|
|
417
|
+
],
|
|
418
|
+
"javascript_var": [
|
|
419
|
+
{
|
|
420
|
+
"id": "var-declaration",
|
|
421
|
+
"pattern": "var $VAR = $$$",
|
|
422
|
+
"description": "Var declaration (use const/let)",
|
|
423
|
+
"quality": "bad",
|
|
424
|
+
"weight": -3,
|
|
425
|
+
"language": "javascript"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"id": "const-declaration",
|
|
429
|
+
"pattern": "const $VAR = $$$",
|
|
430
|
+
"description": "Const declaration",
|
|
431
|
+
"quality": "good",
|
|
432
|
+
"weight": 2,
|
|
433
|
+
"language": "javascript"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"id": "let-declaration",
|
|
437
|
+
"pattern": "let $VAR = $$$",
|
|
438
|
+
"description": "Let declaration",
|
|
439
|
+
"quality": "good",
|
|
440
|
+
"weight": 1,
|
|
441
|
+
"language": "javascript"
|
|
442
|
+
}
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
def get_all_patterns(self) -> List[Dict[str, Any]]:
|
|
447
|
+
"""Get all patterns as a flat list."""
|
|
448
|
+
all_patterns = []
|
|
449
|
+
for category, patterns in self.patterns.items():
|
|
450
|
+
for pattern in patterns:
|
|
451
|
+
# Avoid mutating source; create a copy
|
|
452
|
+
item = dict(pattern)
|
|
453
|
+
item['category'] = category
|
|
454
|
+
all_patterns.append(item)
|
|
455
|
+
return all_patterns
|
|
456
|
+
|
|
457
|
+
def get_patterns_by_language(self, language: str) -> List[Dict[str, Any]]:
|
|
458
|
+
"""Get patterns for a specific language."""
|
|
459
|
+
return [p for p in self.get_all_patterns() if p.get('language') == language]
|
|
460
|
+
|
|
461
|
+
def get_good_patterns(self) -> List[Dict[str, Any]]:
|
|
462
|
+
"""Get only good quality patterns."""
|
|
463
|
+
return [p for p in self.get_all_patterns() if p.get('quality') == 'good']
|
|
464
|
+
|
|
465
|
+
def get_bad_patterns(self) -> List[Dict[str, Any]]:
|
|
466
|
+
"""Get only bad quality patterns (anti-patterns)."""
|
|
467
|
+
return [p for p in self.get_all_patterns() if p.get('quality') == 'bad']
|
|
468
|
+
|
|
469
|
+
def calculate_quality_score(self, matches: List[Dict]) -> float:
|
|
470
|
+
"""
|
|
471
|
+
Calculate quality score based on pattern matches.
|
|
472
|
+
Each match includes the pattern and count.
|
|
473
|
+
"""
|
|
474
|
+
total_weight = 0
|
|
475
|
+
total_count = 0
|
|
476
|
+
|
|
477
|
+
for match in matches:
|
|
478
|
+
weight = match.get('weight', 0)
|
|
479
|
+
count = match.get('count', 0)
|
|
480
|
+
total_weight += weight * count
|
|
481
|
+
total_count += abs(weight) * count
|
|
482
|
+
|
|
483
|
+
if total_count == 0:
|
|
484
|
+
return 0.5
|
|
485
|
+
|
|
486
|
+
# Normalize to 0-1 range
|
|
487
|
+
normalized = (total_weight + 100) / 200
|
|
488
|
+
return max(0.0, min(1.0, normalized))
|
|
489
|
+
|
|
490
|
+
def export_to_json(self, path: str):
|
|
491
|
+
"""Export registry to JSON file."""
|
|
492
|
+
data = {
|
|
493
|
+
'source': 'unified-ast-grep',
|
|
494
|
+
'version': '2.0.0',
|
|
495
|
+
'patterns': self.patterns,
|
|
496
|
+
'stats': {
|
|
497
|
+
'total_patterns': len(self.get_all_patterns()),
|
|
498
|
+
'good_patterns': len(self.get_good_patterns()),
|
|
499
|
+
'bad_patterns': len(self.get_bad_patterns()),
|
|
500
|
+
'languages': list(set(p.get('language') for p in self.get_all_patterns())),
|
|
501
|
+
'categories': list(self.patterns.keys())
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
with open(path, 'w') as f:
|
|
506
|
+
json.dump(data, f, indent=2)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
# Singleton instance
|
|
510
|
+
_unified_registry = None
|
|
511
|
+
|
|
512
|
+
def get_unified_registry() -> UnifiedASTGrepRegistry:
|
|
513
|
+
"""Get or create the unified AST-GREP pattern registry."""
|
|
514
|
+
global _unified_registry
|
|
515
|
+
if _unified_registry is None:
|
|
516
|
+
_unified_registry = UnifiedASTGrepRegistry()
|
|
517
|
+
return _unified_registry
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
if __name__ == "__main__":
|
|
521
|
+
# Test the unified registry
|
|
522
|
+
registry = get_unified_registry()
|
|
523
|
+
|
|
524
|
+
print("Unified AST-GREP Pattern Registry")
|
|
525
|
+
print("=" * 60)
|
|
526
|
+
|
|
527
|
+
all_patterns = registry.get_all_patterns()
|
|
528
|
+
print(f"\nTotal patterns: {len(all_patterns)}")
|
|
529
|
+
print(f"Good patterns: {len(registry.get_good_patterns())}")
|
|
530
|
+
print(f"Bad patterns: {len(registry.get_bad_patterns())}")
|
|
531
|
+
|
|
532
|
+
# Count by language
|
|
533
|
+
languages = {}
|
|
534
|
+
for pattern in all_patterns:
|
|
535
|
+
lang = pattern.get('language', 'unknown')
|
|
536
|
+
languages[lang] = languages.get(lang, 0) + 1
|
|
537
|
+
|
|
538
|
+
print(f"\nPatterns by language:")
|
|
539
|
+
for lang, count in languages.items():
|
|
540
|
+
print(f" - {lang}: {count} patterns")
|
|
541
|
+
|
|
542
|
+
print(f"\nCategories ({len(registry.patterns)}):")
|
|
543
|
+
for category in registry.patterns.keys():
|
|
544
|
+
count = len(registry.patterns[category])
|
|
545
|
+
print(f" - {category}: {count} patterns")
|
|
546
|
+
|
|
547
|
+
# Export to JSON
|
|
548
|
+
export_path = "/Users/ramakrishnanannaswamy/projects/claude-self-reflect/scripts/unified_registry.json"
|
|
549
|
+
registry.export_to_json(export_path)
|
|
550
|
+
print(f"\n✅ Exported unified registry to {export_path}")
|
|
551
|
+
|
|
552
|
+
# Show sample patterns
|
|
553
|
+
print("\nSample patterns:")
|
|
554
|
+
for pattern in all_patterns[:5]:
|
|
555
|
+
print(f" - {pattern['id']} ({pattern['language']}): {pattern.get('pattern', 'N/A')[:40]}...")
|
|
556
|
+
print(f" Quality: {pattern['quality']}, Weight: {pattern['weight']}")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Check Qdrant collections."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
from qdrant_client import QdrantClient
|
|
6
|
+
|
|
7
|
+
# Configuration
|
|
8
|
+
QDRANT_URL = os.getenv("QDRANT_URL", "http://localhost:6333")
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
"""List all collections."""
|
|
12
|
+
client = QdrantClient(url=QDRANT_URL)
|
|
13
|
+
|
|
14
|
+
# Get all collections
|
|
15
|
+
collections = client.get_collections()
|
|
16
|
+
|
|
17
|
+
print("Qdrant Collections:")
|
|
18
|
+
print("-" * 60)
|
|
19
|
+
|
|
20
|
+
voyage_collections = []
|
|
21
|
+
for collection in collections.collections:
|
|
22
|
+
print(f"- {collection.name}")
|
|
23
|
+
if collection.name.endswith("_voyage"):
|
|
24
|
+
voyage_collections.append(collection.name)
|
|
25
|
+
|
|
26
|
+
print(f"\nFound {len(voyage_collections)} Voyage collections")
|
|
27
|
+
|
|
28
|
+
if __name__ == "__main__":
|
|
29
|
+
main()
|