diff --git a/static/panels.js b/static/panels.js index b44be0cb..30d19c2b 100644 --- a/static/panels.js +++ b/static/panels.js @@ -865,21 +865,6 @@ async function _loadCronDetailRuns(jobId){ } catch(e) { /* ignore */ } } -function _wrapCronOutput(text){ - const trimmed = (text || '').trim(); - if (!trimmed) return ''; - // If content starts with a common markdown block marker, render as-is. - // Otherwise wrap in triple backticks so JSON, logs, and structured text - // render as a
 block with preserved whitespace.
-  const isMarkdown =
-    trimmed.startsWith('#') || trimmed.startsWith('|') ||
-    trimmed.startsWith('>') || trimmed.startsWith('```') ||
-    trimmed.startsWith('~~~') || trimmed.startsWith('-') ||
-    trimmed.startsWith('*') || trimmed.startsWith('_') ||
-    trimmed.startsWith('[');
-  return isMarkdown ? trimmed : '```\n' + trimmed + '\n```';
-}
-
 async function _loadRunContent(jobId, filename, runId){
   const body = document.querySelector(`#${runId} .detail-run-body`);
   if (!body) return;
@@ -909,12 +894,17 @@ async function _loadRunContent(jobId, filename, runId){
     const expanded = _cronExpansionGet(_cronRunExpandKey(jobId, filename));
     const output = expanded ? (data.content || data.snippet || '') : (data.snippet || data.content || '');
     body.classList.toggle('expanded', expanded);
-    const wrapped = _wrapCronOutput(output);
-    if (typeof renderMd === 'function') {
-      body.innerHTML = renderMd(wrapped);
-    } else {
-      body.textContent = output;
-    }
+    // Cron run output is never authored Markdown — render as literal
+    // preformatted text using DOM-created 
 so all content
+    // (including shapes starting with #, |, >, ``` and embedded fences)
+    // renders verbatim without Markdown interpretation.
+    body.innerHTML = '';
+    const pre = document.createElement('pre');
+    pre.className = 'cron-run-pre';
+    const code = document.createElement('code');
+    code.textContent = output;
+    pre.appendChild(code);
+    body.appendChild(pre);
     const usageStrip = _formatCronRunUsageStrip(data.usage);
     if (usageStrip) {
       const usage = document.createElement('div');
@@ -930,7 +920,20 @@ async function _loadRunContent(jobId, filename, runId){
       btn.onclick = () => {
         _cronExpansionSet(_cronRunExpandKey(jobId, filename), true);
         body.classList.add('expanded');
-        body.innerHTML = renderMd ? renderMd(_wrapCronOutput(data.content)) : data.content;
+        body.innerHTML = '';
+        const pre = document.createElement('pre');
+        pre.className = 'cron-run-pre';
+        const code = document.createElement('code');
+        code.textContent = data.content || '';
+        pre.appendChild(code);
+        body.appendChild(pre);
+        const usageStrip = _formatCronRunUsageStrip(data.usage);
+        if (usageStrip) {
+          const usage = document.createElement('div');
+          usage.className = 'cron-run-usage-strip cron-run-usage-footer';
+          usage.textContent = usageStrip;
+          body.appendChild(usage);
+        }
         btn.remove();
       };
       body.appendChild(btn);
diff --git a/static/style.css b/static/style.css
index ae87e257..daa9cab3 100644
--- a/static/style.css
+++ b/static/style.css
@@ -5533,6 +5533,8 @@ main.main > .main-view:not([id="mainChat"]):not([id="mainSettings"]) .main-view-
 .detail-run-body{display:none;margin-top:6px;font-size:12px;color:var(--muted);white-space:pre-wrap;line-height:1.5;max-height:260px;overflow-y:auto;background:var(--sidebar);border:1px solid var(--border);border-radius:6px;padding:8px 10px;}
 .detail-run-item.open .detail-run-body{display:block;}
 .detail-run-body.expanded{max-height:none;overflow-y:visible;}
+.detail-run-body .cron-run-pre{margin:0;font-size:12px;line-height:1.5;white-space:pre-wrap;word-break:break-word;}
+.detail-run-body .cron-run-pre code{background:transparent;padding:0;font-family:var(--font-mono);}
 .workspace-panel-tabs{display:flex;gap:4px;padding:6px 8px;border-bottom:1px solid var(--border);}
 .workspace-panel-tab{flex:1;border:1px solid transparent;background:transparent;color:var(--muted);border-radius:7px;padding:5px 8px;font-size:12px;cursor:pointer;}
 .workspace-panel-tab.active{background:var(--surface-subtle);color:var(--text);border-color:var(--border2);}