Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
---
|
|
|
|
|
id: CB-WP-0018
|
|
|
|
|
kind: product
|
|
|
|
|
title: "The browser is a client: game over, a log, and where a drop goes"
|
CB-WP-0018 T03/T04: explanations, and window 1's verdict
T03: input::describe writes a sentence per legal command; data-descs
carries them in step with data-targets; the ghost already following the
pointer shows the one for whatever legal target is under it, so the
explanation lands beside the target with no overlay layer to keep
aligned. ADR-0010 D1 binds -- the page renders it, never composes it.
Both mutations INITIALLY SURVIVED because the fixture's Attack card had
exactly one target, where an off-by-one shift and a truncation are both
no-ops. CB-EV-0014's lesson one level in: a fixture too thin to express
a failure is how the failure survives. Two attack targets now, both red.
T04: chaos rate d4 -> d8, window 2 open at 12 declarations, retiring if
an override changes nothing twice running. Window 1's condition was NOT
met -- both overrides changed the outcome -- so the mechanism is kept.
The weakest part of the decision is that it is a rate change argued from
n=2, so window 2 carries a falsifier: no override at all is evidence the
rate went too far, not that the mechanism is healthy.
InnerLoop.md hit 401 lines and the loadability gate fired; the rationale
moved to InnerLoopReference.md, structurally, per the standing precedent
that limits are not raised.
CB-WP-0017 settled at $9.48/40 against $5.19/23 reported mid-flight,
83% higher. Six for six, always low -- read by re-running the instrument
at the moment of quoting, which is CB-EV-0015's correction applied for
the first time.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 02:24:13 +02:00
|
|
|
status: done
|
2026-08-03 02:24:57 +02:00
|
|
|
state_hub_workstream_id: "8a87aaec-1fd1-4faa-87d9-e10220adf45c"
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Purpose
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
structural tier M (changes how the loop constrains its own operation:
|
|
|
|
|
the chaos rate d4 → d8 and a second calibration
|
|
|
|
|
window, owed by CB-EV-0015 §5)
|
|
|
|
|
chaos d4 = 3 → no override
|
|
|
|
|
declared tier M
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Declaration 1 of the second chaos window** — opened by T04 below, at the
|
|
|
|
|
rate T04 sets. This declaration was rolled at the old d4, because the rate
|
|
|
|
|
changes when the decision lands, not retroactively.
|
|
|
|
|
|
|
|
|
|
## The defect: a finished game is indistinguishable from a crash
|
|
|
|
|
|
|
|
|
|
Reported: *"after some time i get an empty page back. I guess the game
|
|
|
|
|
crashes or ends but that is unclear as the ui disappears."*
|
|
|
|
|
|
|
|
|
|
Reproduced by driving a real game to completion over HTTP:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
move 5 accepted → ok
|
|
|
|
|
GET / → URLError: [Errno 111] Connection refused
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The game **ended normally** — 5 rounds, 30 commands — and everything it
|
|
|
|
|
produced went to the terminal:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
coalition [P2] score 0
|
|
|
|
|
coalition [P3] score 0
|
|
|
|
|
winners
|
|
|
|
|
game over — 30 commands, hash f6c890a65271
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The browser got nothing, because `next_choice` only accepts connections
|
|
|
|
|
*inside* a human decision point. When `play()` returns, `run_game` writes
|
|
|
|
|
the outcome to stdout and the process exits; the listener dies and the
|
|
|
|
|
page's post-`ok` reload is refused.
|
|
|
|
|
|
|
|
|
|
**The browser is a second-class client.** Every terminal outcome — the
|
|
|
|
|
result, the scores, the winners, and every error `run_game` can return —
|
|
|
|
|
is invisible to the only interface a player is actually using. A crash and
|
|
|
|
|
a win render identically: nothing.
|
|
|
|
|
|
|
|
|
|
This is the same defect class as CB-WP-0016's silent drop. The system
|
|
|
|
|
refuses to say what happened and the player is left to infer it.
|
|
|
|
|
|
|
|
|
|
## Task: serve the end of the game
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: CB-WP-0018-T01
|
2026-08-03 02:08:04 +02:00
|
|
|
status: done
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
priority: high
|
2026-08-03 02:24:57 +02:00
|
|
|
state_hub_task_id: "5654aae5-dc87-4621-8061-6492f626f1c1"
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
When `play()` returns — **`Ok` or `Err`** — the browser must be told, on
|
|
|
|
|
the page, in terms a player understands.
|
|
|
|
|
|
|
|
|
|
- **A win** shows the outcome the spectator projection already carries:
|
|
|
|
|
totals, threshold, coalitions, mastery, winners.
|
|
|
|
|
- **An error** shows that the game ended badly and why. `run_game`
|
|
|
|
|
currently returns `Err(String)` to a terminal nobody is reading.
|
|
|
|
|
- The final page must **not** auto-reload into a refused connection.
|
|
|
|
|
|
|
|
|
|
The listener has to outlive the game, which it does not today. Decide how
|
|
|
|
|
it ends — a timeout, an explicit close, or serving until interrupted — and
|
|
|
|
|
say why; a server that never exits is its own defect.
|
|
|
|
|
|
|
|
|
|
**Controls:** a test that plays a game to its end through the socket and
|
|
|
|
|
asserts the final GET returns a page naming the outcome, **not** a refused
|
|
|
|
|
connection. And the error path, driven by a game that fails, asserting the
|
|
|
|
|
reason reaches the page.
|
|
|
|
|
|
2026-08-03 02:08:04 +02:00
|
|
|
**Done 2026-08-03.** `Server::serve_end` plus `doc::ending`, wired into
|
|
|
|
|
both of `run_game`'s exits. Verified live: where the browser used to get
|
|
|
|
|
`Connection refused` it now gets an 8,998-byte page reading *"GROUND —
|
|
|
|
|
game over … 30 commands, hash f6c890a65271"* with the final table.
|
|
|
|
|
|
|
|
|
|
**How it ends:** it serves until the page posts `done` — the ending page
|
|
|
|
|
carries a *"close — I have read this"* control — with a 600 s linger as
|
|
|
|
|
the bound, so an abandoned tab cannot hold the process open and a player
|
|
|
|
|
reading the result is not raced by a timeout.
|
|
|
|
|
|
|
|
|
|
`document()` was split into `body()` and `move_section()` so the ending
|
|
|
|
|
shows the **same** table rather than a second rendering of it; two
|
|
|
|
|
renderings of one state is how they drift.
|
|
|
|
|
|
|
|
|
|
**The control had to be built twice, and the first one was worthless.**
|
|
|
|
|
`the_end_of_the_game_reaches_the_browser` calls `serve_end` directly —
|
|
|
|
|
and deleting the call from `run_game` left it **green**. It tested the
|
|
|
|
|
link and not the chain, which is CB-EV-0012's finding recurring
|
|
|
|
|
(*"every link was tested and the chain was not"*).
|
|
|
|
|
|
|
|
|
|
`a_real_game_played_to_its_end_leaves_the_ending_on_screen` runs the real
|
|
|
|
|
`play()` with a browser seat, drives a real game to its end over a real
|
|
|
|
|
socket, and requires the last page to be the ending. Under the same
|
|
|
|
|
mutation it goes red — and prints an **empty page**, which is exactly the
|
|
|
|
|
symptom that was reported.
|
|
|
|
|
|
|
|
|
|
A second control: a game that ended badly says why and draws **no** table,
|
|
|
|
|
because drawing a table for a game that never happened is the same lie the
|
|
|
|
|
empty page told.
|
|
|
|
|
|
|
|
|
|
**And a weak assertion of mine, caught by itself.** The first version
|
|
|
|
|
grepped the page for `location.reload`. The ending page reuses `SCRIPT`,
|
|
|
|
|
whose reload is guarded by `t.indexOf('ok') === 0`, and the ending
|
|
|
|
|
endpoint answers `closed` — so the grep would have forced a second script
|
|
|
|
|
to satisfy a test rather than a requirement. That is the source-text
|
|
|
|
|
control shape ADR-0010 D2 demoted. It now asserts the endpoint cannot
|
|
|
|
|
answer `ok`.
|
|
|
|
|
|
2026-08-03 02:00:21 +02:00
|
|
|
## The second report, and what it actually is
|
|
|
|
|
|
|
|
|
|
Reported: *"the cards I play by pulling them on a target will not be
|
|
|
|
|
removed, that is wrong i guess we will need a discard pile."*
|
|
|
|
|
|
|
|
|
|
**A discard pile already exists** — `solution_discard` on `GroundState`,
|
|
|
|
|
`SolutionDiscarded` removes the card from the hand and pushes it there,
|
|
|
|
|
and the page already renders `deck N remaining / discard …`. Building one
|
|
|
|
|
would have been building a thing that is there.
|
|
|
|
|
|
|
|
|
|
What the maintainer dragged were **action** cards. The five GROUND actions
|
|
|
|
|
are not cards and are correctly never consumed. Solution cards leave the
|
|
|
|
|
hand at **Resolve**, not at Select, because a selection is a face-down
|
|
|
|
|
commit.
|
|
|
|
|
|
|
|
|
|
But the report is pointing at something real. Measured over a live game:
|
|
|
|
|
|
|
|
|
|
| move | hand | discard |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| 1 · Investigate → problem-2 | 2 cards | none |
|
|
|
|
|
| 2 · Investigate → problem-3 | **3 cards** | none |
|
|
|
|
|
| 3 · Solve → problem-1 | 4 cards | none |
|
|
|
|
|
| 4 · Solve → problem-1 | **4 cards** | none |
|
|
|
|
|
| 5 · Solve → problem-1 | **4 cards** | none |
|
|
|
|
|
|
|
|
|
|
Investigate draws, correctly. **Solve was played three times and did
|
|
|
|
|
nothing, three times, in silence.** GR-A02's resolver `continue`s when the
|
|
|
|
|
problem is face-down, already claimed, denied, or when the seat holds no
|
|
|
|
|
card of the matching suit — and `legal_commands` offers Solve on every
|
|
|
|
|
face-up problem without consulting the hand, while the page offers it on
|
|
|
|
|
problem-1 which was still face-down.
|
|
|
|
|
|
|
|
|
|
**Whether that is a rule gap or intended is not this repo's call.** A
|
|
|
|
|
face-down commit you cannot fulfil is a plausible bluff in a commit/reveal
|
|
|
|
|
game with DARVO, and INTENT defers game semantics to `ground-game`. What
|
|
|
|
|
*is* this repo's call is that a move which provably does nothing is
|
|
|
|
|
offered, accepted, and never accounted for. That is the log's job (T02)
|
|
|
|
|
and the explanation's job (T03), and it is now the concrete case both are
|
|
|
|
|
measured against.
|
|
|
|
|
|
|
|
|
|
Raised for `ground-game`, not decided here: **should SOLVE be selectable
|
|
|
|
|
against a face-down problem, or against a suit the seat cannot match?**
|
|
|
|
|
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
## Task: a game log, and what to do next
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: CB-WP-0018-T02
|
2026-08-03 02:15:30 +02:00
|
|
|
status: done
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
priority: high
|
2026-08-03 02:24:57 +02:00
|
|
|
state_hub_task_id: "1ed3e87a-2a21-4b08-9a3a-2bbf69268dec"
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Requested: *"a game log about the events that have been generated and a
|
|
|
|
|
hint of what the next move/options are."*
|
|
|
|
|
|
|
|
|
|
The events exist — `validate` produces them and `record::to_scenario`
|
|
|
|
|
already turns them into a scenario file. The page shows none of them, so a
|
|
|
|
|
player sees state change with no account of why.
|
|
|
|
|
|
|
|
|
|
- **The log** is the event stream, in the recorder's vocabulary. Do not
|
|
|
|
|
invent a fourth phrasing: `cb-play`'s `describe()` exists precisely so
|
|
|
|
|
*"what the player reads is what the scenario file will say"*, and the
|
|
|
|
|
HTML renderer currently uses `{c:?}` Debug instead. Reuse it or say why
|
|
|
|
|
it cannot be reused.
|
|
|
|
|
- **The hint** is what the seat may do now, which is `legal` — already in
|
|
|
|
|
hand, already rendered as cards by CB-WP-0017. The hint is the *step*
|
|
|
|
|
context that makes those cards make sense: what the round is waiting
|
|
|
|
|
for, and what happens when it stops waiting.
|
|
|
|
|
|
|
|
|
|
**Control:** the log must be derived from the events the aggregate
|
|
|
|
|
produced, not re-narrated from the state. A log that describes the state
|
|
|
|
|
after the fact is a second implementation of the rules and will drift.
|
|
|
|
|
|
2026-08-03 02:00:21 +02:00
|
|
|
**The case it must handle**, from the measurement above: three SOLVEs that
|
|
|
|
|
produced no events at all. A log built only from events would show nothing
|
|
|
|
|
for them and reproduce the silence. So the log must distinguish *"this
|
|
|
|
|
command produced these events"* from *"this command produced none"* —
|
|
|
|
|
the second is the one the player needs and the harder one to render.
|
|
|
|
|
|
2026-08-03 02:15:30 +02:00
|
|
|
**Done 2026-08-03.** `bot::Journal` — a shared list of `Applied { actor,
|
|
|
|
|
command, events }` the driver appends to, via the new `play_journaled`.
|
|
|
|
|
`play` delegates to it with `None`, so nothing existing changed. The
|
|
|
|
|
journal exists because `BotGame.events` only appears *after* `play`
|
|
|
|
|
returns, which is no use to a page rendered mid-game.
|
|
|
|
|
|
|
|
|
|
The log is phrased with `record::to_step` — the recorder's vocabulary, so
|
|
|
|
|
what the player reads is what the scenario file will say — and every one
|
|
|
|
|
of the 29 `GroundEvent` variants now renders in words rather than `{:?}`.
|
|
|
|
|
From a live game:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
P1 select_action action=INVESTIGATE problem=2
|
|
|
|
|
→ P1 chose Investigate on problem 2
|
|
|
|
|
the round resolve
|
|
|
|
|
→ problem 2 turned face up
|
|
|
|
|
→ P1 drew a solution
|
|
|
|
|
→ step → Resolve
|
|
|
|
|
the round end_round
|
|
|
|
|
→ round 2 ended; P2 leads next
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**A command that produced no events says `no effect`**, which is the whole
|
|
|
|
|
point; the mutation that drops that branch goes red.
|
|
|
|
|
|
|
|
|
|
**An honest limitation.** The reported case — SOLVE doing nothing — is
|
|
|
|
|
*not* rendered as `no effect`, because the SOLVE is resolved inside the
|
|
|
|
|
system's `resolve` command, which does produce events for other seats. The
|
|
|
|
|
player now sees the selection and sees no claim follow it, which is a
|
|
|
|
|
large improvement on silence but is still an inference. Making it explicit
|
|
|
|
|
would mean the renderer deciding *why* a rule did nothing, which is a
|
|
|
|
|
second implementation of the rules — exactly what this task's control
|
|
|
|
|
forbids. Left as an inference deliberately, and owed to `ground-game` as
|
|
|
|
|
the question of whether the move should be offered at all.
|
|
|
|
|
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
## Task: say where a drop goes, and what it means
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: CB-WP-0018-T03
|
CB-WP-0018 T03/T04: explanations, and window 1's verdict
T03: input::describe writes a sentence per legal command; data-descs
carries them in step with data-targets; the ghost already following the
pointer shows the one for whatever legal target is under it, so the
explanation lands beside the target with no overlay layer to keep
aligned. ADR-0010 D1 binds -- the page renders it, never composes it.
Both mutations INITIALLY SURVIVED because the fixture's Attack card had
exactly one target, where an off-by-one shift and a truncation are both
no-ops. CB-EV-0014's lesson one level in: a fixture too thin to express
a failure is how the failure survives. Two attack targets now, both red.
T04: chaos rate d4 -> d8, window 2 open at 12 declarations, retiring if
an override changes nothing twice running. Window 1's condition was NOT
met -- both overrides changed the outcome -- so the mechanism is kept.
The weakest part of the decision is that it is a rate change argued from
n=2, so window 2 carries a falsifier: no override at all is evidence the
rate went too far, not that the mechanism is healthy.
InnerLoop.md hit 401 lines and the loadability gate fired; the rationale
moved to InnerLoopReference.md, structurally, per the standing precedent
that limits are not raised.
CB-WP-0017 settled at $9.48/40 against $5.19/23 reported mid-flight,
83% higher. Six for six, always low -- read by re-running the instrument
at the moment of quoting, which is CB-EV-0015's correction applied for
the first time.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 02:24:13 +02:00
|
|
|
status: done
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
priority: high
|
2026-08-03 02:24:57 +02:00
|
|
|
state_hub_task_id: "f603476c-8fc3-46c4-9897-361d243cec5d"
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Requested: *"an overlay arrow pointing to the droptarget element with an
|
|
|
|
|
explanation showing up besides it, when we drag on it."*
|
|
|
|
|
|
|
|
|
|
CB-WP-0017 marks every legal target. What it does not do is say what any
|
|
|
|
|
particular drop **means** — the player sees five outlined boxes and must
|
|
|
|
|
still guess which one does what.
|
|
|
|
|
|
|
|
|
|
So the explanation is the substance and the arrow is the delivery. Both
|
|
|
|
|
need the meaning to exist as data first, and **ADR-0010 Decision 1 binds
|
|
|
|
|
here**: the description of what `action-attack → seat-1` does must be
|
|
|
|
|
written by Rust into the page. The script may render it on hover; it may
|
|
|
|
|
not compose it.
|
|
|
|
|
|
|
|
|
|
**Controls:** every advertised target carries a description, and the
|
|
|
|
|
description a target shows is the one Rust wrote for *that* pair — a
|
|
|
|
|
mutation that shows a neighbouring pair's text must go red. The set
|
|
|
|
|
equality property from ADR-0010 D2 must still hold.
|
|
|
|
|
|
CB-WP-0018 T03/T04: explanations, and window 1's verdict
T03: input::describe writes a sentence per legal command; data-descs
carries them in step with data-targets; the ghost already following the
pointer shows the one for whatever legal target is under it, so the
explanation lands beside the target with no overlay layer to keep
aligned. ADR-0010 D1 binds -- the page renders it, never composes it.
Both mutations INITIALLY SURVIVED because the fixture's Attack card had
exactly one target, where an off-by-one shift and a truncation are both
no-ops. CB-EV-0014's lesson one level in: a fixture too thin to express
a failure is how the failure survives. Two attack targets now, both red.
T04: chaos rate d4 -> d8, window 2 open at 12 declarations, retiring if
an override changes nothing twice running. Window 1's condition was NOT
met -- both overrides changed the outcome -- so the mechanism is kept.
The weakest part of the decision is that it is a rate change argued from
n=2, so window 2 carries a falsifier: no override at all is evidence the
rate went too far, not that the mechanism is healthy.
InnerLoop.md hit 401 lines and the loadability gate fired; the rationale
moved to InnerLoopReference.md, structurally, per the standing precedent
that limits are not raised.
CB-WP-0017 settled at $9.48/40 against $5.19/23 reported mid-flight,
83% higher. Six for six, always low -- read by re-running the instrument
at the moment of quoting, which is CB-EV-0015's correction applied for
the first time.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 02:24:13 +02:00
|
|
|
**Done 2026-08-03.** `input::describe` writes a sentence per legal
|
|
|
|
|
command; `data-descs` carries them in step with `data-targets`; the ghost
|
|
|
|
|
already following the pointer shows the one for whatever legal target is
|
|
|
|
|
under it, so the explanation appears beside the target without an overlay
|
|
|
|
|
layer to keep aligned.
|
|
|
|
|
|
|
|
|
|
**Both mutations initially SURVIVED**, because the fixture's Attack card
|
|
|
|
|
had exactly **one** target — where an off-by-one shift and a truncation
|
|
|
|
|
are both no-ops. That is CB-EV-0014's lesson one level in: *a fixture too
|
|
|
|
|
thin to express a failure is how the failure survives*. The fixture now
|
|
|
|
|
offers two attack targets on purpose and both go red.
|
|
|
|
|
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
## Task: close the chaos change, and the evidence
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: CB-WP-0018-T04
|
CB-WP-0018 T03/T04: explanations, and window 1's verdict
T03: input::describe writes a sentence per legal command; data-descs
carries them in step with data-targets; the ghost already following the
pointer shows the one for whatever legal target is under it, so the
explanation lands beside the target with no overlay layer to keep
aligned. ADR-0010 D1 binds -- the page renders it, never composes it.
Both mutations INITIALLY SURVIVED because the fixture's Attack card had
exactly one target, where an off-by-one shift and a truncation are both
no-ops. CB-EV-0014's lesson one level in: a fixture too thin to express
a failure is how the failure survives. Two attack targets now, both red.
T04: chaos rate d4 -> d8, window 2 open at 12 declarations, retiring if
an override changes nothing twice running. Window 1's condition was NOT
met -- both overrides changed the outcome -- so the mechanism is kept.
The weakest part of the decision is that it is a rate change argued from
n=2, so window 2 carries a falsifier: no override at all is evidence the
rate went too far, not that the mechanism is healthy.
InnerLoop.md hit 401 lines and the loadability gate fired; the rationale
moved to InnerLoopReference.md, structurally, per the standing precedent
that limits are not raised.
CB-WP-0017 settled at $9.48/40 against $5.19/23 reported mid-flight,
83% higher. Six for six, always low -- read by re-running the instrument
at the moment of quoting, which is CB-EV-0015's correction applied for
the first time.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 02:24:13 +02:00
|
|
|
status: done
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
priority: high
|
2026-08-03 02:24:57 +02:00
|
|
|
state_hub_task_id: "590f5eb7-b2c9-468d-8db7-4dede4e95371"
|
Declare CB-WP-0018: the browser is a client, tier M
Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 22:59:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
CB-EV-0015 §5 recommended and did not make the change, on the grounds that
|
|
|
|
|
it alters how the loop constrains its own operation and was therefore owed
|
|
|
|
|
a tier-M declaration. This is it.
|
|
|
|
|
|
|
|
|
|
**Make it or reject it**, in `specs/InnerLoop.md` and `gates.toml`:
|
|
|
|
|
|
|
|
|
|
- rate **d4 → d8**;
|
|
|
|
|
- a **second window of 12** declarations;
|
|
|
|
|
- new retirement condition: *retire if an override changes nothing twice
|
|
|
|
|
running*.
|
|
|
|
|
|
|
|
|
|
The argument to test rather than assume: both overrides were informative
|
|
|
|
|
*because they were rare*. If that is right the rate should fall; if the
|
|
|
|
|
real driver was that they landed on passes with something to find, the
|
|
|
|
|
rate is irrelevant and the recommendation is wrong. Say which, and note
|
|
|
|
|
that n=2 is thin evidence for a rate change — including the possibility
|
|
|
|
|
that the honest answer is to keep d4 for another window and decide with
|
|
|
|
|
four data points instead of two.
|
|
|
|
|
|
|
|
|
|
Then `evidence/CB-EV-0016-*.md`:
|
|
|
|
|
|
|
|
|
|
- **What the maintainer's three reports have cost and bought**, now that
|
|
|
|
|
there are three in a row and every one found something no test did.
|
|
|
|
|
- **Whether stage 1 closes.**
|
|
|
|
|
- **Quote CB-WP-0017's cost by re-running the instrument**, not from
|
|
|
|
|
memory — CB-EV-0015 §6 found that quoting a remembered figure defeats
|
|
|
|
|
the rule even when the boundary is right, and this is the first pass
|
|
|
|
|
that can apply that correction.
|
CB-WP-0018 T03/T04: explanations, and window 1's verdict
T03: input::describe writes a sentence per legal command; data-descs
carries them in step with data-targets; the ghost already following the
pointer shows the one for whatever legal target is under it, so the
explanation lands beside the target with no overlay layer to keep
aligned. ADR-0010 D1 binds -- the page renders it, never composes it.
Both mutations INITIALLY SURVIVED because the fixture's Attack card had
exactly one target, where an off-by-one shift and a truncation are both
no-ops. CB-EV-0014's lesson one level in: a fixture too thin to express
a failure is how the failure survives. Two attack targets now, both red.
T04: chaos rate d4 -> d8, window 2 open at 12 declarations, retiring if
an override changes nothing twice running. Window 1's condition was NOT
met -- both overrides changed the outcome -- so the mechanism is kept.
The weakest part of the decision is that it is a rate change argued from
n=2, so window 2 carries a falsifier: no override at all is evidence the
rate went too far, not that the mechanism is healthy.
InnerLoop.md hit 401 lines and the loadability gate fired; the rationale
moved to InnerLoopReference.md, structurally, per the standing precedent
that limits are not raised.
CB-WP-0017 settled at $9.48/40 against $5.19/23 reported mid-flight,
83% higher. Six for six, always low -- read by re-running the instrument
at the moment of quoting, which is CB-EV-0015's correction applied for
the first time.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 02:24:13 +02:00
|
|
|
|
|
|
|
|
**Done 2026-08-03.**
|
|
|
|
|
[CB-EV-0016](../evidence/CB-EV-0016-the-browser-is-a-client.md). `make
|
|
|
|
|
all` exits 0.
|
|
|
|
|
|
|
|
|
|
- **Chaos rate d4 → d8, window 2 open at 12 declarations**, retiring if an
|
|
|
|
|
override changes nothing twice running. Window 1's condition was not
|
|
|
|
|
met — both overrides changed the outcome — so the mechanism is kept.
|
|
|
|
|
**The weakest part of the decision is that it is a rate change argued
|
|
|
|
|
from n=2**, and window 2 therefore carries a falsifier: no override at
|
|
|
|
|
all is evidence the rate went too far.
|
|
|
|
|
- The rationale moved to `InnerLoopReference.md` because `InnerLoop.md`
|
|
|
|
|
hit 401 lines and the loadability gate fired — fixed structurally, per
|
|
|
|
|
the standing precedent that limits are not raised.
|
|
|
|
|
- **CB-WP-0017 settled at $9.48/40** against $5.19/23 reported mid-flight,
|
|
|
|
|
83% higher. Six for six, always low. Read by re-running the instrument
|
|
|
|
|
at the moment of quoting, which is CB-EV-0015 §6's correction applied
|
|
|
|
|
for the first time.
|