So it’s still showing "Writing article to Google Sheets…" which means the Promise.race timeout isn’t working either. And "Starting article generation…" appears right after β€” which means handleArticleComplete finished and called processNextPrompt, but then the step notifications inside processNextPrompt never updated the status.

This tells me the service worker is restarting between calls. Chrome kills extension service workers after 30 seconds of inactivity, and when it restarts it loses all in-memory state. The state is saved to chrome.storage.local so it survives, but the execution flow doesn’t β€” processNextPrompt gets called, the service worker dies mid-execution, and nothing ever updates the status again.

The fix is to make processNextPrompt restart itself if the service worker wakes up, and to use an alarm to keep the service worker alive during long operations:This addresses the root cause. Chrome MV3 service workers are killed after ~30 seconds of inactivity β€” and a long fetch to Google Apps Script or a waitForInput call counts as "inactivity" from Chrome’s perspective since there’s no active network request Chrome tracks.

What’s new:

Keep-alive alarm β€” fires every 24 seconds, keeping the service worker alive throughout the entire run. This is the standard Chrome-recommended approach for long-running MV3 extensions.

Heartbeat + recovery β€” every poll cycle writes a timestamp to storage. If the alarm fires and the heartbeat is more than 60 seconds old, it knows the worker was killed mid-execution and automatically restarts processNextPrompt for the current article rather than freezing silently.

Automatic recovery β€” if the worker does get killed during a fetch or navigation, it will restart itself within 24 seconds and pick up where it left off instead of hanging forever.