claude-self-reflect 5.0.2 → 5.0.4
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/docker-compose.yaml +3 -1
- package/installer/setup-wizard-docker.js +64 -9
- package/package.json +1 -1
- package/scripts/ast_grep_final_analyzer.py +16 -6
- package/scripts/csr-status +120 -17
- package/scripts/debug-august-parsing.py +5 -1
- package/scripts/debug-project-resolver.py +3 -3
- package/scripts/import-conversations-unified.py +292 -821
- package/scripts/session_quality_tracker.py +10 -0
- package/scripts/unified_state_manager.py +7 -4
- package/mcp-server/src/test_quality.py +0 -153
|
@@ -647,6 +647,8 @@ if __name__ == "__main__":
|
|
|
647
647
|
parser.add_argument('--project-name', help='Name of the project for cache file')
|
|
648
648
|
parser.add_argument('--use-tracker', action='store_true',
|
|
649
649
|
help='Use session edit tracker for analysis')
|
|
650
|
+
parser.add_argument('--update-cache-only', action='store_true',
|
|
651
|
+
help='Only update cache without printing report')
|
|
650
652
|
args = parser.parse_args()
|
|
651
653
|
|
|
652
654
|
# If external project specified, change to that directory
|
|
@@ -658,4 +660,12 @@ if __name__ == "__main__":
|
|
|
658
660
|
# This will be used in the main() function for cache naming
|
|
659
661
|
os.environ['QUALITY_PROJECT_NAME'] = args.project_name
|
|
660
662
|
|
|
663
|
+
# For cache-only mode, suppress output
|
|
664
|
+
if args.update_cache_only:
|
|
665
|
+
# Redirect logger to null
|
|
666
|
+
import os
|
|
667
|
+
import sys
|
|
668
|
+
sys.stdout = open(os.devnull, 'w')
|
|
669
|
+
sys.stderr = open(os.devnull, 'w')
|
|
670
|
+
|
|
661
671
|
main(use_tracker=args.use_tracker)
|
|
@@ -21,7 +21,7 @@ import logging
|
|
|
21
21
|
import sys
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
from datetime import datetime, timedelta, timezone
|
|
24
|
-
from typing import Dict, Any, Optional, List, Set
|
|
24
|
+
from typing import Dict, Any, Optional, List, Set, Union
|
|
25
25
|
from contextlib import contextmanager
|
|
26
26
|
|
|
27
27
|
# Try to import filelock, fall back to platform-specific implementation
|
|
@@ -62,14 +62,17 @@ class UnifiedStateManager:
|
|
|
62
62
|
LOCK_TIMEOUT = 5.0
|
|
63
63
|
LOCK_EXPIRY = timedelta(seconds=30)
|
|
64
64
|
|
|
65
|
-
def __init__(self, state_file: Optional[Path] = None):
|
|
65
|
+
def __init__(self, state_file: Optional[Union[Path, str]] = None):
|
|
66
66
|
"""
|
|
67
67
|
Initialize the unified state manager.
|
|
68
68
|
|
|
69
69
|
Args:
|
|
70
70
|
state_file: Path to the state file (defaults to ~/.claude-self-reflect/config/unified-state.json)
|
|
71
71
|
"""
|
|
72
|
-
|
|
72
|
+
if state_file:
|
|
73
|
+
self.state_file = Path(state_file) if isinstance(state_file, str) else state_file
|
|
74
|
+
else:
|
|
75
|
+
self.state_file = Path.home() / ".claude-self-reflect" / "config" / "unified-state.json"
|
|
73
76
|
self.lock_file = self.state_file.with_suffix('.lock')
|
|
74
77
|
self.temp_file = self.state_file.with_suffix('.tmp')
|
|
75
78
|
self._file_lock = None
|
|
@@ -127,7 +130,7 @@ class UnifiedStateManager:
|
|
|
127
130
|
if HAS_FILELOCK:
|
|
128
131
|
lock = filelock.FileLock(str(self.lock_file), timeout=timeout)
|
|
129
132
|
try:
|
|
130
|
-
with lock
|
|
133
|
+
with lock:
|
|
131
134
|
yield lock
|
|
132
135
|
except filelock.Timeout:
|
|
133
136
|
raise TimeoutError(f"Could not acquire lock within {timeout} seconds")
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Test file with intentional quality issues for testing quality-fixer agent.
|
|
4
|
-
This file contains patterns that should be fixed:
|
|
5
|
-
- sync file operations that should be async
|
|
6
|
-
- global variables
|
|
7
|
-
- print statements
|
|
8
|
-
- long functions
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
import json
|
|
13
|
-
import asyncio
|
|
14
|
-
import logging
|
|
15
|
-
import aiofiles
|
|
16
|
-
from typing import List, Dict, Any
|
|
17
|
-
|
|
18
|
-
# Set up logger instead of print statements
|
|
19
|
-
logger = logging.getLogger(__name__)
|
|
20
|
-
|
|
21
|
-
# Configuration management class instead of global variables
|
|
22
|
-
class ConfigManager:
|
|
23
|
-
def __init__(self):
|
|
24
|
-
self.config = None
|
|
25
|
-
self.counter = 0
|
|
26
|
-
|
|
27
|
-
async def load_config(config_manager: ConfigManager) -> Dict[str, Any]:
|
|
28
|
-
"""Load config using async file operations."""
|
|
29
|
-
# Async file operation using aiofiles
|
|
30
|
-
async with aiofiles.open("config.json", "r") as f:
|
|
31
|
-
content = await f.read()
|
|
32
|
-
config_manager.config = json.loads(content)
|
|
33
|
-
|
|
34
|
-
logger.info(f"Config loaded: {config_manager.config}")
|
|
35
|
-
return config_manager.config
|
|
36
|
-
|
|
37
|
-
async def save_data(data: Dict[str, Any], config_manager: ConfigManager) -> None:
|
|
38
|
-
"""Save data using async operations."""
|
|
39
|
-
config_manager.counter += 1
|
|
40
|
-
|
|
41
|
-
# Async file operation using aiofiles
|
|
42
|
-
async with aiofiles.open("data.json", "w") as f:
|
|
43
|
-
await f.write(json.dumps(data))
|
|
44
|
-
|
|
45
|
-
logger.info(f"Data saved, counter: {config_manager.counter}")
|
|
46
|
-
|
|
47
|
-
def validate_items(items: List[str]) -> List[str]:
|
|
48
|
-
"""Validate input items."""
|
|
49
|
-
valid_items = []
|
|
50
|
-
for item in items:
|
|
51
|
-
if not item:
|
|
52
|
-
logger.warning(f"Invalid item: {item}")
|
|
53
|
-
continue
|
|
54
|
-
valid_items.append(item)
|
|
55
|
-
return valid_items
|
|
56
|
-
|
|
57
|
-
def process_items(items: List[str]) -> List[str]:
|
|
58
|
-
"""Process each item."""
|
|
59
|
-
return [item.upper() for item in items]
|
|
60
|
-
|
|
61
|
-
def filter_results(results: List[str]) -> List[str]:
|
|
62
|
-
"""Filter results by length."""
|
|
63
|
-
return [result for result in results if len(result) > 3]
|
|
64
|
-
|
|
65
|
-
def create_summary(items: List[str], results: List[str], filtered: List[str]) -> Dict[str, int]:
|
|
66
|
-
"""Create processing summary."""
|
|
67
|
-
return {
|
|
68
|
-
"total": len(items),
|
|
69
|
-
"processed": len(results),
|
|
70
|
-
"filtered": len(filtered)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async def save_results(filtered: List[str]) -> None:
|
|
74
|
-
"""Save results to file asynchronously."""
|
|
75
|
-
async with aiofiles.open("results.txt", "w") as f:
|
|
76
|
-
for item in filtered:
|
|
77
|
-
await f.write(f"{item}\n")
|
|
78
|
-
|
|
79
|
-
async def process_items_improved(items: List[str], config_manager: ConfigManager) -> Dict[str, Any]:
|
|
80
|
-
"""Improved function broken down into smaller functions."""
|
|
81
|
-
# Step 1: Validate items
|
|
82
|
-
valid_items = validate_items(items)
|
|
83
|
-
|
|
84
|
-
# Step 2: Process each item
|
|
85
|
-
results = process_items(valid_items)
|
|
86
|
-
|
|
87
|
-
# Step 3: Filter results
|
|
88
|
-
filtered = filter_results(results)
|
|
89
|
-
|
|
90
|
-
# Step 4: Sort results
|
|
91
|
-
filtered.sort()
|
|
92
|
-
|
|
93
|
-
# Step 5: Create summary
|
|
94
|
-
summary = create_summary(items, results, filtered)
|
|
95
|
-
|
|
96
|
-
# Step 6: Log summary
|
|
97
|
-
logger.info(f"Processing complete: {summary}")
|
|
98
|
-
|
|
99
|
-
# Step 7: Save results asynchronously
|
|
100
|
-
await save_results(filtered)
|
|
101
|
-
|
|
102
|
-
# Step 8: Update counter
|
|
103
|
-
config_manager.counter += len(filtered)
|
|
104
|
-
|
|
105
|
-
# Step 9: Create report
|
|
106
|
-
report = {
|
|
107
|
-
"summary": summary,
|
|
108
|
-
"results": filtered,
|
|
109
|
-
"counter": config_manager.counter
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return report
|
|
113
|
-
|
|
114
|
-
async def debug_function() -> None:
|
|
115
|
-
"""Function with debug statements."""
|
|
116
|
-
logger.debug("Debug: Starting function")
|
|
117
|
-
|
|
118
|
-
# Reading file asynchronously
|
|
119
|
-
if os.path.exists("debug.log"):
|
|
120
|
-
async with aiofiles.open("debug.log", "r") as f:
|
|
121
|
-
log_data = await f.read()
|
|
122
|
-
logger.debug(f"Log data: {log_data}")
|
|
123
|
-
|
|
124
|
-
logger.debug("Debug: Function complete")
|
|
125
|
-
|
|
126
|
-
# Using var instead of let/const (for JS patterns if analyzed)
|
|
127
|
-
var_example = "This would be flagged in JS"
|
|
128
|
-
|
|
129
|
-
async def main() -> None:
|
|
130
|
-
"""Main execution function."""
|
|
131
|
-
# Set up logging
|
|
132
|
-
logging.basicConfig(level=logging.INFO)
|
|
133
|
-
|
|
134
|
-
# Initialize config manager
|
|
135
|
-
config_manager = ConfigManager()
|
|
136
|
-
|
|
137
|
-
logger.info("Starting application...")
|
|
138
|
-
|
|
139
|
-
try:
|
|
140
|
-
# Note: These operations would fail without actual files, but structure is correct
|
|
141
|
-
await load_config(config_manager)
|
|
142
|
-
await process_items_improved(["test", "data", "example"], config_manager)
|
|
143
|
-
await debug_function()
|
|
144
|
-
except FileNotFoundError:
|
|
145
|
-
logger.warning("Required files not found - this is expected in test context")
|
|
146
|
-
except Exception as e:
|
|
147
|
-
logger.error(f"Application error: {e}")
|
|
148
|
-
|
|
149
|
-
logger.info("Application complete!")
|
|
150
|
-
|
|
151
|
-
if __name__ == "__main__":
|
|
152
|
-
# Run async main function
|
|
153
|
-
asyncio.run(main())
|