tzero-mcp 10.7.0 → 10.7.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/bin/tzero-mcp.js +9 -16
- package/bin/tzero.js +9 -16
- package/index.js +7 -2
- package/package.json +2 -1
- package/src/addmcp.py +1194 -0
- package/src/main.py +60 -0
- package/src/siber_akademi_icon.py +77 -0
- package/src/tzero/jarvis/semantic_compressor.py +373 -0
- package/src/tzero.py +58 -0
- package/src/tzero_benchmark.py +475 -0
- package/src/tzero_bridge.py +362 -0
- package/src/tzero_ci.py +153 -0
- package/src/tzero_commit.py +192 -0
- package/src/tzero_cost.py +163 -0
- package/src/tzero_dashboard.py +1448 -0
- package/src/tzero_deps.py +287 -0
- package/src/tzero_drift.py +208 -0
- package/src/tzero_explain.py +240 -0
- package/src/tzero_features.py +3022 -0
- package/src/tzero_fix.py +228 -0
- package/src/tzero_fixer/__init__.py +63 -0
- package/src/tzero_fixer/amalgamation.py +334 -0
- package/src/tzero_fixer/ast_syntax_healer.py +464 -0
- package/src/tzero_fixer/ast_type_modernizer.py +288 -0
- package/src/tzero_fixer/async_io_modernizer.py +127 -0
- package/src/tzero_fixer/automated_regression_suite.py +600 -0
- package/src/tzero_fixer/benchmarks_and_diagnostics.py +174 -0
- package/src/tzero_fixer/ci_cd_self_healing_gate.py +246 -0
- package/src/tzero_fixer/code_duplicity_and_refactorer.py +151 -0
- package/src/tzero_fixer/code_smells_healer.py +260 -0
- package/src/tzero_fixer/cwe_remediator.py +171 -0
- package/src/tzero_fixer/dead_code_eliminator.py +150 -0
- package/src/tzero_fixer/dependency_vulnerability_auditor.py +309 -0
- package/src/tzero_fixer/git_advanced_surgeon.py +280 -0
- package/src/tzero_fixer/hardware_and_disk_doctor.py +325 -0
- package/src/tzero_fixer/import_graph_healer.py +412 -0
- package/src/tzero_fixer/interactive_tui.py +91 -0
- package/src/tzero_fixer/knowledge_base.py +295 -0
- package/src/tzero_fixer/knowledge_base_extended.py +940 -0
- package/src/tzero_fixer/linters_and_static_analyzer.py +307 -0
- package/src/tzero_fixer/mcp_server.py +447 -0
- package/src/tzero_fixer/models.py +385 -0
- package/src/tzero_fixer/orchestrator.py +375 -0
- package/src/tzero_fixer/os_doctor.py +502 -0
- package/src/tzero_fixer/packaging_abi_surgeon.py +323 -0
- package/src/tzero_fixer/pc_fixer_doctor.py +599 -0
- package/src/tzero_fixer/performance_and_memory_profiler.py +274 -0
- package/src/tzero_fixer/polyglot_ast_parsers.py +313 -0
- package/src/tzero_fixer/polyglot_build_healer.py +364 -0
- package/src/tzero_fixer/polyglot_config_healer.py +318 -0
- package/src/tzero_fixer/polyglot_doctor.py +372 -0
- package/src/tzero_fixer/polyglot_linters.py +619 -0
- package/src/tzero_fixer/polyglot_schema_validator.py +305 -0
- package/src/tzero_fixer/security_cwe_database.py +444 -0
- package/src/tzero_fixer/security_deep_rules.py +114 -0
- package/src/tzero_fixer/security_rules_catalog.py +110 -0
- package/src/tzero_fixer/security_zero_leak.py +326 -0
- package/src/tzero_fixer/smart_patch_recommender.py +223 -0
- package/src/tzero_fixer/synthetic_workspace_generator.py +220 -0
- package/src/tzero_fixer/system_diagnostics_extended.py +493 -0
- package/src/tzero_fixer/system_repair_recipes.py +447 -0
- package/src/tzero_fixer/venv_doctor.py +309 -0
- package/src/tzero_gateway.py +885 -0
- package/src/tzero_guard.py +243 -0
- package/src/tzero_infra.py +274 -0
- package/src/tzero_jarvis/__init__.py +124 -0
- package/src/tzero_jarvis/causal_graph.py +310 -0
- package/src/tzero_jarvis/graph_visualizer.py +395 -0
- package/src/tzero_jarvis/hybrid_search.py +214 -0
- package/src/tzero_jarvis/latent_press.py +137 -0
- package/src/tzero_jarvis/memory_consolidation.py +212 -0
- package/src/tzero_jarvis/minhash_lsh.py +184 -0
- package/src/tzero_jarvis/orchestrator.py +335 -0
- package/src/tzero_jarvis/self_healing.py +308 -0
- package/src/tzero_jarvis/semantic_compressor.py +887 -0
- package/src/tzero_jarvis/swarm.py +261 -0
- package/src/tzero_jarvis/swarm_bft.py +144 -0
- package/src/tzero_jarvis/workspace_orchestrator.py +1167 -0
- package/src/tzero_jarvis/zero_key_router.py +173 -0
- package/src/tzero_mcp.py +4858 -0
- package/src/tzero_neural_cortex.py +1425 -0
- package/src/tzero_packer.py +370 -0
- package/src/tzero_patch.py +624 -0
- package/src/tzero_pc_fixer.py +12657 -0
- package/src/tzero_pipe.py +95 -0
- package/src/tzero_polyglot.py +422 -0
- package/src/tzero_reachability.py +272 -0
- package/src/tzero_replay.py +141 -0
- package/src/tzero_security.py +570 -0
- package/src/tzero_snapshot.py +258 -0
- package/src/tzero_stubs.py +313 -0
- package/src/tzero_superdesign.py +774 -0
- package/src/tzero_sync.py +241 -0
- package/src/tzero_task_benchmark.py +363 -0
- package/src/tzero_tui.py +244 -0
- package/src/tzero_v3.py +9435 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""T-Zero Master Autonomous Orchestrator & Transactional Rollback Engine.
|
|
3
|
+
|
|
4
|
+
Coordinates all specialized doctor engines:
|
|
5
|
+
- OS & Hardware Doctor (OSDoctor)
|
|
6
|
+
- Virtualenv & Dependency Drift Doctor (VenvDoctor)
|
|
7
|
+
- AST Syntax Healer (ASTSyntaxHealer)
|
|
8
|
+
- Import Graph & Cycle Healer (ImportGraphHealer)
|
|
9
|
+
- Code Smells & Modernizer (CodeSmellsHealer)
|
|
10
|
+
- 100% Zero-Leak Security Guard (SecurityZeroLeakDoctor)
|
|
11
|
+
|
|
12
|
+
Features:
|
|
13
|
+
- Transactional file backups with atomic rollback (.tzero/fixer_backups/).
|
|
14
|
+
- Multi-pass convergence loop (diagnose -> heal -> verify AST -> converge).
|
|
15
|
+
- Unified ANSI terminal rendering and JSON / SARIF v2.1.0 report generation.
|
|
16
|
+
|
|
17
|
+
Author: Toprak Ahmet Aydogmus (Siber Akademi)
|
|
18
|
+
Version: 10.5.0
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import shutil
|
|
24
|
+
import sys
|
|
25
|
+
import time
|
|
26
|
+
import uuid
|
|
27
|
+
from dataclasses import asdict
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
30
|
+
|
|
31
|
+
from .ast_syntax_healer import ASTSyntaxHealer
|
|
32
|
+
from .code_smells_healer import CodeSmellsHealer
|
|
33
|
+
from .git_advanced_surgeon import GitAdvancedSurgeon
|
|
34
|
+
from .hardware_and_disk_doctor import HardwareAndDiskSurgeon
|
|
35
|
+
from .import_graph_healer import ImportGraphHealer
|
|
36
|
+
from .models import (
|
|
37
|
+
DiagnosticCategory,
|
|
38
|
+
DiagnosticIssue,
|
|
39
|
+
DiagnosticReport,
|
|
40
|
+
EnvironmentSnapshot,
|
|
41
|
+
HealAction,
|
|
42
|
+
HealReport,
|
|
43
|
+
RollbackManifest,
|
|
44
|
+
SeverityLevel,
|
|
45
|
+
)
|
|
46
|
+
from .os_doctor import OSDoctor
|
|
47
|
+
from .packaging_abi_surgeon import PackagingAbiSurgeon
|
|
48
|
+
from .polyglot_build_healer import PolyglotBuildHealer
|
|
49
|
+
from .cwe_remediator import SecurityCweRemediator
|
|
50
|
+
from .dead_code_eliminator import DeadCodeEliminator
|
|
51
|
+
from .async_io_modernizer import AsyncIoModernizer
|
|
52
|
+
from .security_zero_leak import SecurityZeroLeakDoctor
|
|
53
|
+
from .venv_doctor import VenvDoctor
|
|
54
|
+
|
|
55
|
+
# Safe stdout on Windows
|
|
56
|
+
if sys.platform == "win32":
|
|
57
|
+
try:
|
|
58
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
59
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
60
|
+
if hasattr(sys.stderr, "reconfigure"):
|
|
61
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
62
|
+
except Exception:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class FixerOrchestrator:
|
|
67
|
+
"""Master orchestrator for all diagnosis and autonomous self-healing operations."""
|
|
68
|
+
|
|
69
|
+
BACKUP_ROOT = ".tzero/fixer_backups"
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def create_transaction_backup(cls, workspace_dir: str, files_to_backup: Set[str]) -> RollbackManifest:
|
|
73
|
+
"""Create timestamped transactional backup directory for atomic rollback."""
|
|
74
|
+
tx_id = f"tx_{int(time.time())}_{uuid.uuid4().hex[:6]}"
|
|
75
|
+
backup_dir = os.path.join(workspace_dir, cls.BACKUP_ROOT, tx_id)
|
|
76
|
+
os.makedirs(backup_dir, exist_ok=True)
|
|
77
|
+
|
|
78
|
+
manifest = RollbackManifest(
|
|
79
|
+
transaction_id=tx_id,
|
|
80
|
+
timestamp=time.time(),
|
|
81
|
+
target_dir=str(Path(workspace_dir).resolve()),
|
|
82
|
+
backup_dir=backup_dir,
|
|
83
|
+
backed_up_files={}
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
for src_f in files_to_backup:
|
|
87
|
+
if os.path.isfile(src_f):
|
|
88
|
+
rel_f = os.path.relpath(src_f, workspace_dir).replace(os.sep, "_")
|
|
89
|
+
dest_f = os.path.join(backup_dir, rel_f)
|
|
90
|
+
shutil.copy2(src_f, dest_f)
|
|
91
|
+
manifest.backed_up_files[src_f] = dest_f
|
|
92
|
+
|
|
93
|
+
manifest_file = os.path.join(backup_dir, "manifest.json")
|
|
94
|
+
manifest.save(manifest_file)
|
|
95
|
+
return manifest
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def rollback_transaction(cls, workspace_dir: str, transaction_id: str) -> bool:
|
|
99
|
+
"""Restore all original files from a previous transactional backup."""
|
|
100
|
+
backup_dir = os.path.join(workspace_dir, cls.BACKUP_ROOT, transaction_id)
|
|
101
|
+
manifest_file = os.path.join(backup_dir, "manifest.json")
|
|
102
|
+
if not os.path.isfile(manifest_file):
|
|
103
|
+
print(f"\033[31m[ERROR] Manifest not found for transaction '{transaction_id}'\033[0m")
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
manifest = RollbackManifest.load(manifest_file)
|
|
107
|
+
restored = 0
|
|
108
|
+
for orig_p, backup_p in manifest.backed_up_files.items():
|
|
109
|
+
if os.path.isfile(backup_p):
|
|
110
|
+
shutil.copy2(backup_p, orig_p)
|
|
111
|
+
restored += 1
|
|
112
|
+
|
|
113
|
+
print(f"\033[32m✔ Successfully rolled back transaction {transaction_id} ({restored} files restored)\033[0m")
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def calculate_health_score(cls, issues: List[DiagnosticIssue]) -> float:
|
|
118
|
+
"""Compute 0.0-100.0 overall health score based on issue counts and severity weights."""
|
|
119
|
+
if not issues:
|
|
120
|
+
return 100.0
|
|
121
|
+
crit = sum(1 for i in issues if i.severity == SeverityLevel.CRITICAL.value)
|
|
122
|
+
err = sum(1 for i in issues if i.severity == SeverityLevel.ERROR.value)
|
|
123
|
+
warn = sum(1 for i in issues if i.severity == SeverityLevel.WARNING.value)
|
|
124
|
+
info = sum(1 for i in issues if i.severity == SeverityLevel.INFO.value)
|
|
125
|
+
|
|
126
|
+
penalty = (crit * 5.0) + (err * 3.0) + (warn * 1.0) + (info * 0.2)
|
|
127
|
+
score = 100.0 / (1.0 + penalty * 0.02)
|
|
128
|
+
return round(score, 1)
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def diagnose_workspace(cls, workspace_dir: str = ".") -> DiagnosticReport:
|
|
132
|
+
"""Run complete, multi-category diagnostic sweep across the entire workspace."""
|
|
133
|
+
t0 = time.time()
|
|
134
|
+
root = Path(workspace_dir).resolve()
|
|
135
|
+
issues: List[DiagnosticIssue] = []
|
|
136
|
+
|
|
137
|
+
# 1. Environment & Tools
|
|
138
|
+
env_snapshot = OSDoctor.capture_snapshot(workspace_dir)
|
|
139
|
+
issues.extend(OSDoctor.check_windows_registry_settings())
|
|
140
|
+
issues.extend(OSDoctor.check_path_environment())
|
|
141
|
+
issues.extend(OSDoctor.check_file_locks_and_permissions(workspace_dir))
|
|
142
|
+
issues.extend(OSDoctor.check_bytecode_and_temp_bloat(workspace_dir))
|
|
143
|
+
|
|
144
|
+
# 2. Virtualenv & Dependencies
|
|
145
|
+
issues.extend(VenvDoctor.diagnose(workspace_dir))
|
|
146
|
+
|
|
147
|
+
# 3. Import Graph & Cycles
|
|
148
|
+
issues.extend(ImportGraphHealer.diagnose_workspace(workspace_dir))
|
|
149
|
+
|
|
150
|
+
# 4. Packaging, PEP 517 & ABI
|
|
151
|
+
issues.extend(PackagingAbiSurgeon.diagnose_workspace(workspace_dir))
|
|
152
|
+
|
|
153
|
+
# 5. Git VCS Integrity & Locks
|
|
154
|
+
issues.extend(GitAdvancedSurgeon.diagnose_workspace(workspace_dir))
|
|
155
|
+
|
|
156
|
+
# 6. Polyglot Build & Infrastructure
|
|
157
|
+
issues.extend(PolyglotBuildHealer.diagnose_workspace(workspace_dir))
|
|
158
|
+
|
|
159
|
+
# 4. File-by-file AST, Smells, Security
|
|
160
|
+
scanned_files = 0
|
|
161
|
+
for root_dir, dirs, files in os.walk(str(root)):
|
|
162
|
+
dirs[:] = [d for d in dirs if d not in OSDoctor.IGNORED_DIRS]
|
|
163
|
+
for file in files:
|
|
164
|
+
if file.endswith(".py"):
|
|
165
|
+
full_p = os.path.join(root_dir, file)
|
|
166
|
+
scanned_files += 1
|
|
167
|
+
# Syntax & Encoding
|
|
168
|
+
issues.extend(ASTSyntaxHealer.diagnose_file(full_p))
|
|
169
|
+
# Code Smells
|
|
170
|
+
issues.extend(CodeSmellsHealer.diagnose_file(full_p))
|
|
171
|
+
# Security & Zero-Leak
|
|
172
|
+
issues.extend(SecurityZeroLeakDoctor.diagnose_file(full_p))
|
|
173
|
+
# CWE Security Remediations
|
|
174
|
+
issues.extend(SecurityCweRemediator.diagnose_file(full_p))
|
|
175
|
+
# Dead Code & Unreachable Stmts
|
|
176
|
+
issues.extend(DeadCodeEliminator.diagnose_file(full_p))
|
|
177
|
+
# AsyncIO Blocking Checks
|
|
178
|
+
issues.extend(AsyncIoModernizer.diagnose_file(full_p))
|
|
179
|
+
|
|
180
|
+
# Tallies
|
|
181
|
+
crit_c = sum(1 for i in issues if i.severity == SeverityLevel.CRITICAL.value)
|
|
182
|
+
err_c = sum(1 for i in issues if i.severity == SeverityLevel.ERROR.value)
|
|
183
|
+
warn_c = sum(1 for i in issues if i.severity == SeverityLevel.WARNING.value)
|
|
184
|
+
info_c = sum(1 for i in issues if i.severity == SeverityLevel.INFO.value)
|
|
185
|
+
|
|
186
|
+
syntax_c = sum(1 for i in issues if i.category == DiagnosticCategory.SYNTAX.value)
|
|
187
|
+
import_c = sum(1 for i in issues if i.category == DiagnosticCategory.IMPORTS.value)
|
|
188
|
+
env_c = sum(1 for i in issues if i.category == DiagnosticCategory.ENVIRONMENT.value)
|
|
189
|
+
sec_c = sum(1 for i in issues if i.category == DiagnosticCategory.SECURITY.value)
|
|
190
|
+
smell_c = sum(1 for i in issues if i.category in (DiagnosticCategory.SMELLS.value, DiagnosticCategory.PERFORMANCE.value))
|
|
191
|
+
cache_c = sum(1 for i in issues if i.category in (DiagnosticCategory.CACHE.value, DiagnosticCategory.ENCODING.value))
|
|
192
|
+
|
|
193
|
+
score = cls.calculate_health_score(issues)
|
|
194
|
+
duration_ms = round((time.time() - t0) * 1000, 2)
|
|
195
|
+
|
|
196
|
+
return DiagnosticReport(
|
|
197
|
+
timestamp=time.time(),
|
|
198
|
+
target_dir=str(root),
|
|
199
|
+
health_score_pct=score,
|
|
200
|
+
total_issues=len(issues),
|
|
201
|
+
critical_count=crit_c,
|
|
202
|
+
error_count=err_c,
|
|
203
|
+
warning_count=warn_c,
|
|
204
|
+
info_count=info_c,
|
|
205
|
+
syntax_errors=syntax_c,
|
|
206
|
+
missing_imports=import_c,
|
|
207
|
+
env_issues=env_c,
|
|
208
|
+
security_leaks=sec_c,
|
|
209
|
+
code_smells=smell_c,
|
|
210
|
+
cache_issues=cache_c,
|
|
211
|
+
issues=issues,
|
|
212
|
+
environment=env_snapshot,
|
|
213
|
+
scan_duration_ms=duration_ms,
|
|
214
|
+
scanned_file_count=scanned_files
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
@classmethod
|
|
218
|
+
def auto_heal(cls, workspace_dir: str = ".", dry_run: bool = False, max_iterations: int = 3) -> HealReport:
|
|
219
|
+
"""Execute autonomous self-healing convergence loop across all categories."""
|
|
220
|
+
t0 = time.time()
|
|
221
|
+
initial_diag = cls.diagnose_workspace(workspace_dir)
|
|
222
|
+
all_actions: List[HealAction] = []
|
|
223
|
+
manifest = None
|
|
224
|
+
|
|
225
|
+
if initial_diag.total_issues > 0 and not dry_run:
|
|
226
|
+
# Gather files to backup
|
|
227
|
+
files_to_backup: Set[str] = set()
|
|
228
|
+
for issue in initial_diag.issues:
|
|
229
|
+
if issue.file_path and os.path.isfile(issue.file_path):
|
|
230
|
+
files_to_backup.add(issue.file_path)
|
|
231
|
+
if files_to_backup:
|
|
232
|
+
manifest = cls.create_transaction_backup(workspace_dir, files_to_backup)
|
|
233
|
+
|
|
234
|
+
current_issues = initial_diag.issues
|
|
235
|
+
|
|
236
|
+
# Convergence passes
|
|
237
|
+
for iteration in range(1, max_iterations + 1):
|
|
238
|
+
if not current_issues:
|
|
239
|
+
break
|
|
240
|
+
|
|
241
|
+
pass_actions: List[HealAction] = []
|
|
242
|
+
# 1. OS & Cache Heals
|
|
243
|
+
pass_actions.extend(OSDoctor.execute_os_heals(current_issues, dry_run=dry_run))
|
|
244
|
+
|
|
245
|
+
# 2. Virtualenv Heals
|
|
246
|
+
pass_actions.extend(VenvDoctor.execute_venv_heals(current_issues, dry_run=dry_run))
|
|
247
|
+
|
|
248
|
+
# 3. Syntax & Encoding Heals
|
|
249
|
+
pass_actions.extend(ASTSyntaxHealer.execute_syntax_heals(current_issues, dry_run=dry_run))
|
|
250
|
+
|
|
251
|
+
# 4. Import Heals
|
|
252
|
+
pass_actions.extend(ImportGraphHealer.execute_import_heals(current_issues, dry_run=dry_run))
|
|
253
|
+
|
|
254
|
+
# 5. Code Smell Heals
|
|
255
|
+
pass_actions.extend(CodeSmellsHealer.execute_smell_heals(current_issues, dry_run=dry_run))
|
|
256
|
+
|
|
257
|
+
# 6. Security Heals
|
|
258
|
+
pass_actions.extend(SecurityZeroLeakDoctor.execute_security_heals(current_issues, workspace_dir, dry_run=dry_run))
|
|
259
|
+
|
|
260
|
+
# 7. Packaging Heals
|
|
261
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") in ("missing_build_system", "broken_pyvenv_home", "stale_egg_info", "legacy_setup_py")]:
|
|
262
|
+
pass_actions.append(PackagingAbiSurgeon.heal_issue(issue, dry_run=dry_run))
|
|
263
|
+
|
|
264
|
+
# 8. Git VCS Heals
|
|
265
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") in ("stale_git_lock", "missing_gitattributes")]:
|
|
266
|
+
pass_actions.append(GitAdvancedSurgeon.heal_issue(issue, dry_run=dry_run))
|
|
267
|
+
|
|
268
|
+
# 9. Polyglot Build Heals
|
|
269
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") in ("missing_dockerignore", "makefile_spaces_to_tabs", "makefile_missing_phony", "docker_add_to_copy")]:
|
|
270
|
+
pass_actions.append(PolyglotBuildHealer.heal_issue(issue, dry_run=dry_run))
|
|
271
|
+
|
|
272
|
+
# 10. CWE Remediations
|
|
273
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") in ("cwe_78_shell_injection", "cwe_89_sql_injection", "cwe_327_weak_hash")]:
|
|
274
|
+
pass_actions.append(SecurityCweRemediator.heal_issue(issue, dry_run=dry_run))
|
|
275
|
+
|
|
276
|
+
# 11. Dead Code Prunes
|
|
277
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") == "unreachable_code"]:
|
|
278
|
+
pass_actions.append(DeadCodeEliminator.heal_issue(issue, dry_run=dry_run))
|
|
279
|
+
|
|
280
|
+
# 12. AsyncIO Modernizations
|
|
281
|
+
for issue in [i for i in current_issues if i.metadata.get("issue_type") == "async_time_sleep"]:
|
|
282
|
+
pass_actions.append(AsyncIoModernizer.heal_issue(issue, dry_run=dry_run))
|
|
283
|
+
|
|
284
|
+
all_actions.extend(pass_actions)
|
|
285
|
+
|
|
286
|
+
if dry_run or not pass_actions:
|
|
287
|
+
break
|
|
288
|
+
|
|
289
|
+
# Re-diagnose to verify convergence
|
|
290
|
+
post_pass_diag = cls.diagnose_workspace(workspace_dir)
|
|
291
|
+
current_issues = [i for i in post_pass_diag.issues if i.auto_fixable]
|
|
292
|
+
|
|
293
|
+
final_diag = cls.diagnose_workspace(workspace_dir) if not dry_run else initial_diag
|
|
294
|
+
duration_ms = round((time.time() - t0) * 1000, 2)
|
|
295
|
+
healed_count = sum(1 for a in all_actions if a.success)
|
|
296
|
+
|
|
297
|
+
return HealReport(
|
|
298
|
+
timestamp=time.time(),
|
|
299
|
+
target_dir=str(Path(workspace_dir).resolve()),
|
|
300
|
+
transaction_id=manifest.transaction_id if manifest else "dry_run",
|
|
301
|
+
initial_health_score=initial_diag.health_score_pct,
|
|
302
|
+
final_health_score=final_diag.health_score_pct,
|
|
303
|
+
issues_detected=initial_diag.total_issues,
|
|
304
|
+
issues_healed=healed_count,
|
|
305
|
+
dry_run=dry_run,
|
|
306
|
+
actions=all_actions,
|
|
307
|
+
backup_manifest=manifest,
|
|
308
|
+
execution_duration_ms=duration_ms
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
@classmethod
|
|
312
|
+
def render_cli(cls, diag: DiagnosticReport, heal: Optional[HealReport] = None):
|
|
313
|
+
"""Render high-contrast, beautiful ANSI terminal cockpit report."""
|
|
314
|
+
print("=" * 80)
|
|
315
|
+
print("\033[1;36m🩺 T-ZERO MASTER PC-FIXER & ENVIRONMENT AUTONOMOUS DOCTOR v10.5.0\033[0m")
|
|
316
|
+
print("=" * 80)
|
|
317
|
+
print(f"Target Directory: \033[33m{diag.target_dir}\033[0m")
|
|
318
|
+
print(f"Host OS: \033[32m{diag.environment.os_release}\033[0m (Arch: {diag.environment.python_architecture})")
|
|
319
|
+
print(f"Python Runtime: \033[32mv{diag.environment.python_version}\033[0m ({diag.environment.python_executable})")
|
|
320
|
+
print(f"Virtualenv: \033[32m{diag.environment.virtualenv_root or 'Global / System Python'}\033[0m")
|
|
321
|
+
print(f"Hardware Stats: \033[36m{diag.environment.cpu_cores} Cores\033[0m | \033[36m{diag.environment.available_ram_gb:.1f}GB / {diag.environment.total_ram_gb:.1f}GB Free RAM\033[0m")
|
|
322
|
+
|
|
323
|
+
# Tools status
|
|
324
|
+
tools_str = " ".join([
|
|
325
|
+
f"\033[32m[✔ {t}]\033[0m" if s.available else f"\033[31m[✘ {t}]\033[0m"
|
|
326
|
+
for t, s in diag.environment.tools.items()
|
|
327
|
+
])
|
|
328
|
+
print(f"CLI Toolchain: {tools_str}")
|
|
329
|
+
|
|
330
|
+
score_color = "\033[1;32m" if diag.health_score_pct >= 90 else ("\033[1;33m" if diag.health_score_pct >= 70 else "\033[1;31m")
|
|
331
|
+
print(f"Health Score: {score_color}{diag.health_score_pct} / 100\033[0m "
|
|
332
|
+
f"(\033[35m{diag.scanned_file_count} files scanned in {diag.scan_duration_ms}ms\033[0m)")
|
|
333
|
+
print("-" * 80)
|
|
334
|
+
|
|
335
|
+
if diag.total_issues == 0:
|
|
336
|
+
print("\033[1;32m✨ Codebase and host environment are in 100% pristine condition! Zero defects found.\033[0m")
|
|
337
|
+
else:
|
|
338
|
+
print(f"Detected Issues: \033[1;31m{diag.total_issues}\033[0m "
|
|
339
|
+
f"(\033[1;31mCrit: {diag.critical_count}\033[0m, \033[31mErr: {diag.error_count}\033[0m, "
|
|
340
|
+
f"\033[33mWarn: {diag.warning_count}\033[0m, \033[36mInfo: {diag.info_count}\033[0m)")
|
|
341
|
+
print(f"Breakdown: Syntax: \033[31m{diag.syntax_errors}\033[0m | "
|
|
342
|
+
f"Imports: \033[33m{diag.missing_imports}\033[0m | "
|
|
343
|
+
f"Security: \033[1;31m{diag.security_leaks}\033[0m | "
|
|
344
|
+
f"Env: \033[35m{diag.env_issues}\033[0m | "
|
|
345
|
+
f"Cache: \033[36m{diag.cache_issues}\033[0m")
|
|
346
|
+
print()
|
|
347
|
+
|
|
348
|
+
for idx, issue in enumerate(diag.issues[:20], start=1):
|
|
349
|
+
sev_color = "\033[1;31m" if issue.severity == "critical" else ("\033[31m" if issue.severity == "error" else "\033[33m")
|
|
350
|
+
loc = issue.formatted_location
|
|
351
|
+
print(f" {idx:2d}. {sev_color}[{issue.severity.upper():<4}]\033[0m \033[1m{loc:<26}\033[0m {issue.message}")
|
|
352
|
+
print(f" \033[36mFix:\033[0m {issue.suggested_fix}")
|
|
353
|
+
|
|
354
|
+
if len(diag.issues) > 20:
|
|
355
|
+
print(f" ... and {len(diag.issues) - 20} more diagnostic issues.")
|
|
356
|
+
|
|
357
|
+
if heal:
|
|
358
|
+
print("-" * 80)
|
|
359
|
+
print("\033[1;32m💉 AUTONOMOUS SELF-HEALING EXECUTION RESULTS:\033[0m")
|
|
360
|
+
print(f" Transaction ID: \033[35m{heal.transaction_id}\033[0m")
|
|
361
|
+
print(f" Issues Healed: \033[32m{heal.issues_healed} / {heal.issues_detected}\033[0m")
|
|
362
|
+
print(f" Health Boost: \033[33m{heal.initial_health_score}%\033[0m -> \033[1;32m{heal.final_health_score}%\033[0m")
|
|
363
|
+
print(f" Execution Time: \033[36m{heal.execution_duration_ms:.2f} ms\033[0m")
|
|
364
|
+
|
|
365
|
+
for a in heal.actions[:12]:
|
|
366
|
+
status_icon = "\033[32m✔\033[0m" if a.success else "\033[31m✘\033[0m"
|
|
367
|
+
print(f" {status_icon} [{a.category.upper()}] {a.description}")
|
|
368
|
+
if a.diff:
|
|
369
|
+
for dline in a.diff.splitlines()[:3]:
|
|
370
|
+
print(f" \033[35m{dline}\033[0m")
|
|
371
|
+
|
|
372
|
+
if len(heal.actions) > 12:
|
|
373
|
+
print(f" ... and {len(heal.actions) - 12} additional repairs.")
|
|
374
|
+
|
|
375
|
+
print("=" * 80)
|