SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,523
Folders
410
Scanned Size
3.85 GB
PHP Files
894
Editable Text Files
12,784
File viewer
guarded to /htdocs
/simon/data/evolution_core.php
<?php declare(strict_types=1); final class SimonEvolutionCore { private string $baseDir; private string $dataDir; public function __construct(?string $baseDir = null) { $this->baseDir = $baseDir ?: __DIR__; $this->dataDir = $this->baseDir . '/_data'; if (!is_dir($this->dataDir) && !@mkdir($this->dataDir, 0755, true) && !is_dir($this->dataDir)) { throw new RuntimeException('Unable to create Phase 3 data directory.'); } $this->bootstrap(); } public function status(): array { $cycles = $this->read('cycles.json', []); $candidates = $this->read('candidates.json', []); $deployments = $this->read('deployments.json', []); $events = $this->read('events.json', []); $manifest = $this->loadManifest(); return [ 'ok' => true, 'generated_at' => gmdate('c'), 'counts' => [ 'manifest_functions' => count($manifest['functions'] ?? []), 'cycles' => count($cycles), 'active_cycles' => count(array_filter($cycles, fn(array $c): bool => !in_array($c['status'] ?? '', ['completed','rolled_back','rejected'], true))), 'candidates' => count($candidates), 'deployments' => count($deployments), 'events' => count($events), ], 'cycles' => array_values(array_slice(array_reverse($cycles), 0, 20)), 'candidates' => array_values(array_slice(array_reverse($candidates), 0, 30)), 'deployments' => array_values(array_slice(array_reverse($deployments), 0, 20)), 'events' => array_values(array_slice(array_reverse($events), 0, 50)), 'manifest' => [ 'path' => $manifest['_path'] ?? null, 'version' => $manifest['manifest_version'] ?? null, 'generated_at' => $manifest['generated_at'] ?? null, ], ]; } public function startCycle(array $input): array { $role = trim((string)($input['role'] ?? '')); if ($role === '') { throw new InvalidArgumentException('Function role is required.'); } $cycles = $this->read('cycles.json', []); $cycle = [ 'cycle_id' => $this->uuid(), 'role' => $role, 'current_version' => trim((string)($input['current_version'] ?? '1.0.0')) ?: '1.0.0', 'trigger' => trim((string)($input['trigger'] ?? 'manual_review')) ?: 'manual_review', 'authority' => trim((string)($input['authority'] ?? 'approval_required')) ?: 'approval_required', 'risk' => $this->clamp((float)($input['risk'] ?? 0.25)), 'confidence' => $this->clamp((float)($input['confidence'] ?? 0.70)), 'status' => 'candidate_generation', 'created_at' => gmdate('c'), 'updated_at' => gmdate('c'), ]; $cycles[] = $cycle; $this->write('cycles.json', $cycles); $this->event('evolution.cycle.started', $cycle); return $cycle; } public function createCandidate(array $input): array { $cycleId = trim((string)($input['cycle_id'] ?? '')); $name = trim((string)($input['name'] ?? '')); if ($cycleId === '' || $name === '') { throw new InvalidArgumentException('Cycle ID and candidate name are required.'); } $cycle = $this->findCycle($cycleId); $candidates = $this->read('candidates.json', []); $candidate = [ 'candidate_id' => $this->uuid(), 'cycle_id' => $cycleId, 'role' => $cycle['role'], 'name' => $name, 'strategy' => trim((string)($input['strategy'] ?? 'refactor')) ?: 'refactor', 'description' => trim((string)($input['description'] ?? '')), 'proposed_version' => trim((string)($input['proposed_version'] ?? $this->nextVersion((string)$cycle['current_version']))), 'status' => 'ready_for_test', 'score' => null, 'metrics' => null, 'created_at' => gmdate('c'), 'updated_at' => gmdate('c'), ]; $candidates[] = $candidate; $this->write('candidates.json', $candidates); $this->updateCycle($cycleId, ['status' => 'testing']); $this->event('evolution.candidate.created', $candidate); return $candidate; } public function runTest(array $input): array { $candidateId = trim((string)($input['candidate_id'] ?? '')); $candidate = $this->findCandidate($candidateId); $seed = abs(crc32($candidateId . gmdate('Y-m-d-H'))); $correctness = 82 + ($seed % 18); $compatibility = 78 + (($seed >> 2) % 22); $security = 80 + (($seed >> 4) % 20); $performance = -5 + (($seed >> 6) % 31); $testCoverage = 70 + (($seed >> 8) % 30); $failures = ($correctness < 90 ? 1 : 0) + ($compatibility < 88 ? 1 : 0); $score = round(($correctness * .30) + ($compatibility * .25) + ($security * .20) + ($testCoverage * .15) + (max(0, min(100, 70 + $performance)) * .10), 1); $metrics = [ 'correctness' => $correctness, 'compatibility' => $compatibility, 'security' => $security, 'performance_gain_percent' => $performance, 'test_coverage' => $testCoverage, 'failures' => $failures, 'tests_run' => 24 + ($seed % 37), ]; $status = $failures === 0 && $score >= 86 ? 'shadow_ready' : 'revision_required'; $updated = $this->updateCandidate($candidateId, [ 'status' => $status, 'score' => $score, 'metrics' => $metrics, 'tested_at' => gmdate('c'), ]); $this->event('evolution.candidate.tested', ['candidate_id' => $candidateId, 'score' => $score, 'status' => $status, 'metrics' => $metrics]); return $updated; } public function runShadow(array $input): array { $candidateId = trim((string)($input['candidate_id'] ?? '')); $candidate = $this->findCandidate($candidateId); if (!in_array($candidate['status'], ['shadow_ready','canary_ready'], true)) { throw new RuntimeException('Candidate must pass tests before shadow execution.'); } $seed = abs(crc32('shadow-' . $candidateId . gmdate('Y-m-d-H'))); $requests = 100 + ($seed % 901); $agreement = round(94 + (($seed % 600) / 100), 2); $errorDelta = round(-2 + (($seed % 400) / 100), 2); $latencyDelta = round(-18 + (($seed % 3200) / 100), 2); $passed = $agreement >= 97.0 && $errorDelta <= 0.5; $result = [ 'requests_compared' => $requests, 'output_agreement_percent' => $agreement, 'error_rate_delta_percent' => $errorDelta, 'latency_delta_percent' => $latencyDelta, 'passed' => $passed, ]; $status = $passed ? 'canary_ready' : 'revision_required'; $updated = $this->updateCandidate($candidateId, [ 'status' => $status, 'shadow' => $result, 'shadow_at' => gmdate('c'), ]); $this->event('evolution.shadow.completed', ['candidate_id' => $candidateId, 'status' => $status, 'result' => $result]); return $updated; } public function startCanary(array $input): array { $candidateId = trim((string)($input['candidate_id'] ?? '')); $percent = max(1, min(100, (int)($input['percent'] ?? 5))); $candidate = $this->findCandidate($candidateId); if ($candidate['status'] !== 'canary_ready') { throw new RuntimeException('Candidate is not ready for canary deployment.'); } $deployments = $this->read('deployments.json', []); $deployment = [ 'deployment_id' => $this->uuid(), 'candidate_id' => $candidateId, 'cycle_id' => $candidate['cycle_id'], 'role' => $candidate['role'], 'version' => $candidate['proposed_version'], 'mode' => 'canary', 'traffic_percent' => $percent, 'status' => 'active', 'baseline_error_rate' => 1.2, 'current_error_rate' => 1.0, 'baseline_latency_ms' => 420, 'current_latency_ms' => 390, 'started_at' => gmdate('c'), 'updated_at' => gmdate('c'), ]; $deployments[] = $deployment; $this->write('deployments.json', $deployments); $this->updateCandidate($candidateId, ['status' => 'canary_active']); $this->updateCycle((string)$candidate['cycle_id'], ['status' => 'canary']); $this->event('evolution.canary.started', $deployment); return $deployment; } public function advanceCanary(array $input): array { $deploymentId = trim((string)($input['deployment_id'] ?? '')); $target = max(1, min(100, (int)($input['percent'] ?? 25))); $deployments = $this->read('deployments.json', []); foreach ($deployments as &$deployment) { if (($deployment['deployment_id'] ?? '') !== $deploymentId) continue; if (($deployment['status'] ?? '') !== 'active') throw new RuntimeException('Deployment is not active.'); $deployment['traffic_percent'] = $target; $deployment['updated_at'] = gmdate('c'); if ($target === 100) { $deployment['status'] = 'completed'; $deployment['completed_at'] = gmdate('c'); $this->updateCandidate((string)$deployment['candidate_id'], ['status' => 'canonical']); $this->updateCycle((string)$deployment['cycle_id'], ['status' => 'completed']); } $this->write('deployments.json', $deployments); $this->event('evolution.canary.advanced', $deployment); return $deployment; } throw new RuntimeException('Deployment not found.'); } public function rollback(array $input): array { $deploymentId = trim((string)($input['deployment_id'] ?? '')); $reason = trim((string)($input['reason'] ?? 'manual rollback')) ?: 'manual rollback'; $deployments = $this->read('deployments.json', []); foreach ($deployments as &$deployment) { if (($deployment['deployment_id'] ?? '') !== $deploymentId) continue; $deployment['status'] = 'rolled_back'; $deployment['rollback_reason'] = $reason; $deployment['rolled_back_at'] = gmdate('c'); $deployment['updated_at'] = gmdate('c'); $this->write('deployments.json', $deployments); $this->updateCandidate((string)$deployment['candidate_id'], ['status' => 'rolled_back']); $this->updateCycle((string)$deployment['cycle_id'], ['status' => 'rolled_back']); $this->event('evolution.rollback.completed', $deployment); return $deployment; } throw new RuntimeException('Deployment not found.'); } public function seedDemo(): array { if (count($this->read('cycles.json', [])) > 0) return $this->status(); $cycle = $this->startCycle([ 'role' => 'telemetry.event.record', 'current_version' => '1.4.0', 'trigger' => 'duplicate_functions_detected', 'risk' => .18, 'confidence' => .91, ]); $candidate = $this->createCandidate([ 'cycle_id' => $cycle['cycle_id'], 'name' => 'Unified Telemetry Writer', 'strategy' => 'merge_and_normalize', 'description' => 'Combines validation, structured logging, and reusable stream routing.', ]); $this->runTest(['candidate_id' => $candidate['candidate_id']]); return $this->status(); } private function bootstrap(): void { foreach (['cycles.json','candidates.json','deployments.json','events.json'] as $file) { $path = $this->dataDir . '/' . $file; if (!is_file($path)) $this->write($file, []); } } private function loadManifest(): array { $paths = [ $this->baseDir . '/function_flow_manifest.json', dirname($this->baseDir) . '/function_flow_manifest.json', dirname($this->baseDir) . '/_data/simon/function_flow_manifest.json', $this->baseDir . '/_data/simon/function_flow_manifest.json', ]; foreach ($paths as $path) { if (!is_file($path)) continue; $data = json_decode((string)file_get_contents($path), true); if (is_array($data)) { $data['_path'] = $path; return $data; } } return ['functions' => [], '_path' => null]; } private function event(string $type, array $data): void { $events = $this->read('events.json', []); $events[] = [ 'event_id' => $this->uuid(), 'type' => $type, 'data' => $this->sanitize($data), 'created_at' => gmdate('c'), ]; if (count($events) > 5000) $events = array_slice($events, -5000); $this->write('events.json', $events); } private function sanitize(mixed $value): mixed { if (!is_array($value)) return $value; $blocked = ['password','token','secret','api_key','authorization','cookie']; $out = []; foreach ($value as $k => $v) { $key = strtolower((string)$k); $out[$k] = in_array($key, $blocked, true) ? '[REDACTED]' : $this->sanitize($v); } return $out; } private function findCycle(string $id): array { foreach ($this->read('cycles.json', []) as $cycle) if (($cycle['cycle_id'] ?? '') === $id) return $cycle; throw new RuntimeException('Evolution cycle not found.'); } private function findCandidate(string $id): array { foreach ($this->read('candidates.json', []) as $candidate) if (($candidate['candidate_id'] ?? '') === $id) return $candidate; throw new RuntimeException('Candidate not found.'); } private function updateCycle(string $id, array $changes): array { $cycles = $this->read('cycles.json', []); foreach ($cycles as &$cycle) { if (($cycle['cycle_id'] ?? '') !== $id) continue; $cycle = array_merge($cycle, $changes, ['updated_at' => gmdate('c')]); $this->write('cycles.json', $cycles); return $cycle; } throw new RuntimeException('Evolution cycle not found.'); } private function updateCandidate(string $id, array $changes): array { $candidates = $this->read('candidates.json', []); foreach ($candidates as &$candidate) { if (($candidate['candidate_id'] ?? '') !== $id) continue; $candidate = array_merge($candidate, $changes, ['updated_at' => gmdate('c')]); $this->write('candidates.json', $candidates); return $candidate; } throw new RuntimeException('Candidate not found.'); } private function read(string $file, array $default): array { $path = $this->dataDir . '/' . $file; if (!is_file($path)) return $default; $fp = @fopen($path, 'rb'); if (!$fp) return $default; try { flock($fp, LOCK_SH); $raw = stream_get_contents($fp); flock($fp, LOCK_UN); } finally { fclose($fp); } $data = json_decode((string)$raw, true); return is_array($data) ? $data : $default; } private function write(string $file, array $data): void { $path = $this->dataDir . '/' . $file; $tmp = $path . '.tmp'; $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR); if (file_put_contents($tmp, $json, LOCK_EX) === false) throw new RuntimeException('Unable to write ' . $file); @chmod($tmp, 0640); if (!@rename($tmp, $path)) { @unlink($tmp); throw new RuntimeException('Unable to replace ' . $file); } } private function uuid(): string { $d = random_bytes(16); $d[6] = chr((ord($d[6]) & 0x0f) | 0x40); $d[8] = chr((ord($d[8]) & 0x3f) | 0x80); return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($d), 4)); } private function clamp(float $v): float { return max(0.0, min(1.0, $v)); } private function nextVersion(string $version): string { $parts = array_map('intval', explode('.', preg_replace('/[^0-9.]/', '', $version))); while (count($parts) < 3) $parts[] = 0; $parts[1]++; $parts[2] = 0; return implode('.', array_slice($parts, 0, 3)); } }
Save file
Quick jump
open a path
Open