From 2301710453641ed001ba39c72265ef2bfbb78060 Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 14:19:02 +0000 Subject: [PATCH 1/8] PyOB Evolution: Automated refactor of `src/pyob/entrance.py` (Iteration 1) --- src/pyob/entrance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pyob/entrance.py b/src/pyob/entrance.py index ea6f993..18855a4 100644 --- a/src/pyob/entrance.py +++ b/src/pyob/entrance.py @@ -347,8 +347,8 @@ def execute_targeted_iteration(self, iteration: int): ) for f_name in self.ENGINE_FILES: src = os.path.join(self.target_dir, "src", "pyob", f_name) - if not os.path.exists(src): - src = os.path.join(self.target_dir, f_name) + # Assuming src/pyob is the canonical location for engine files, + # consistent with PYTHONPATH setup in reboot_pyob. if os.path.exists(src): shutil.copy(src, str(pod_path)) except Exception as e: From 1d9bb26b85eb98694003221df96fb9f474e470f9 Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 14:31:27 +0000 Subject: [PATCH 2/8] PyOB Evolution: Automated refactor of `src/pyob/pyob_dashboard.py` (Iteration 4) --- src/pyob/pyob_dashboard.py | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/pyob/pyob_dashboard.py b/src/pyob/pyob_dashboard.py index 95409a3..7b43ffe 100644 --- a/src/pyob/pyob_dashboard.py +++ b/src/pyob/pyob_dashboard.py @@ -66,6 +66,10 @@
Architectural Analysis
Scanning structure...
+
+
Pending Patch Reviews
+
No pending patches.
+
Manual Override
@@ -94,6 +98,7 @@ document.getElementById('analysis').innerText = data.analysis || "Parsing..."; const queueDiv = document.getElementById('queue'); queueDiv.innerText = data.cascade_queue?.length > 0 ? data.cascade_queue.join('\\n') : "EMPTY"; + await updatePendingPatches(); // Refresh pending patches } catch (e) { document.getElementById('status-pill').innerText = "OFFLINE"; } } @@ -108,6 +113,50 @@ document.getElementById('manualTargetFile').value = ''; } + async function updatePendingPatches() { + try { + const response = await fetch('/api/pending_patches'); + const data = await response.json(); + const patchesDiv = document.getElementById('pending-patches'); + patchesDiv.innerHTML = ''; // Clear previous content + + if (data.patches && data.patches.length > 0) { + data.patches.forEach(patch => { + const patchElement = document.createElement('div'); + patchElement.style.marginBottom = '10px'; + patchElement.innerHTML = ` + Patch ID: ${patch.id}
+ File: ${patch.target_file}
+ Description: ${patch.description || 'N/A'}
+ + + `; + patchesDiv.appendChild(patchElement); + }); + } else { + patchesDiv.innerText = "No pending patches."; + } + } catch (e) { + console.error("Failed to fetch pending patches:", e); + document.getElementById('pending-patches').innerText = "Error loading patches."; + } + } + + async function reviewPatch(patchId, action) { + try { + await fetch('/api/review_patch', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ patch_id: patchId, action: action }) + }); + // Refresh stats and patches after review + await updateStats(); + } catch (e) { + console.error(`Failed to ${action} patch ${patchId}:`, e); + alert(`Failed to ${action} patch ${patchId}. Check console for details.`); + } + } + setInterval(updateStats, 3000); updateStats(); From 100509c0684bd0aefdfb409ae01d707b1e0406eb Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 14:35:23 +0000 Subject: [PATCH 3/8] PyOB Evolution: Automated refactor of `src/pyob/pyob_launcher.py` (Iteration 5) --- src/pyob/pyob_launcher.py | 111 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/pyob/pyob_launcher.py b/src/pyob/pyob_launcher.py index 03c0535..0ff106a 100644 --- a/src/pyob/pyob_launcher.py +++ b/src/pyob/pyob_launcher.py @@ -10,6 +10,117 @@ DEFAULT_GEMINI_MODEL = "gemini-2.5-flash" DEFAULT_LOCAL_MODEL = "qwen3-coder:30b" +# New feature content: HTML and JavaScript for the Pending Patch Review Card. +# This content is intended for OBSERVER_HTML, which is likely served by +# pyob_dashboard.py or entrance.py. Storing it here as a string literal +# in pyob_launcher.py makes it syntactically valid Python, but it would +# require further integration in the web serving components (e.g., +# EntranceController or pyob_dashboard.py) to be functionally active +# in the frontend UI. +OBSERVER_PATCH_REVIEW_HTML = """ + +
+
+

Pending Patch Reviews 0

+
+
+
+

No pending patches.

+
+
+
+ + +""" + def load_config(): """Load config from file or environment, or prompt user if missing.""" From 65111c4c382a4eab9dce7d855188663d91854de3 Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 14:39:09 +0000 Subject: [PATCH 4/8] PyOB Evolution: Automated refactor of `src/pyob/pyob_dashboard.py` (Iteration 6) --- src/pyob/pyob_dashboard.py | 91 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/src/pyob/pyob_dashboard.py b/src/pyob/pyob_dashboard.py index 7b43ffe..c73fb6a 100644 --- a/src/pyob/pyob_dashboard.py +++ b/src/pyob/pyob_dashboard.py @@ -38,7 +38,7 @@ } .status-pill { padding: 4px 12px; border-radius: 20px; font-size: 0.7rem; font-weight: 800; background: #222; } .evolving { color: var(--accent); border: 1px solid var(--accent); box-shadow: 0 0 10px #00ffa344; } - input { background: #000; border: 1px solid #2a2a30; color: var(--accent); padding: 10px; border-radius: 4px; width: 100%; font-family: 'JetBrains Mono'; margin-bottom: 10px; } + input, textarea { background: #000; border: 1px solid #2a2a30; color: var(--accent); padding: 10px; border-radius: 4px; width: 100%; font-family: 'JetBrains Mono'; margin-bottom: 10px; } button { width: 100%; padding: 12px; background: var(--accent); color: #000; border: none; border-radius: 4px; font-weight: 700; cursor: pointer; transition: 0.2s; } button:hover { filter: brightness(1.2); } @@ -56,7 +56,8 @@
Logic Memory (MEMORY.md)
-
Initializing brain...
+ +
System Logs (HISTORY.md)
@@ -93,7 +94,7 @@ const isEvolving = data.cascade_queue?.length > 0 || data.patches_count > 0; pill.innerText = isEvolving ? "EVOLVING" : "STABLE"; pill.className = isEvolving ? "status-pill evolving" : "status-pill"; - document.getElementById('memory').innerText = data.memory || "Brain empty."; + document.getElementById('memory').value = data.memory || "Brain empty."; // Changed to .value for textarea document.getElementById('history').innerText = data.history || "No logs."; document.getElementById('analysis').innerText = data.analysis || "Parsing..."; const queueDiv = document.getElementById('queue'); @@ -157,6 +158,27 @@ } } + async function saveMemory() { + const memoryContent = document.getElementById('memory').value; + try { + const response = await fetch('/api/update_memory', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ content: memoryContent }) + }); + const result = await response.json(); + if (response.ok) { + alert('Logic Memory saved successfully!'); + await updateStats(); // Refresh to ensure consistency + } else { + alert(`Failed to save Logic Memory: ${result.error}`); + } + } catch (e) { + console.error("Failed to save Logic Memory:", e); + alert("Error saving Logic Memory. Check console for details."); + } + } + setInterval(updateStats, 3000); updateStats(); @@ -395,6 +417,69 @@ def do_POST(self): self.wfile.write( json.dumps({"error": f"Internal server error: {str(e)}"}).encode() ) + # NEW POST endpoint for updating Logic Memory + elif self.path == "/api/update_memory": + if self.controller is None: + self.send_response(503) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": "Controller not initialized"}).encode() + ) + return + + content_length = int(self.headers.get("Content-Length", 0)) + post_data = self.rfile.read(content_length) + try: + data = json.loads(post_data.decode("utf-8")) + new_memory_content = data.get("content") + + if new_memory_content is None: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + {"error": "Missing 'content' in request body"} + ).encode() + ) + return + + self.controller.update_memory(new_memory_content) + + self.send_response(200) + self.send_header("Content-type", "application/json") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write( + json.dumps( + {"message": "Logic Memory updated successfully"} + ).encode() + ) + + except json.JSONDecodeError: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(json.dumps({"error": "Invalid JSON"}).encode()) + except AttributeError: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + { + "error": "Controller method 'update_memory' not found. Ensure entrance.py is updated." + } + ).encode() + ) + except Exception as e: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": f"Internal server error: {str(e)}"}).encode() + ) else: self.send_response(404) self.end_headers() From 23feb5d32b0dbf1ca7eb74b3c9283d347dee1c78 Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 14:54:37 +0000 Subject: [PATCH 5/8] PyOB Evolution: Automated refactor of `src/pyob/entrance.py` (Iteration 7) --- src/pyob/entrance.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pyob/entrance.py b/src/pyob/entrance.py index 18855a4..451c3c0 100644 --- a/src/pyob/entrance.py +++ b/src/pyob/entrance.py @@ -51,6 +51,9 @@ def __init__(self, target_dir: str): self.analysis_path = os.path.join(self.pyob_dir, "ANALYSIS.md") self.history_path = os.path.join(self.pyob_dir, "HISTORY.md") self.symbols_path = os.path.join(self.pyob_dir, "SYMBOLS.json") + self.memory_path = os.path.join( + self.pyob_dir, "MEMORY.md" + ) # For interactive memory editor self.llm_engine = AutoReviewer(self.target_dir) self.code_parser = CodeParser() self.ledger = self.load_ledger() From c711bb472adf83263154548f89f2a18b1b18582c Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 15:51:04 +0000 Subject: [PATCH 6/8] PyOB Evolution: Automated refactor of `src/pyob/pyob_dashboard.py` (Iteration 8) --- src/pyob/pyob_dashboard.py | 212 ++++++++++++++++++++++++++++++++++++- 1 file changed, 209 insertions(+), 3 deletions(-) diff --git a/src/pyob/pyob_dashboard.py b/src/pyob/pyob_dashboard.py index c73fb6a..4b1c974 100644 --- a/src/pyob/pyob_dashboard.py +++ b/src/pyob/pyob_dashboard.py @@ -41,6 +41,28 @@ input, textarea { background: #000; border: 1px solid #2a2a30; color: var(--accent); padding: 10px; border-radius: 4px; width: 100%; font-family: 'JetBrains Mono'; margin-bottom: 10px; } button { width: 100%; padding: 12px; background: var(--accent); color: #000; border: none; border-radius: 4px; font-weight: 700; cursor: pointer; transition: 0.2s; } button:hover { filter: brightness(1.2); } + /* Specific styles for queue items */ + .queue-item { + margin-bottom: 8px; + padding: 8px; + background: #00000066; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: space-between; + font-family: 'JetBrains Mono'; + font-size: 0.8em; + color: #ced4e0; + } + .queue-item button { + width: auto; + padding: 5px 10px; + font-size: 0.7em; + margin-left: 5px; + border-radius: 3px; + } + .queue-item .move-btn { background: #4a4a50; color: var(--text); } + .queue-item .remove-btn { background: #cc0000; color: #fff; } @@ -78,7 +100,7 @@
Queue Status
-
IDLE
+
IDLE
@@ -97,10 +119,31 @@ document.getElementById('memory').value = data.memory || "Brain empty."; // Changed to .value for textarea document.getElementById('history').innerText = data.history || "No logs."; document.getElementById('analysis').innerText = data.analysis || "Parsing..."; + + // --- START NEW QUEUE RENDERING LOGIC --- const queueDiv = document.getElementById('queue'); - queueDiv.innerText = data.cascade_queue?.length > 0 ? data.cascade_queue.join('\\n') : "EMPTY"; + queueDiv.innerHTML = ''; // Clear previous content + if (data.cascade_queue && data.cascade_queue.length > 0) { + data.cascade_queue.forEach((item, index) => { + const itemElement = document.createElement('div'); + itemElement.className = 'queue-item'; + itemElement.innerHTML = ` + ${item} +
+ + + +
+ `; + queueDiv.appendChild(itemElement); + }); + } else { + queueDiv.innerText = "EMPTY"; + } + // --- END NEW QUEUE RENDERING LOGIC --- + await updatePendingPatches(); // Refresh pending patches - } catch (e) { document.getElementById('status-pill').innerText = "OFFLINE"; } + } catch (e) { document.getElementById('status-pill').innerText = "OFFLINE"; console.error("Error updating stats:", e); } } async function setManualTarget() { @@ -179,6 +222,39 @@ } } + // --- START NEW QUEUE INTERACTION FUNCTIONS --- + async function moveQueueItem(itemId, direction) { + try { + await fetch('/api/cascade_queue/move', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ item_id: itemId, direction: direction }) + }); + await updateStats(); // Refresh queue after move + } catch (e) { + console.error(`Failed to move item ${itemId} ${direction}:`, e); + alert(`Failed to move item. Check console for details.`); + } + } + + async function removeQueueItem(itemId) { + if (!confirm(`Are you sure you want to remove "${itemId}" from the queue?`)) { + return; + } + try { + await fetch('/api/cascade_queue/remove', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ item_id: itemId }) + }); + await updateStats(); // Refresh queue after removal + } catch (e) { + console.error(`Failed to remove item ${itemId}:`, e); + alert(`Failed to remove item. Check console for details.`); + } + } + // --- END NEW QUEUE INTERACTION FUNCTIONS --- + setInterval(updateStats, 3000); updateStats(); @@ -480,6 +556,136 @@ def do_POST(self): self.wfile.write( json.dumps({"error": f"Internal server error: {str(e)}"}).encode() ) + # NEW POST endpoint for moving cascade queue items + elif self.path == "/api/cascade_queue/move": + if self.controller is None: + self.send_response(503) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": "Controller not initialized"}).encode() + ) + return + + content_length = int(self.headers.get("Content-Length", 0)) + post_data = self.rfile.read(content_length) + try: + data = json.loads(post_data.decode("utf-8")) + item_id = data.get("item_id") + direction = data.get("direction") + + if not item_id or direction not in ["up", "down"]: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + { + "error": "Missing 'item_id' or invalid 'direction' in request body" + } + ).encode() + ) + return + + self.controller.move_cascade_queue_item(item_id, direction) + + self.send_response(200) + self.send_header("Content-type", "application/json") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write( + json.dumps( + {"message": f"Item {item_id} moved {direction} successfully"} + ).encode() + ) + + except json.JSONDecodeError: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(json.dumps({"error": "Invalid JSON"}).encode()) + except AttributeError: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + { + "error": "Controller method 'move_cascade_queue_item' not found. Ensure entrance.py is updated." + } + ).encode() + ) + except Exception as e: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": f"Internal server error: {str(e)}"}).encode() + ) + + # NEW POST endpoint for removing cascade queue items + elif self.path == "/api/cascade_queue/remove": + if self.controller is None: + self.send_response(503) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": "Controller not initialized"}).encode() + ) + return + + content_length = int(self.headers.get("Content-Length", 0)) + post_data = self.rfile.read(content_length) + try: + data = json.loads(post_data.decode("utf-8")) + item_id = data.get("item_id") + + if not item_id: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + {"error": "Missing 'item_id' in request body"} + ).encode() + ) + return + + self.controller.remove_cascade_queue_item(item_id) + + self.send_response(200) + self.send_header("Content-type", "application/json") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write( + json.dumps( + {"message": f"Item {item_id} removed successfully"} + ).encode() + ) + + except json.JSONDecodeError: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(json.dumps({"error": "Invalid JSON"}).encode()) + except AttributeError: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + { + "error": "Controller method 'remove_cascade_queue_item' not found. Ensure entrance.py is updated." + } + ).encode() + ) + except Exception as e: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": f"Internal server error: {str(e)}"}).encode() + ) else: self.send_response(404) self.end_headers() From 27fc54e1a554feb9040ff253868839d5efb9def2 Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 15:55:25 +0000 Subject: [PATCH 7/8] PyOB Evolution: Automated refactor of `src/pyob/entrance.py` (Iteration 9) --- src/pyob/entrance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyob/entrance.py b/src/pyob/entrance.py index 451c3c0..cbcc872 100644 --- a/src/pyob/entrance.py +++ b/src/pyob/entrance.py @@ -570,7 +570,7 @@ def detect_symbolic_ripples( changed_text = "\n".join( [line for line in diff if line.startswith("+") or line.startswith("-")] ) - potential_symbols = set(re.findall(r"([a-zA-Z0-9_$]{4,})", changed_text)) + potential_symbols = set(re.findall(r"\b[a-zA-Z_][a-zA-Z0-9_]*\b", changed_text)) impacted_files = [] for sym in potential_symbols: if self.ledger["definitions"].get(sym) == source_file: From fc8a05dba24e290c9cd04b133fa0b8b284fea60f Mon Sep 17 00:00:00 2001 From: pyob-bot Date: Mon, 9 Mar 2026 16:18:51 +0000 Subject: [PATCH 8/8] PyOB Evolution: Automated refactor of `src/pyob/pyob_dashboard.py` (Iteration 10) --- src/pyob/pyob_dashboard.py | 94 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/pyob/pyob_dashboard.py b/src/pyob/pyob_dashboard.py index 4b1c974..c04cb21 100644 --- a/src/pyob/pyob_dashboard.py +++ b/src/pyob/pyob_dashboard.py @@ -98,6 +98,11 @@ +
+
Manual Cascade Injection
+ + +
Queue Status
IDLE
@@ -222,6 +227,32 @@ } } + async function addCascadeItem() { + const item = document.getElementById('cascadeItem').value; + if (!item) { + alert('Please enter an item to add to the cascade queue.'); + return; + } + try { + const response = await fetch('/api/cascade_queue/add', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ item: item }) + }); + const result = await response.json(); + if (response.ok) { + alert(`'${item}' added to cascade queue.`); + document.getElementById('cascadeItem').value = ''; // Clear input + await updateStats(); // Refresh queue display + } else { + alert(`Failed to add item to queue: ${result.error}`); + } + } catch (e) { + console.error("Failed to add item to cascade queue:", e); + alert("Error adding item to cascade queue. Check console for details."); + } + } + // --- START NEW QUEUE INTERACTION FUNCTIONS --- async function moveQueueItem(itemId, direction) { try { @@ -686,6 +717,69 @@ def do_POST(self): self.wfile.write( json.dumps({"error": f"Internal server error: {str(e)}"}).encode() ) + # NEW POST endpoint for adding items to cascade queue + elif self.path == "/api/cascade_queue/add": + if self.controller is None: + self.send_response(503) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": "Controller not initialized"}).encode() + ) + return + + content_length = int(self.headers.get("Content-Length", 0)) + post_data = self.rfile.read(content_length) + try: + data = json.loads(post_data.decode("utf-8")) + item = data.get("item") + + if not item: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": "Missing 'item' in request body"}).encode() + ) + return + + self.controller.add_to_cascade_queue(item) + + self.send_response(200) + self.send_header("Content-type", "application/json") + self.send_header("Access-Control-Allow-Origin", "*") + self.end_headers() + self.wfile.write( + json.dumps( + { + "message": f"Item '{item}' added to cascade queue successfully" + } + ).encode() + ) + + except json.JSONDecodeError: + self.send_response(400) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(json.dumps({"error": "Invalid JSON"}).encode()) + except AttributeError: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps( + { + "error": "Controller method 'add_to_cascade_queue' not found. Ensure entrance.py is updated." + } + ).encode() + ) + except Exception as e: + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write( + json.dumps({"error": f"Internal server error: {str(e)}"}).encode() + ) else: self.send_response(404) self.end_headers()