The worker's status claims success only on its first frame (improvise-i0v9)
The worker transport wrote "in-page worker · <doc>" when it spawned the worker, before anything had answered, so a tab whose worker could not start showed a success-looking status over a blank page. It now writes "starting the worker · <doc>…", and createShell's arm() takes an `answer` that sawFrame writes on the first frame, but only while the watchdog is still armed. A ReadOnly or SeedMissing notice lands BEFORE the Snapshot, and fail() has already disarmed, so the claim cannot overwrite the precise reason. The two-tab spec now logs every #status and denies both the premature claim and "did not answer" before the page clock is walked. A new spec pins the exact status sequence on the writable path. Reasoning: context/code/clients.md, "The watchdog". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
+13
-7
@@ -339,7 +339,12 @@ export function createShell({
|
||||
clearTimer = clearTimeout,
|
||||
}) {
|
||||
let watchdog = null;
|
||||
let answered = null;
|
||||
let arms = 0;
|
||||
const disarm = () => {
|
||||
clearTimer(watchdog);
|
||||
watchdog = null;
|
||||
};
|
||||
|
||||
return {
|
||||
setShell(text) {
|
||||
@@ -350,24 +355,25 @@ export function createShell({
|
||||
},
|
||||
/** A peer that never answers the handshake. Deliberately about the *first
|
||||
* frame*, not either peer's own failure modes — clients.md. */
|
||||
arm(message) {
|
||||
arm(message, { answer = null } = {}) {
|
||||
arms += 1;
|
||||
clearTimer(watchdog);
|
||||
answered = answer;
|
||||
disarm();
|
||||
watchdog = setTimer(() => {
|
||||
watchdog = null;
|
||||
this.setShell(message);
|
||||
}, timeoutMs);
|
||||
},
|
||||
/** A frame arrived, so the peer answered: the watchdog has no question
|
||||
* left to ask. */
|
||||
/** A frame arrived, so the peer answered. Only the FIRST, and only if no
|
||||
* failure spoke first, may say so (improvise-i0v9, clients.md). */
|
||||
sawFrame() {
|
||||
clearTimer(watchdog);
|
||||
watchdog = null;
|
||||
if (watchdog !== null && answered !== null) this.setShell(answered);
|
||||
disarm();
|
||||
},
|
||||
/** A peer that failed *loudly* has already said something more precise, so
|
||||
* the watchdog must be DISARMED and not merely pre-empted (PR #13). */
|
||||
fail(text) {
|
||||
this.sawFrame();
|
||||
disarm();
|
||||
this.setShell(text);
|
||||
},
|
||||
armed: () => watchdog !== null,
|
||||
|
||||
Reference in New Issue
Block a user