Two reports, one cause: the script's fetch had no .catch. When the server had exited the promise rejected, the chain never ran, and not even the status line moved — so a dead server and a click that did nothing were indistinguishable. play again read as a dead button, and the linger timeout was invisible. Now a rejection says the session is gone and seals the page, and a 5-second heartbeat against a new /alive notices it without needing a click, which is what the timeout case requires. The beat carries the token, and does not extend the linger: that deadline is absolute. The harness had the same hole. jsrun's fetch stub had no .catch, so the branch that notices a dead server would have been unreachable in every test — the very defect the stub's own comment records from CB-WP-0024. Teaching it __failing, .catch and a recorded setInterval was the fix; writing the script defensively would have repeated the trap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c2a7e40b67
commit
82aead6cea
9 changed files with 448 additions and 7 deletions
|
|
@ -3,6 +3,7 @@ id: CB-WP-0034
|
|||
kind: product
|
||||
title: "Who you are bonding with"
|
||||
status: done
|
||||
state_hub_workstream_id: "bde0c1d5-a76c-4431-a48a-a9fa81f4d0cc"
|
||||
---
|
||||
|
||||
# Purpose
|
||||
|
|
@ -52,6 +53,7 @@ neighbours as they were.
|
|||
id: CB-WP-0034-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "d8429ce2-991a-45df-9fcd-6b70b0e81511"
|
||||
```
|
||||
|
||||
**Controls:**
|
||||
|
|
|
|||
78
workplans/CB-WP-0035-a-session-that-answers-nothing.md
Normal file
78
workplans/CB-WP-0035-a-session-that-answers-nothing.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
id: CB-WP-0035
|
||||
kind: product
|
||||
title: "A session that answers nothing"
|
||||
status: done
|
||||
---
|
||||
|
||||
# Purpose
|
||||
|
||||
```
|
||||
structural tier S (one endpoint, one rejection handler; no rule, no
|
||||
dependency, no artifact contract moved)
|
||||
chaos d8 = 4 → no override
|
||||
declared tier S
|
||||
```
|
||||
|
||||
**Declaration 6 of chaos window 3.**
|
||||
|
||||
## The report, and it is one defect not two
|
||||
|
||||
> *"I think the server timing out is not noticed by the client. And 'Play
|
||||
> Again' does not report that the session is no longer available."*
|
||||
|
||||
Both come from the same three characters. The script's request was
|
||||
|
||||
```js
|
||||
fetch(...).then(...).then(...) // and no .catch
|
||||
```
|
||||
|
||||
so when the process had exited the promise **rejected, the chain never
|
||||
ran, and not even the status line moved.** A dead server and a click that
|
||||
did nothing were indistinguishable — which is why `play again` read as a
|
||||
dead button and the linger timeout was invisible.
|
||||
|
||||
**A request that cannot be answered is information**, and it was being
|
||||
thrown away.
|
||||
|
||||
## Task: notice, and say so
|
||||
|
||||
```task
|
||||
id: CB-WP-0035-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Controls:**
|
||||
- **both paths** — pressing a control, and noticing without pressing
|
||||
anything, which is the timeout case;
|
||||
- **both pages**, because the timeout matters most *during play*;
|
||||
- the heartbeat **carries the token**, or a refusal every five seconds
|
||||
would seal a live session;
|
||||
- mutation-proven: remove the `.catch` and the status goes empty, which is
|
||||
the reported symptom exactly.
|
||||
|
||||
**Done 2026-08-07.** `.catch(gone)`, plus a 5-second heartbeat against a
|
||||
new `/alive` — its own path so a beat costs a few bytes rather than a
|
||||
whole re-render. It **does not extend the linger**: that deadline is
|
||||
absolute, so a tab left open still cannot hold the process open.
|
||||
|
||||
**The harness had the same hole as the code.** `jsrun`'s `fetch` stub had
|
||||
no `.catch`, so the branch that notices a dead server would have been
|
||||
unreachable in every test — *the very defect the stub's own comment
|
||||
records from CB-WP-0024*, where a then-chain that never invoked its
|
||||
callbacks let "the page still looks live" survive. Teaching the stub
|
||||
`__failing`, `.catch` and a recorded `setInterval` was the fix; writing
|
||||
the script defensively instead would have repeated the trap.
|
||||
|
||||
**The first cut wired the heartbeat into the ending page only.** An unused
|
||||
variable caught it — luck, not a control — so `every_page_can_tell_the_
|
||||
session_has_gone` now asserts it on both.
|
||||
|
||||
## Not done here
|
||||
|
||||
- **Five seconds is a guess.** Nothing measures how long a player tolerates
|
||||
a dead-looking page, and this pass did not find out.
|
||||
- **A brief network stall seals the page**, the same as a dead server. For
|
||||
a loopback-only server that is nearly always the truth, but it is a
|
||||
false positive waiting for the first non-loopback deployment.
|
||||
Loading…
Add table
Add a link
Reference in a new issue