|
8 | 8 | <html lang="en"> |
9 | 9 | <head> |
10 | 10 | <meta charset="UTF-8"> |
11 | | - <title>PyOB // OBSERVER</title> |
| 11 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 12 | + <title>PyOB // ARCHITECT HUD</title> |
| 13 | + <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@300;600&display=swap" rel="stylesheet"> |
12 | 14 | <style> |
13 | | - body { background: #050505; color: #00FF41; font-family: 'Menlo', monospace; margin: 0; padding: 20px; overflow-x: hidden; } |
14 | | - .glow { text-shadow: 0 0 10px #00FF41, 0 0 20px #00FF41; } |
15 | | - .border { border: 1px solid #00FF41; box-shadow: 0 0 15px rgba(0, 255, 65, 0.2); padding: 20px; margin-bottom: 20px; } |
16 | | - h1 { font-size: 2em; border-bottom: 2px solid #00FF41; padding-bottom: 10px; } |
17 | | - .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } |
18 | | - .card { background: rgba(0, 255, 65, 0.05); } |
19 | | - .label { color: #008F11; font-weight: bold; margin-bottom: 5px; } |
20 | | - .data { font-size: 0.9em; white-space: pre-wrap; height: 300px; overflow-y: auto; border: 1px solid #004411; padding: 10px; background: #000; } |
21 | | - .stat-bar { display: flex; justify-content: space-between; font-size: 1.2em; margin-bottom: 20px; } |
22 | | - .queue-item { background: #00FF41; color: #000; padding: 2px 5px; margin: 2px; display: inline-block; font-size: 0.8em; } |
23 | | - #iteration { font-size: 1.5em; color: #fff; } |
24 | | - /* New styles for patch review */ |
25 | | - .patch-card { background: rgba(0, 255, 65, 0.1); border: 1px solid #008F11; padding: 10px; margin-bottom: 10px; } |
26 | | - .patch-content { font-family: 'Courier New', monospace; font-size: 0.8em; background: #000; border: 1px solid #004411; padding: 5px; margin-top: 5px; max-height: 200px; overflow-y: auto; } |
27 | | - .patch-actions button { padding: 5px 10px; margin-right: 5px; cursor: pointer; border: none; } |
28 | | - .approve-btn { background: #00FF41; color: #000; } |
29 | | - .reject-btn { background: #FF0000; color: #fff; } |
| 15 | + :root { --bg: #0a0a0c; --card: #141417; --accent: #00ffa3; --text: #e0e0e6; --dim: #88888e; --err: #ff4d4d; } |
| 16 | + * { box-sizing: border-box; } |
| 17 | + body { background: var(--bg); color: var(--text); font-family: 'Inter', sans-serif; margin: 0; padding: 15px; line-height: 1.5; } |
| 18 | + .hud-container { max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } |
| 19 | + |
| 20 | + /* Typography & Glow */ |
| 21 | + h1 { grid-column: span 2; font-family: 'JetBrains Mono'; font-size: 1.2rem; letter-spacing: 2px; color: var(--accent); text-transform: uppercase; margin: 10px 0; display: flex; justify-content: space-between; } |
| 22 | + .glow { text-shadow: 0 0 15px var(--accent); } |
| 23 | +
|
| 24 | + /* Component Cards */ |
| 25 | + .card { background: var(--card); border: 1px solid #2a2a30; border-radius: 8px; padding: 20px; overflow: hidden; position: relative; } |
| 26 | + .card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: linear-gradient(90deg, transparent, var(--accent), transparent); opacity: 0.3; } |
| 27 | + .label { font-size: 0.7rem; font-weight: 600; color: var(--dim); text-transform: uppercase; margin-bottom: 12px; letter-spacing: 1px; display: flex; align-items: center; gap: 8px; } |
| 28 | + .label::before { content: ''; width: 6px; height: 6px; background: var(--accent); border-radius: 50%; box-shadow: 0 0 8px var(--accent); } |
| 29 | +
|
| 30 | + /* Data Displays */ |
| 31 | + .data-box { font-family: 'JetBrains Mono', monospace; font-size: 0.85rem; height: 250px; overflow-y: auto; background: #00000044; border-radius: 4px; padding: 12px; color: #ced4e0; scrollbar-width: thin; } |
| 32 | + .stat-grid { grid-column: span 2; display: flex; gap: 40px; background: var(--card); padding: 15px 25px; border-radius: 8px; border: 1px solid #2a2a30; } |
| 33 | + .stat-item { display: flex; flex-direction: column; } |
| 34 | + .stat-val { font-size: 1.5rem; font-weight: 700; font-family: 'JetBrains Mono'; color: #fff; } |
| 35 | + .stat-lbl { font-size: 0.6rem; color: var(--dim); } |
| 36 | +
|
| 37 | + /* Mobile Specifics */ |
| 38 | + @media (max-width: 768px) { |
| 39 | + .hud-container { grid-template-columns: 1fr; } |
| 40 | + h1, .stat-grid { grid-column: 1; } |
| 41 | + .stat-grid { flex-wrap: wrap; gap: 20px; } |
| 42 | + } |
| 43 | +
|
| 44 | + .status-pill { padding: 4px 12px; border-radius: 20px; font-size: 0.7rem; font-weight: 800; background: #222; } |
| 45 | + .evolving { color: var(--accent); border: 1px solid var(--accent); box-shadow: 0 0 10px #00ffa344; } |
| 46 | + |
| 47 | + input { background: #000; border: 1px solid #2a2a30; color: var(--accent); padding: 10px; border-radius: 4px; width: 100%; font-family: 'JetBrains Mono'; margin-bottom: 10px; } |
| 48 | + button { width: 100%; padding: 12px; background: var(--accent); color: #000; border: none; border-radius: 4px; font-weight: 700; cursor: pointer; transition: 0.2s; } |
| 49 | + button:hover { filter: brightness(1.2); } |
30 | 50 | </style> |
31 | 51 | </head> |
32 | 52 | <body> |
33 | | - <h1 class="glow">PYOB_OS // OBSERVER_DASHBOARD</h1> |
34 | | - <div class="stat-bar border card"> |
35 | | - <div>ITERATION: <span id="iteration" class="glow">--</span></div> |
36 | | - <div>LEDGER: <span id="ledger">--</span> symbols</div> |
37 | | - <div>STATUS: <span id="status" style="color: #fff">SCANNING...</span></div> |
38 | | - </div> |
39 | | - <div class="border card"><div class="label">SYMBOLIC CASCADE QUEUE:</div><div id="queue">--</div></div> |
40 | | - <div class="grid"> |
41 | | - <div class="border card"><div class="label">LIVE MEMORY (MEMORY.md):</div><div id="memory" class="data">--</div></div> |
42 | | - <div class="border card"><div class="label">RECENT HISTORY (HISTORY.md):</div><div id="history" class="data">--</div></div> |
43 | | - </div> |
44 | | - <div class="border card"><div class="label">LATEST ARCHITECTURAL ANALYSIS:</div><div id="analysis" class="data">--</div></div> |
45 | | - <!-- New section for Pending Architectural Patches --> |
46 | | - <div class="border card"> |
47 | | - <div class="label">PENDING ARCHITECTURAL PATCHES:</div> |
48 | | - <div id="pendingPatches" class="data" style="height: auto; min-height: 150px;"> |
49 | | - <!-- Patches will be loaded here --> |
50 | | - No pending patches. |
| 53 | + <h1> |
| 54 | + <span>PyOB // Evolution Engine</span> |
| 55 | + <span id="status-pill" class="status-pill">READY</span> |
| 56 | + </h1> |
| 57 | +
|
| 58 | + <div class="hud-container"> |
| 59 | + <div class="stat-grid"> |
| 60 | + <div class="stat-item"><span class="stat-lbl">Iteration</span><span id="iteration" class="stat-val">--</span></div> |
| 61 | + <div class="stat-item"><span class="stat-lbl">Symbolic Ledger</span><span id="ledger" class="stat-val">--</span></div> |
| 62 | + <div class="stat-item"><span class="stat-lbl">Pending Cascades</span><span id="queue-count" class="stat-val">--</span></div> |
| 63 | + </div> |
| 64 | +
|
| 65 | + <div class="card"> |
| 66 | + <div class="label">Logic Memory (MEMORY.md)</div> |
| 67 | + <div id="memory" class="data-box">Initializing brain...</div> |
| 68 | + </div> |
| 69 | +
|
| 70 | + <div class="card"> |
| 71 | + <div class="label">System Logs (HISTORY.md)</div> |
| 72 | + <div id="history" class="data-box">No history yet.</div> |
| 73 | + </div> |
| 74 | +
|
| 75 | + <div class="card" style="grid-column: span 2;"> |
| 76 | + <div class="label">Architectural Analysis</div> |
| 77 | + <div id="analysis" class="data-box" style="height: 350px;">Scanning structure...</div> |
| 78 | + </div> |
| 79 | +
|
| 80 | + <div class="card"> |
| 81 | + <div class="label">Manual Override</div> |
| 82 | + <input type="text" id="manualTargetFile" placeholder="src/pyob/target.py"> |
| 83 | + <button onclick="setManualTarget()">FORCE TARGET</button> |
| 84 | + </div> |
| 85 | +
|
| 86 | + <div class="card"> |
| 87 | + <div class="label">Queue Status</div> |
| 88 | + <div id="queue" class="data-box" style="height: 100px;">IDLE</div> |
51 | 89 | </div> |
52 | 90 | </div> |
53 | | - <div class="border card"> |
54 | | - <div class="label">MANUAL TARGET OVERRIDE:</div> |
55 | | - <input type="text" id="manualTargetFile" placeholder="e.g., src/pyob/new_feature.py" style="width: calc(100% - 120px); padding: 8px; margin-right: 10px; background: #000; border: 1px solid #00FF41; color: #00FF41;"> |
56 | | - <button onclick="setManualTarget()" style="padding: 8px 15px; background: #00FF41; color: #000; border: none; cursor: pointer;">Set Next Target</button> |
57 | | - <div id="targetMessage" style="margin-top: 10px; font-size: 0.9em;"></div> |
58 | | - </div> |
| 91 | +
|
59 | 92 | <script> |
60 | 93 | async function updateStats() { |
61 | 94 | try { |
62 | 95 | const response = await fetch('/api/status'); |
63 | 96 | const data = await response.json(); |
64 | | - document.getElementById('iteration').innerText = data.iteration; |
65 | | - document.getElementById('ledger').innerText = data.ledger_stats.definitions; |
66 | | - document.getElementById('memory').innerText = data.memory || "Initializing brain..."; |
67 | | - document.getElementById('history').innerText = data.history || "No history recorded yet."; |
68 | | - document.getElementById('analysis').innerText = data.analysis || "Parsing directory structure..."; |
69 | | - const queueDiv = document.getElementById('queue'); |
70 | | - queueDiv.innerHTML = data.cascade_queue.length > 0 ? data.cascade_queue.map(f => `<span class='queue-item'>${f}</span>`).join('') : "IDLE // NO PENDING CASCADES"; |
71 | | - document.getElementById('status').innerText = data.cascade_queue.length > 0 ? "EVOLVING" : "READY"; |
| 97 | + |
| 98 | + document.getElementById('iteration').innerText = data.iteration || "0"; |
| 99 | + document.getElementById('ledger').innerText = (data.ledger_stats?.definitions || 0) + " SYM"; |
| 100 | + document.getElementById('queue-count').innerText = data.cascade_queue?.length || "0"; |
| 101 | + |
| 102 | + const pill = document.getElementById('status-pill'); |
| 103 | + const isEvolving = data.cascade_queue?.length > 0 || data.patches_count > 0; |
| 104 | + pill.innerText = isEvolving ? "EVOLVING" : "STABLE"; |
| 105 | + pill.className = isEvolving ? "status-pill evolving" : "status-pill"; |
72 | 106 |
|
73 | | - // Fetch and render pending patches |
74 | | - const patchesResponse = await fetch('/api/pending_patches'); |
75 | | - const patchesData = await patchesResponse.json(); |
76 | | - renderPatches(patchesData.patches); |
77 | | -
|
78 | | - } catch (e) { |
79 | | - console.error("Error updating stats:", e); |
80 | | - document.getElementById('status').innerText = "OFFLINE"; |
81 | | - } |
| 107 | + document.getElementById('memory').innerText = data.memory || "Brain empty."; |
| 108 | + document.getElementById('history').innerText = data.history || "No logs."; |
| 109 | + document.getElementById('analysis').innerText = data.analysis || "Parsing..."; |
| 110 | + |
| 111 | + const queueDiv = document.getElementById('queue'); |
| 112 | + queueDiv.innerText = data.cascade_queue?.length > 0 ? data.cascade_queue.join('\\n') : "EMPTY"; |
| 113 | + } catch (e) { document.getElementById('status-pill').innerText = "OFFLINE"; } |
82 | 114 | } |
83 | 115 |
|
84 | 116 | async function setManualTarget() { |
85 | 117 | const targetFile = document.getElementById('manualTargetFile').value; |
86 | | - const targetMessageDiv = document.getElementById('targetMessage'); |
87 | | - if (!targetFile) { |
88 | | - targetMessageDiv.innerText = "Please enter a file path."; |
89 | | - targetMessageDiv.style.color = 'red'; |
90 | | - return; |
91 | | - } |
92 | | - try { |
93 | | - const response = await fetch('/api/set_target_file', { |
94 | | - method: 'POST', |
95 | | - headers: { 'Content-Type': 'application/json' }, |
96 | | - body: JSON.stringify({ target_file: targetFile }) |
97 | | - }); |
98 | | - const data = await response.json(); |
99 | | - if (response.ok) { |
100 | | - targetMessageDiv.innerText = `Target set: ${data.target_file}`; |
101 | | - targetMessageDiv.style.color = '#00FF41'; |
102 | | - document.getElementById('manualTargetFile').value = ''; // Clear input |
103 | | - } else { |
104 | | - targetMessageDiv.innerText = `Error: ${data.error || 'Failed to set target.'}`; |
105 | | - targetMessageDiv.style.color = 'red'; |
106 | | - } |
107 | | - } catch (e) { |
108 | | - targetMessageDiv.innerText = `Network error: ${e.message}`; |
109 | | - targetMessageDiv.style.color = 'red'; |
110 | | - } |
111 | | - } |
112 | | -
|
113 | | - // New function to render patches |
114 | | - function renderPatches(patches) { |
115 | | - const patchesDiv = document.getElementById('pendingPatches'); |
116 | | - if (patches.length === 0) { |
117 | | - patchesDiv.innerHTML = "No pending patches."; |
118 | | - return; |
119 | | - } |
120 | | - patchesDiv.innerHTML = patches.map(patch => ` |
121 | | - <div class="patch-card"> |
122 | | - <div class="label">Patch ID: ${patch.id}</div> |
123 | | - <pre class="patch-content">${patch.content}</pre> |
124 | | - <div class="patch-actions" style="margin-top: 10px;"> |
125 | | - <button class="approve-btn" onclick="reviewPatch('${patch.id}', 'approve')">Approve</button> |
126 | | - <button class="reject-btn" onclick="reviewPatch('${patch.id}', 'reject')">Reject</button> |
127 | | - </div> |
128 | | - </div> |
129 | | - `).join(''); |
130 | | - } |
131 | | -
|
132 | | - // New function to send patch review action |
133 | | - async function reviewPatch(patchId, action) { |
134 | | - try { |
135 | | - const response = await fetch('/api/review_patch', { |
136 | | - method: 'POST', |
137 | | - headers: { 'Content-Type': 'application/json' }, |
138 | | - body: JSON.stringify({ patch_id: patchId, action: action }) |
139 | | - }); |
140 | | - const data = await response.json(); |
141 | | - if (response.ok) { |
142 | | - alert(`Patch ${patchId} ${action}d successfully.`); |
143 | | - updateStats(); // Refresh dashboard to reflect changes |
144 | | - } else { |
145 | | - alert(`Error ${action}ing patch ${patchId}: ${data.error || 'Unknown error'}`); |
146 | | - } |
147 | | - } catch (e) { |
148 | | - alert(`Network error while ${action}ing patch ${patchId}: ${e.message}`); |
149 | | - } |
| 118 | + if (!targetFile) return; |
| 119 | + await fetch('/api/set_target_file', { |
| 120 | + method: 'POST', |
| 121 | + headers: { 'Content-Type': 'application/json' }, |
| 122 | + body: JSON.stringify({ target_file: targetFile }) |
| 123 | + }); |
| 124 | + document.getElementById('manualTargetFile').value = ''; |
150 | 125 | } |
151 | 126 |
|
152 | 127 | setInterval(updateStats, 3000); |
|
0 commit comments