') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix(runtime): preserve stop semantics for synthetic terminals by Astro-Han · Pull Request #435 · apache/maka · GitHub
Skip to content

fix(runtime): preserve stop semantics for synthetic terminals - #435

Merged
Astro-Han merged 2 commits into
mainfrom
codex/runtime-terminal-followup
Jul 2, 2026
Merged

fix(runtime): preserve stop semantics for synthetic terminals#435
Astro-Han merged 2 commits into
mainfrom
codex/runtime-terminal-followup

Conversation

@Astro-Han

@Astro-HanAstro-Han commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Preserve user stop semantics when a live AgentRun has to synthesize a missing terminal RuntimeEvent.
  • Split live synthetic terminal facts from legacy recovered terminal facts so live fallbacks keep the current invocationId and do not set recovered=true.
  • Keep synthetic cancelled RuntimeEvent metadata and run headers consistent, including default abortSource.
  • Remove the unused RuntimeRunner.onInitialRuntimeEvent hook so the initial runtime event has one owner.

Why

Follow-up to #410.

The merged terminal-ledger invariant now prevents terminal run headers without terminal runtime facts, but the live fallback path still treated every missing terminal as a failed recovered event. That made user-initiated stops look like system failures when the backend did not emit an abort/complete terminal event, and it made current-run synthetic terminals look like historical recovery facts.

Scope

Changed:

  • AgentRun now maps stopped or aborted missing-terminal finalization to a cancelled run header and an aborted terminal RuntimeEvent with abortSource.
  • terminal-run-commit now uses one synthetic terminal builder for live and recovered events, with recovery metadata controlled by inputs.
  • Live synthetic failed terminals keep the current invocation id and no longer carry stateDelta.recovered.
  • Synthetic cancelled fallbacks now commit the same effective abortSource to both the RuntimeEvent and run header.
  • RuntimeRunner no longer exposes the unused onInitialRuntimeEvent hook.
  • Regression tests cover stopped live runs with no terminal event, live synthetic invocation ids, recovered-vs-live terminal metadata, and cancelled fallback default abortSource.

Not included:

  • UI changes, schema migrations, or changes to legacy recovery semantics. Legacy recovery still writes recovered=true.

Verification

  • npm run -w @maka/runtime test
  • npm run typecheck
  • npm run -w @maka/headless test
  • git diff --check

User-facing impact

No UI changes. A user-stopped run should remain cancelled even if the backend never emits a terminal event, instead of being recorded as failed/missing_terminal_event.

Reviewer notes

This is a small follow-up after #410 merged. The main behavior change is deliberately in the live synthetic terminal path; repair/recovery builders remain reserved for legacy or startup recovery facts, while the shared builder keeps their common event shape from drifting.

@Astro-Han
Astro-Han merged commit a63ae4d into mainJul 2, 2026
@Astro-Han
Astro-Han deleted the codex/runtime-terminal-followup branch July 2, 2026 16:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Astro-Han