Skip to content

Fix cells stuck as "needs run" after backend-initiated execution#8794

Merged
manzt merged 6 commits intomainfrom
push-spyzussywurm
Mar 21, 2026
Merged

Fix cells stuck as "needs run" after backend-initiated execution#8794
manzt merged 6 commits intomainfrom
push-spyzussywurm

Conversation

@manzt
Copy link
Copy Markdown
Collaborator

@manzt manzt commented Mar 20, 2026

Two code_mode paths left cells permanently showing "needs run" in the
frontend even after execution. In _apply_ops, reactive descendants
from mutate_graph were never included in the run set, so autorun
executed them but the frontend was told they were stale. In __aexit__,
a run-only flush (no structural ops) bypassed _apply_ops entirely and
never notified the frontend.

Both fixes are backend-only. In autorun mode, execute-code now blocks
until downstream cells finish so the agent sees their full output. Lazy
mode is unchanged -- downstream cells stay stale as expected.

Copilot AI review requested due to automatic review settings March 20, 2026 18:08
@manzt manzt requested a review from Light2Dark as a code owner March 20, 2026 18:08
@manzt manzt added the bug Something isn't working label Mar 20, 2026
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Mar 21, 2026 0:50am

Request Review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a frontend state-sync gap where cells created as stale (e.g., via code_mode) could remain visually “needs run” after being auto-executed by the backend, by updating CellData when execution completes.

Changes:

  • Detects a backend-initiated run completion (cell transitions to idle after having a runStartTimestamp) and synchronizes CellData.edited / CellData.lastCodeRun.
  • Ensures the “needs run” UI state reflects completed execution even when prepareForRun was never called.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# cells without run_cell leaves them stale/unexecuted.
_run_set = explicit_run or set()
if _run_set and self._kernel.reactive_execution_mode == "autorun":
_run_set = _run_set | cells_to_run
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be from (or related to) a hack a long time ago where we put cells as queued when they were run from the frontend (but are now no longer)

@mscolnick mscolnick requested a review from akshayka March 20, 2026 22:29
@manzt
Copy link
Copy Markdown
Collaborator Author

manzt commented Mar 20, 2026

The main behavior change here is that execute-code.sh now streams the response of the full execution that is configured by the user (including dependent cells if they have "autorun" enabled). I think this is desired because the agent then "sees" how its executed changes effect other cells. Otherwise if there is a runtime error, the model wouldn't know without figuring out to re-inspect state.

manzt added 6 commits March 21, 2026 08:48
When code_mode creates cells marked as stale (`code_is_stale=true`), the
frontend sets `lastCodeRun=null` and `edited=true`. If the kernel then
auto-executes those cells via reactivity (autorun mode), the cell
transitions through queued/running/idle in `CellRuntimeState`, but
`handleCellMessage` never touched `CellData` — so `edited` stayed true
and the cell displayed a permanent yellow "needs run" border despite
having correct output.

The fix detects when a cell transitions to idle after a completed run
(indicated by `runStartTimestamp` being set) while still marked as
`edited`, and syncs `CellData.lastCodeRun` and `edited` to reflect the
completed execution. This mirrors what `prepareForRun` does for
frontend-initiated runs, covering the backend-initiated path that was
previously missed.
Guard the edited/lastCodeRun sync with lastCodeRun == null so it only
fires for cells created as stale by the backend (where setCellCodes set
lastCodeRun to null). This avoids incorrectly clearing edited for cells
where the user edits code mid-run — in that case lastCodeRun was already
set by prepareForRun, so the guard skips the sync and the cell correctly
stays marked as needs-run.

Adds two tests: one for the backend-stale path (should clear edited) and
one for the mid-run user-edit path (should preserve edited).
The two-step pattern (edit_cell in one flush, run_cell in a separate
flush) bypassed _apply_ops entirely via the elif branch in __aexit__,
so no UpdateCellCodesNotification was sent and the frontend never
cleared its stale state. Send a code_is_stale=false notification
before re-running so the frontend syncs edited/lastCodeRun.

Also narrow the frontend safety-net in handleCellMessage to only fire
when lastCodeRun is null (per review feedback), avoiding interference
with mid-run user edits. Add tests for both paths.
Two code_mode paths left cells permanently showing "needs run" in the
frontend even after execution. In `_apply_ops`, reactive descendants
from `mutate_graph` were never included in the run set, so autorun
executed them but the frontend was told they were stale. In `__aexit__`,
a run-only flush (no structural ops) bypassed `_apply_ops` entirely and
never notified the frontend.

Both fixes are backend-only. In autorun mode, `execute-code` now blocks
until downstream cells finish so the agent sees their full output. Lazy
mode is unchanged -- downstream cells stay stale as expected.
Backend-only fix is sufficient. The frontend safety net in
handleCellMessage is not needed since _apply_ops and __aexit__
now correctly send code_is_stale=false before execution.
@manzt manzt merged commit 825296c into main Mar 21, 2026
43 checks passed
@manzt manzt deleted the push-spyzussywurm branch March 21, 2026 14:44
@github-actions
Copy link
Copy Markdown

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.21.2-dev31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants