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,025
Folders
377
Scanned Size
3.79 GB
PHP Files
791
Editable Text Files
12,309
File viewer
guarded to /htdocs
/connlink/simon_connlink_ready.php
<?php declare(strict_types=1); date_default_timezone_set('America/Chicago'); $DATA_DIR = __DIR__ . '/data'; function jsonResponse(array $payload, int $statusCode = 200): void { http_response_code($statusCode); header('Content-Type: application/json; charset=utf-8'); echo json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); exit; } function scanJsonFiles(string $dir): array { if (!is_dir($dir)) return []; $files = glob(rtrim($dir, '/\\') . '/*.json') ?: []; usort($files, static fn($a, $b) => filemtime($b) <=> filemtime($a)); return array_values($files); } function loadJson(string $file, array $fallback = []): array { if (!is_file($file)) return $fallback; $raw = file_get_contents($file); if ($raw === false || trim($raw) === '') return $fallback; $decoded = json_decode($raw, true); return is_array($decoded) ? $decoded : $fallback; } function latestMatchingJson(string $dir, string $needle): ?string { foreach (scanJsonFiles($dir) as $file) { if (stripos(basename($file), $needle) !== false) return $file; } return null; } function loadConnectorRegistry(string $dir): array { $file = latestMatchingJson($dir, 'connlink_connectors'); $payload = $file ? loadJson($file, []) : []; return [ 'file' => $file ? basename($file) : null, 'generated_at' => $payload['generated_at'] ?? null, 'summary' => $payload['summary'] ?? [], 'connectors' => $payload['connectors'] ?? [], ]; } function buildRecommendations(array $connectors): array { $healthy = count(array_filter($connectors, static fn($c) => ($c['derived_status'] ?? '') === 'healthy')); $pending = count(array_filter($connectors, static fn($c) => ($c['derived_status'] ?? '') === 'pending')); $items = []; $items[] = $healthy > 0 ? 'Healthy connectors are available. Start by wiring the real chat and health routes into the provider router.' : 'No connectors are marked healthy yet. Validate registry JSON and readiness scoring before deploy.'; if ($pending > 0) $items[] = "Pending connectors detected: {$pending}. Use connector tests before enabling write actions."; $items[] = 'Use the data folder auto-pickup to keep the shell synced with new JSON exports from Excel.'; $items[] = 'Promote high-priority carriers from planned to tested before adding write or deploy actions.'; return $items; } function buildAnomalies(array $connectors): array { $items = []; foreach ($connectors as $connector) { $status = (string)($connector['derived_status'] ?? 'pending'); if ($status !== 'healthy') { $items[] = [ 'level' => $status === 'warning' ? 'warn' : ($status === 'pending' ? 'warn' : 'bad'), 'title' => ($connector['name'] ?? 'Connector') . ' needs review', 'text' => 'Frontend: ' . ($connector['status_frontend'] ?? 'unknown') . ' • Backend: ' . ($connector['status_backend'] ?? 'unknown') . ' • Ready score: ' . round(((float)($connector['ready_score'] ?? 0)) * 100) . '%', ]; } if (count($items) >= 8) break; } if (!$items) $items[] = ['level' => 'ok', 'title' => 'No major anomalies', 'text' => 'All loaded connectors are currently healthy.']; return $items; } function buildTimeline(): array { return [ 'Session opened → command shell loaded', 'JSON registry auto-picked from data folder', 'Connector health loaded from exported workbook JSON', 'Memory graph staged for project context', 'Workflow builder shell activated', 'CONN-LINK drawer waiting for live actions', ]; } $registry = loadConnectorRegistry($DATA_DIR); $connectors = $registry['connectors']; $summary = $registry['summary']; $recommendations = buildRecommendations($connectors); $anomalies = buildAnomalies($connectors); if (isset($_GET['api'])) { $api = (string)$_GET['api']; if ($api === 'json_sources') { $files = array_map(static fn($file) => [ 'name' => basename($file), 'modified_at' => date('c', filemtime($file)), 'size' => filesize($file), ], scanJsonFiles($DATA_DIR)); jsonResponse(['ok' => true, 'data_dir' => 'data/', 'sources' => $files, 'auto_pick' => $registry['file']]); } if ($api === 'connectors' || $api === 'health') { jsonResponse([ 'ok' => true, 'registry_file' => $registry['file'], 'generated_at' => $registry['generated_at'], 'summary' => [ 'connector_count' => count($connectors), 'healthy_count' => count(array_filter($connectors, static fn($c) => ($c['derived_status'] ?? '') === 'healthy')), 'warning_count' => count(array_filter($connectors, static fn($c) => ($c['derived_status'] ?? '') === 'warning')), 'pending_count' => count(array_filter($connectors, static fn($c) => ($c['derived_status'] ?? '') === 'pending')), ] + $summary, 'recommendations' => $recommendations, 'anomalies' => $anomalies, 'timeline' => buildTimeline(), 'connectors' => $connectors, ]); } if ($api === 'connector_test') { $carrierKey = (string)($_GET['carrier_key'] ?? ''); foreach ($connectors as $connector) { if (($connector['carrier_key'] ?? '') === $carrierKey) { jsonResponse([ 'ok' => true, 'carrier_key' => $carrierKey, 'name' => $connector['name'] ?? '', 'checks' => [ ['check' => 'config_file', 'ok' => !empty($connector['paths']['config_file'] ?? null)], ['check' => 'connector_file', 'ok' => !empty($connector['paths']['connector_file'] ?? null)], ['check' => 'test_file', 'ok' => !empty($connector['paths']['test_file'] ?? null)], ['check' => 'backend_handler', 'ok' => !empty($connector['scripts']['backend_handler'] ?? null)], ], 'status_frontend' => $connector['status_frontend'] ?? '', 'status_backend' => $connector['status_backend'] ?? '', 'ready_score' => $connector['ready_score'] ?? 0, 'note' => 'Structural validation only. Add real auth/read/write tests after secrets and transports are wired.', ]); } } jsonResponse(['ok' => false, 'error' => 'carrier_key not found'], 404); } if ($api === 'forecast') { jsonResponse([ 'ok' => true, 'forecast' => [ ['label' => 'Backend completion risk', 'value' => 'Medium', 'reason' => 'Most connectors are still planned or partially staged.'], ['label' => 'Best immediate gain', 'value' => 'Wire real connector health route', 'reason' => 'This enables KPIs, anomalies, and readiness cards.'], ['label' => 'Deployment advice', 'value' => 'Safe for prototype shell', 'reason' => 'Use read-only mode until auth and permissions are implemented.'], ], 'anomalies' => $anomalies, ]); } if ($api === 'memory_update') { $payload = json_decode(file_get_contents('php://input') ?: '[]', true); jsonResponse(['ok' => true, 'stored' => true, 'mode' => 'stub', 'received' => $payload, 'note' => 'Attach this route to JSON/SQLite memory persistence next.']); } if ($api === 'workflow_run') { $payload = json_decode(file_get_contents('php://input') ?: '[]', true); jsonResponse(['ok' => true, 'workflow' => $payload['workflow'] ?? 'unnamed', 'status' => 'preview', 'steps' => $payload['steps'] ?? [], 'note' => 'Route this endpoint into your action router when real execution is ready.']); } if ($api === 'chat') { $payload = json_decode(file_get_contents('php://input') ?: '[]', true); $prompt = trim((string)($payload['prompt'] ?? '')); $reply = $prompt === '' ? 'No prompt received.' : "SIMON received your prompt and routed it through the CONN-LINK shell. This backend is now live to the UI. Next step: attach provider-router execution for real multi-model output.\n\nPrompt: {$prompt}"; jsonResponse(['ok' => true, 'reply' => $reply, 'mode' => 'backend_connected', 'registry_file' => $registry['file'], 'connector_count' => count($connectors)]); } jsonResponse(['ok' => false, 'error' => 'Unknown api route'], 404); } $connectorsJson = json_encode($connectors, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $recommendationsJson = json_encode($recommendations, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $anomaliesJson = json_encode($anomalies, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $timelineJson = json_encode(buildTimeline(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover"/> <title>SIMON Intelligence • CONN-LINK Ready</title> <meta name="theme-color" content="#070b16"/> <meta name="description" content="SIMON Intelligence upgraded with predictive UI, memory graph, command palette, multi-AI comparison, workflows, and CONN-LINK integration readiness."/> <style> :root{--bg:#070b16;--bg2:#050913;--panel:rgba(255,255,255,.06);--panel2:rgba(255,255,255,.03);--edge:rgba(255,255,255,.14);--edge2:rgba(255,255,255,.08);--text:#eaf2ff;--muted:#98abd4;--acc:#6ae0ff;--acc2:#7b62ff;--ok:#44d18a;--warn:#ffcc4d;--bad:#ff6b6b;--r:18px;--shadow:0 16px 50px rgba(0,0,0,.35);--headerH:72px;--leftW:280px;--rightW:360px}*{box-sizing:border-box}html,body{height:100%}body{margin:0;color:var(--text);font:14px/1.4 Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,sans-serif;background:radial-gradient(1200px 700px at 10% 0%, rgba(123,98,255,.18), transparent 55%), radial-gradient(900px 600px at 100% 0%, rgba(106,224,255,.14), transparent 60%), linear-gradient(180deg,var(--bg2),var(--bg));overflow:hidden}button,input,textarea{font:inherit}.shell{display:grid;grid-template-rows:var(--headerH) 1fr;height:100%}.header{position:relative;display:flex;align-items:center;justify-content:space-between;padding:12px 18px;border-bottom:1px solid var(--edge);background:linear-gradient(180deg,rgba(7,11,22,.96),rgba(7,11,22,.84));backdrop-filter:blur(12px) saturate(130%);overflow:hidden}.header:before{content:"";position:absolute;inset:-20% -10%;background:radial-gradient(circle at 20% 50%, rgba(106,224,255,.14), transparent 25%), radial-gradient(circle at 80% 50%, rgba(123,98,255,.14), transparent 25%);pointer-events:none;animation:drift 12s linear infinite alternate}@keyframes drift{from{transform:translateX(-20px)}to{transform:translateX(20px)}}.brand{display:flex;align-items:center;gap:14px;position:relative;z-index:1}.orb{width:40px;height:40px;border-radius:50%;background:radial-gradient(circle at 30% 30%, #fff, rgba(255,255,255,.24) 15%, rgba(106,224,255,.32) 25%, rgba(123,98,255,.26) 45%, rgba(12,18,34,.95) 75%);box-shadow:0 0 30px rgba(106,224,255,.25),0 0 60px rgba(123,98,255,.18), inset 0 0 28px rgba(255,255,255,.22);position:relative}.orb:after{content:"";position:absolute;inset:-8px;border-radius:50%;border:1px solid rgba(106,224,255,.22);box-shadow:0 0 22px rgba(106,224,255,.22)}.title{font-weight:800;letter-spacing:.08em}.subtitle{font-size:12px;color:var(--muted)}.top-tools{display:flex;align-items:center;gap:10px;position:relative;z-index:1}.pill,.btn,.iconbtn,.tab{border:1px solid var(--edge);background:linear-gradient(180deg,var(--panel),var(--panel2));color:var(--text);border-radius:12px}.pill{padding:8px 12px}.btn{padding:10px 14px;cursor:pointer}.iconbtn{width:40px;height:40px;display:grid;place-items:center;cursor:pointer}.main{display:grid;grid-template-columns:var(--leftW) 1fr var(--rightW);min-height:0}.left,.right,.center{min-height:0}.left,.right{border-right:1px solid var(--edge2);background:rgba(7,11,22,.5);backdrop-filter:blur(10px)}.right{border-right:none;border-left:1px solid var(--edge2)}.scroll{height:100%;overflow:auto;padding:14px}.section{margin-bottom:14px}.card{background:linear-gradient(180deg,rgba(255,255,255,.07),rgba(255,255,255,.035));border:1px solid var(--edge);border-radius:var(--r);box-shadow:var(--shadow)}.card.pad{padding:14px}.muted{color:var(--muted)}.tiny{font-size:12px}.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}.stack{display:flex;flex-direction:column;gap:10px}.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap}.between{display:flex;align-items:center;justify-content:space-between;gap:10px}.kpi{padding:12px;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid var(--edge2)}.kpi b{display:block;font-size:20px}.status-dot{width:9px;height:9px;border-radius:50%;display:inline-block}.ok{background:var(--ok)}.warn{background:var(--warn)}.bad{background:var(--bad)}.nav{display:flex;flex-direction:column;gap:8px}.nav .tab{padding:10px 12px;text-align:left;cursor:pointer}.nav .tab.active{border-color:rgba(106,224,255,.35);box-shadow:inset 0 0 0 1px rgba(106,224,255,.18)}.center-wrap{display:grid;grid-template-rows:auto auto 1fr auto;gap:12px;padding:12px;min-height:0}.banner{padding:12px 14px;border:1px solid rgba(106,224,255,.18);border-radius:16px;background:linear-gradient(180deg,rgba(106,224,255,.08),rgba(123,98,255,.05))}.chips{display:flex;gap:8px;flex-wrap:wrap}.chip{padding:7px 10px;border-radius:999px;border:1px solid var(--edge);background:rgba(255,255,255,.04);font-size:12px}.energy{height:10px;border-radius:999px;overflow:hidden;border:1px solid var(--edge);background:rgba(255,255,255,.05)}.energy>span{display:block;height:100%;background:linear-gradient(90deg,var(--acc),var(--acc2))}.workbench{display:grid;grid-template-columns:1fr 320px;gap:12px;min-height:0}.chat{display:grid;grid-template-rows:auto 1fr auto;min-height:0}.chat-log{padding:14px;height:100%;overflow:auto}.msg{display:flex;gap:10px;margin:10px 0}.msg .avatar{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;border:1px solid var(--edge);background:rgba(255,255,255,.07)}.msg .bubble{flex:1;padding:12px 14px;border-radius:14px;border:1px solid var(--edge);background:rgba(255,255,255,.05);white-space:pre-wrap}.composer{padding:12px;border-top:1px solid var(--edge2)}.composer textarea{width:100%;min-height:92px;resize:vertical;padding:12px 14px;border-radius:14px;border:1px solid var(--edge);background:rgba(255,255,255,.06);color:var(--text)}.sidepanel{padding:12px;display:flex;flex-direction:column;gap:12px;min-height:0;overflow:auto}.suggest-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.timeline{display:flex;flex-direction:column;gap:8px}.time-item{padding:10px;border-left:3px solid rgba(106,224,255,.55);background:rgba(255,255,255,.04);border-radius:0 12px 12px 0}.graph{position:relative;height:190px;border-radius:16px;border:1px solid var(--edge);background:radial-gradient(circle at 50% 50%, rgba(106,224,255,.07), transparent 55%), rgba(255,255,255,.02);overflow:hidden}.graph .node{position:absolute;width:14px;height:14px;border-radius:50%;background:linear-gradient(180deg,var(--acc),#fff);box-shadow:0 0 20px rgba(106,224,255,.35)}.graph svg{position:absolute;inset:0;width:100%;height:100%}.compare-col,.conn-list{display:flex;flex-direction:column;gap:8px}.compare-box,.conn{padding:10px;border-radius:14px;border:1px solid var(--edge);background:rgba(255,255,255,.04)}.conn .name{font-weight:700}.conn .meta{font-size:12px;color:var(--muted)}.workflow{display:flex;gap:10px;overflow:auto;padding-bottom:4px}.wf{min-width:180px;padding:12px;border-radius:14px;border:1px solid var(--edge);background:rgba(255,255,255,.04)}.palette{position:fixed;inset:0;background:rgba(0,0,0,.42);display:none;align-items:flex-start;justify-content:center;padding-top:9vh;z-index:50}.palette.open{display:flex}.palette-box{width:min(760px,92vw);padding:14px}.palette-box input{width:100%;padding:14px 16px;border-radius:16px;border:1px solid var(--edge);background:rgba(7,11,22,.94);color:var(--text);margin-bottom:10px}.palette-results{max-height:52vh;overflow:auto}.palette-item{padding:12px 14px;border:1px solid var(--edge2);border-radius:14px;background:rgba(255,255,255,.03);margin-bottom:8px;cursor:pointer}.drawer{position:fixed;top:var(--headerH);right:-520px;width:min(520px,94vw);bottom:0;z-index:45;background:linear-gradient(180deg,rgba(8,12,24,.98),rgba(8,12,24,.96));border-left:1px solid var(--edge);transition:right .28s ease}.drawer.open{right:0}.drawer .head{padding:14px 16px;border-bottom:1px solid var(--edge)}.drawer .body{padding:16px;height:calc(100% - 68px);overflow:auto}.table{width:100%;border-collapse:collapse}.table th,.table td{padding:8px;border-bottom:1px solid var(--edge2);text-align:left;vertical-align:top}@media(max-width:1200px){.main{grid-template-columns:250px 1fr 320px}.workbench{grid-template-columns:1fr}}@media(max-width:980px){.main{grid-template-columns:1fr}.left,.right{display:none}.center-wrap{padding:10px}.drawer{top:0}} </style> </head> <body> <div class="shell"><header class="header"><div class="brand"><div class="orb"></div><div><div class="title">SIMON INTELLIGENCE</div><div class="subtitle">Predictive AI shell • CONN-LINK ready • operator-grade interface</div></div></div><div class="top-tools"><button class="pill" id="cmdKBtn">⌘K Command Palette</button><div class="pill">Mode: <b id="modeLabel">Operator</b></div><div class="pill">Voice: <b id="voiceLabel">Ready</b></div><button class="iconbtn" id="themeBtn">◐</button><button class="btn" id="openConnLinkBtn">Open CONN-LINK</button></div></header> <div class="main"><aside class="left"><div class="scroll"><div class="section card pad"><h3>SIMON Navigation</h3><div class="nav"><button class="tab active">Command Center</button><button class="tab">Chat + Voice</button><button class="tab">Memory Graph</button><button class="tab">Timeline</button><button class="tab">Workflows</button><button class="tab">Model Compare</button><button class="tab">Forecasts</button><button class="tab">Plugins</button><button class="tab">CONN-LINK Health</button></div></div><div class="section card pad"><div class="between"><h4>Readiness Score</h4><span class="chip" id="readinessPct">0%</span></div><div class="energy"><span id="readinessBar" style="width:0%"></span></div><p class="muted tiny">This shell auto-loads connector JSON from the data folder and exposes backend endpoints for health, chat, forecast, workflows, and memory updates.</p></div><div class="section card pad"><h4>JSON Auto-Pickup</h4><div class="stack tiny" id="sourceList"></div></div><div class="section card pad"><h4>Connector Targets</h4><div class="conn-list" id="quickConnectors"></div></div></div></aside> <main class="center"><div class="center-wrap"><div class="banner card"><div class="between"><div><div style="font-weight:800">SIMON vNext is now staged for CONN-LINK orchestration</div><div class="muted tiny">The UI is connected to a backend loader and registry health endpoints. Drop updated JSON files into the data folder and the shell will auto-pick them on refresh.</div></div><div class="chips"><span class="chip">Backend connected</span><span class="chip">JSON auto-pickup</span><span class="chip">Registry ready</span></div></div></div><div class="grid2"><div class="card pad"><div class="between"><h4>System KPIs</h4><span class="tiny muted">live backend metrics</span></div><div class="grid2"><div class="kpi"><span class="tiny muted">Connectors</span><b id="kpiConnectors">0</b></div><div class="kpi"><span class="tiny muted">Healthy</span><b id="kpiHealthy">0</b></div><div class="kpi"><span class="tiny muted">Warnings</span><b id="kpiWarnings">0</b></div><div class="kpi"><span class="tiny muted">Anomalies</span><b id="kpiAnomalies">0</b></div></div></div><div class="card pad"><div class="between"><h4>Next Best Moves</h4><span class="tiny muted">recommendation engine</span></div><div class="stack tiny" id="recommendations"></div></div></div><div class="workbench"><section class="chat card"><div class="between" style="padding:12px 14px;border-bottom:1px solid var(--edge2)"><div><strong>SIMON Chat + Streaming Workspace</strong><div class="tiny muted">Chat now posts to the backend route in this file.</div></div><div class="row"><button class="btn" id="streamBtn">Simulate Stream</button><button class="btn" id="voiceBtn">Voice Persona</button><button class="btn" id="compareBtn">Compare Models</button></div></div><div class="chat-log" id="chatLog"></div><div class="composer"><div class="suggest-grid" id="smartSuggestions"></div><div style="height:10px"></div><textarea id="promptInput" placeholder="Ask SIMON anything, route to CONN-LINK, inspect connectors, build workflows, summarize logs, compare providers..."></textarea><div class="between" style="margin-top:10px"><div class="chips"><span class="chip">Backend live</span><span class="chip">JSON registry</span><span class="chip">Auto-pickup</span></div><div class="row"><button class="btn" id="sendBtn">Send</button><button class="btn" id="clearBtn">Clear</button></div></div></div></section><aside class="sidepanel card"><section><div class="between"><h4>Session Timeline</h4><span class="tiny muted">resume continuity</span></div><div class="timeline" id="timeline"></div></section><section><div class="between"><h4>Model Compare</h4><span class="tiny muted">side-by-side</span></div><div class="compare-col" id="compareCols"></div></section></aside></div></div></main> <aside class="right"><div class="scroll"><div class="section card pad"><div class="between"><h3>Memory Graph</h3><span class="chip">Context nodes</span></div><div class="graph"><svg viewBox="0 0 100 100" preserveAspectRatio="none"><line x1="22" y1="24" x2="48" y2="44" stroke="rgba(106,224,255,.55)" stroke-width="1.4"/><line x1="48" y1="44" x2="76" y2="28" stroke="rgba(106,224,255,.55)" stroke-width="1.4"/><line x1="48" y1="44" x2="68" y2="74" stroke="rgba(123,98,255,.6)" stroke-width="1.4"/><line x1="22" y1="24" x2="30" y2="72" stroke="rgba(123,98,255,.4)" stroke-width="1.1"/></svg><div class="node" style="left:18%;top:18%"></div><div class="node" style="left:43%;top:38%"></div><div class="node" style="left:70%;top:24%"></div><div class="node" style="left:63%;top:66%"></div><div class="node" style="left:25%;top:64%"></div></div><p class="tiny muted">Ready for 5W1H records, connector entities, workflow nodes, and contradiction tracking.</p></div><div class="section card pad"><div class="between"><h4>Workflow Builder</h4><span class="chip">staged</span></div><div class="workflow" id="workflowLane"></div></div><div class="section card pad"><div class="between"><h4>Forecast + Anomalies</h4><span class="chip">backend-fed</span></div><div class="stack" id="anomalyList"></div></div><div class="section card pad"><div class="between"><h4>Plugin Slots</h4><span class="chip">extensible</span></div><table class="table tiny"><thead><tr><th>Plugin</th><th>Status</th><th>Purpose</th></tr></thead><tbody id="pluginTable"></tbody></table></div></div></aside></div></div> <div class="palette" id="palette"><div class="palette-box card"><input id="paletteInput" type="text" placeholder="Type a command… open conn-link, compare models, show anomalies, export memory, new workflow"/><div class="palette-results" id="paletteResults"></div></div></div> <aside class="drawer" id="connDrawer"><div class="head between"><div><strong>CONN-LINK Registry Drawer</strong><div class="tiny muted">Live connector shell + auto-picked folder JSON</div></div><button class="btn" id="closeConnDrawer">Close</button></div><div class="body"><div class="card pad section"><div class="between"><h4>Connector Health Matrix</h4><button class="btn" id="refreshConnectorsBtn">Refresh</button></div><div class="conn-list" id="drawerConnectors"></div></div><div class="card pad section"><h4>Hook Targets</h4><table class="table tiny"><tbody><tr><th>?api=chat</th><td>Primary chat route in this file</td></tr><tr><th>?api=health</th><td>Connector health and KPI route</td></tr><tr><th>?api=connector_test&carrier_key=...</th><td>Structural connector validation</td></tr><tr><th>?api=forecast</th><td>Anomaly + prediction route</td></tr><tr><th>?api=workflow_run</th><td>Workflow preview execution</td></tr><tr><th>?api=memory_update</th><td>Memory 5W1H capture stub</td></tr><tr><th>?api=json_sources</th><td>Lists auto-picked JSON sources</td></tr></tbody></table></div><div class="card pad section"><h4>Preparation Checklist</h4><div class="stack tiny"><label><input type="checkbox" checked/> data folder auto-pickup</label><label><input type="checkbox" checked/> connector registry JSON</label><label><input type="checkbox" checked/> backend API routes</label><label><input type="checkbox" checked/> UI connected to fetch calls</label><label><input type="checkbox"/> real auth/read/write execution</label><label><input type="checkbox"/> persistent DB / roles / permissions</label></div></div></div></aside> <script> (()=>{const initialConnectors=<?php echo $connectorsJson ?: '[]'; ?>;const initialRecommendations=<?php echo $recommendationsJson ?: '[]'; ?>;const initialAnomalies=<?php echo $anomaliesJson ?: '[]'; ?>;const initialTimeline=<?php echo $timelineJson ?: '[]'; ?>;const suggestions=['Summarize latest connector failures','Build workflow: upload → scan → summarize','Show memory graph for WEB360 project','Forecast issues from current connector states','Export 5W1H JSON','Prepare deployment checklist','Detect contradictions in system registry','List newest data folder JSON files'];const workflows=['Input Capture','Intent Detect','Route to Connector','Collect Results','Score + Forecast','Store Memory'];const plugins=[['Memory Engine','Stubbed route','entity graph, recall, contradictions'],['Forecast Engine','Backend live','anomalies, trends, next-move scoring'],['Workflow Engine','Preview route','route chains + operator macros'],['Analytics Engine','Ready for wiring','GA4, console, traffic intelligence'],['Security Engine','Ready for wiring','auth, scopes, diagnostics, risk signals']];const compareSamples=[['OpenAI','Use when chat/provider routing is wired.'],['Anthropic','Use when compare mode is added to the router.'],['Gemini','Use when multimodal route is added to the registry.']];const paletteCommands=['Open CONN-LINK drawer','Show anomalies','Export memory JSON','New workflow','Resume last session','Switch theme','Run connector refresh','List data folder JSON'];const $=(id)=>document.getElementById(id);const chatLog=$('chatLog');const promptInput=$('promptInput');const palette=$('palette');const connDrawer=$('connDrawer');function addMsg(role,text){const wrap=document.createElement('div');wrap.className=`msg ${role}`;wrap.innerHTML=`<div class="avatar">${role==='assistant'?'⚡':'🗣️'}</div><div class="bubble"></div>`;wrap.querySelector('.bubble').textContent=text;chatLog.appendChild(wrap);chatLog.scrollTop=chatLog.scrollHeight}function badge(status){if(status==='healthy')return '<span class="status-dot ok"></span> healthy';if(status==='warning'||status==='degraded')return '<span class="status-dot warn"></span> degraded';if(status==='pending')return '<span class="status-dot warn"></span> pending';return '<span class="status-dot bad"></span> issue'}function renderConnectors(connectors){$('quickConnectors').innerHTML=connectors.slice(0,18).map(c=>`<div class="conn"><div class="between"><div class="name">${c.name}</div><div class="tiny">${badge(c.derived_status)}</div></div><div class="meta">${c.type} • ${c.api_type||''} • ${c.auth_method||''}</div><div class="tiny" style="margin-top:6px">${c.notes||c.subcategory||''}</div></div>`).join('');$('drawerConnectors').innerHTML=connectors.map(c=>`<div class="conn"><div class="between"><div class="name">${c.name}</div><div class="tiny">${badge(c.derived_status)}</div></div><div class="meta">${c.carrier_key} • ${c.status_frontend} / ${c.status_backend}</div><div class="tiny" style="margin-top:6px">${(c.capabilities||[]).join(', ')}</div></div>`).join('')}function renderRecommendations(items){$('recommendations').innerHTML=items.map(r=>`<div class="kpi tiny">${r}</div>`).join('')}function renderAnomalies(items){$('anomalyList').innerHTML=items.map(a=>`<div class="kpi"><div class="between"><strong>${a.title}</strong><span class="tiny">${(a.level||'').toUpperCase()}</span></div><div class="tiny muted" style="margin-top:6px">${a.text}</div></div>`).join('');$('kpiAnomalies').textContent=String(items.length)}function renderTimeline(items){$('timeline').innerHTML=items.map(t=>`<div class="time-item tiny">${t}</div>`).join('')}function renderStaticBlocks(){$('smartSuggestions').innerHTML=suggestions.map(s=>`<button class="btn tiny smart-btn">${s}</button>`).join('');$('workflowLane').innerHTML=workflows.map((w,i)=>`<div class="wf"><div class="tiny muted">Step ${i+1}</div><strong>${w}</strong></div>`).join('');$('pluginTable').innerHTML=plugins.map(p=>`<tr><td>${p[0]}</td><td>${p[1]}</td><td>${p[2]}</td></tr>`).join('');$('compareCols').innerHTML=compareSamples.map(c=>`<div class="compare-box"><div class="between"><strong>${c[0]}</strong><span class="chip tiny">ready</span></div><div class="tiny muted" style="margin-top:6px">${c[1]}</div></div>`).join('');$('paletteResults').innerHTML=paletteCommands.map(c=>`<div class="palette-item">${c}</div>`).join('')}async function loadHealth(){const res=await fetch('?api=health',{cache:'no-store'});const data=await res.json();if(!data.ok)return;$('kpiConnectors').textContent=String(data.summary.connector_count||0);$('kpiHealthy').textContent=String(data.summary.healthy_count||0);$('kpiWarnings').textContent=String((data.summary.warning_count||0)+(data.summary.pending_count||0));const readiness=data.summary.connector_count?Math.round(((data.summary.healthy_count||0)/data.summary.connector_count)*100):0;$('readinessPct').textContent=`${readiness}%`;$('readinessBar').style.width=`${readiness}%`;renderConnectors(data.connectors||[]);renderRecommendations(data.recommendations||[]);renderAnomalies(data.anomalies||[]);renderTimeline(data.timeline||[])}async function loadSources(){const res=await fetch('?api=json_sources',{cache:'no-store'});const data=await res.json();if(!data.ok)return;$('sourceList').innerHTML=data.sources.slice(0,8).map(s=>`<div class="tiny"><strong>${s.name}</strong><br><span class="muted">${s.modified_at} • ${s.size} bytes</span></div>`).join('')}async function sendPrompt(){const value=promptInput.value.trim();if(!value)return;addMsg('user',value);promptInput.value='';const bubble=document.createElement('div');bubble.className='msg assistant';bubble.innerHTML='<div class="avatar">⚡</div><div class="bubble">Routing through backend...</div>';chatLog.appendChild(bubble);chatLog.scrollTop=chatLog.scrollHeight;const res=await fetch('?api=chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:value})});const data=await res.json();bubble.querySelector('.bubble').textContent=data.reply||'No reply received.';chatLog.scrollTop=chatLog.scrollHeight}function bootstrapChat(){addMsg('assistant','SIMON shell upgraded. The front-end is now connected to a backend registry loader and JSON auto-pickup in the data folder.');addMsg('assistant','Drop updated JSON exports into /data and click refresh. The shell will auto-pick the newest matching registry files.')}$('sendBtn').addEventListener('click',sendPrompt);$('promptInput').addEventListener('keydown',(e)=>{if((e.metaKey||e.ctrlKey)&&e.key==='Enter')sendPrompt()});$('clearBtn').addEventListener('click',()=>{chatLog.innerHTML='';bootstrapChat()});$('streamBtn').addEventListener('click',()=>addMsg('assistant','Streaming simulation can now be replaced with your real provider router.'));$('compareBtn').addEventListener('click',()=>addMsg('assistant','Compare mode shell is ready. Add a compare endpoint next.'));$('voiceBtn').addEventListener('click',()=>{const label=$('voiceLabel');label.textContent=label.textContent==='Ready'?'Coach Persona':label.textContent==='Coach Persona'?'Direct Persona':'Ready';addMsg('assistant','Voice persona switched. Attach this to your voice profile router next.')});function toggleDrawer(open){connDrawer.classList.toggle('open',open)}$('openConnLinkBtn').addEventListener('click',()=>toggleDrawer(true));$('closeConnDrawer').addEventListener('click',()=>toggleDrawer(false));$('refreshConnectorsBtn').addEventListener('click',async()=>{await loadHealth();await loadSources();addMsg('assistant','Connector refresh complete. Registry and source list reloaded from the data folder.')});function togglePalette(state){palette.classList.toggle('open',state);if(state)$('paletteInput').focus();else $('paletteInput').blur()}$('cmdKBtn').addEventListener('click',()=>togglePalette(true));palette.addEventListener('click',(e)=>{if(e.target===palette)togglePalette(false)});window.addEventListener('keydown',(e)=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==='k'){e.preventDefault();togglePalette(!palette.classList.contains('open'))}if(e.key==='Escape'){togglePalette(false);toggleDrawer(false)}});$('paletteResults').addEventListener('click',async(e)=>{const item=e.target.closest('.palette-item');if(!item)return;const text=item.textContent;if(text.includes('List data folder JSON')){await loadSources();addMsg('assistant','Data folder source list refreshed.')}else if(text.includes('Show anomalies')){addMsg('assistant','Anomaly panel is backend-fed from ?api=forecast and ?api=health.')}else{addMsg('assistant',`Command selected: ${text}. Attach this to your command router next.`)}togglePalette(false)});document.addEventListener('click',(e)=>{const btn=e.target.closest('.smart-btn');if(!btn)return;$('promptInput').value=btn.textContent;$('promptInput').focus()});$('themeBtn').addEventListener('click',()=>{const root=document.documentElement;const dark=getComputedStyle(root).getPropertyValue('--bg').trim()==='#070b16';if(dark){root.style.setProperty('--bg','#f4f7ff');root.style.setProperty('--bg2','#e9f0ff');root.style.setProperty('--panel','rgba(0,0,0,.04)');root.style.setProperty('--panel2','rgba(0,0,0,.02)');root.style.setProperty('--edge','rgba(0,0,0,.12)');root.style.setProperty('--edge2','rgba(0,0,0,.06)');root.style.setProperty('--text','#0a1530');root.style.setProperty('--muted','#5d6f92');document.body.style.background='linear-gradient(180deg,#eef4ff,#dde8ff)'}else{location.reload()}});renderStaticBlocks();renderConnectors(initialConnectors);renderRecommendations(initialRecommendations);renderAnomalies(initialAnomalies);renderTimeline(initialTimeline);bootstrapChat();loadHealth();loadSources();})(); </script> </body> </html>
Save file
Quick jump
open a path
Open