Skip to content

Stop a finished colony taking answers it can never deliver - #114

Merged
ParallelEntrepreneur merged 1 commit into
mainfrom
fix/answer-after-end
Sep 18, 2026
Merged

ParallelEntrepreneur merged 1 commit into
mainfrom
fix/answer-after-end

Conversation

@ParallelEntrepreneur

Copy link
Copy Markdown
Collaborator

An answer could still be submitted after a colony had ended, and the card then sat there saying it was sending — for an agent that is gone.

Three defects, each enough on its own

1. The card is a form. The submit button was disabled, but Enter in any field submits a form and a disabled button does not stop that. submit() now refuses unless answering is possible, which is where the guard belonged.

2. The inputs stayed live, so the card invited an answer it could not send. The fieldset is disabled with the rest now.

3. It said the wrong thing. !canAnswer always rendered "Reconnecting to the colony…" — including when the colony had finished and there was nothing to reconnect to. It now distinguishes disconnected from ended.

And why it looked like it was working

client_command dropped the command silently when the colony was not live (sessions.rs). The browser had already marked the question as sending — that is the spinner — and nothing ever came back to clear it.

It now answers with the session instead, so a client whose view is stale corrects itself and stops offering to answer. The predicate has a name and a test:

fn accepts_commands(status: SessionStatus) -> bool { status.is_live() }

Publishing is included in the refusal: by then the microVM is already gone.

Verified in the browser

Against the mock, stopping a colony with its question card open:

Footer "This colony has finished, so the agent cannot be answered."
Submit button disabled
Controls 8 of 8 effectively disabled (:disabled via the fieldset)
Clicking a radio no change
Submitting the form the way Enter does nothing sent, no spinner

Before the fix the footer read "Reconnecting to the colony…" and that last row sent an answer into nothing.

cargo test -p colonizer-harness    147 passed, 0 failed   (1 new)
cargo check                        0 warnings
npx tsc --noEmit                   clean

One note on the check I ran first: input.disabled reads false for controls inside a disabled <fieldset>, because the property reflects the element's own attribute rather than inherited state. matches(':disabled') is the honest check, and by it all eight are disabled.

An answer could still be submitted after a colony had ended, and the card then
sat there saying it was sending — for an agent that is gone.

Three things were wrong, and each was enough on its own.

The submit button was disabled, but the card is a form: Enter in any field
submits it, and a disabled button does not stop that. `submit()` now refuses
unless answering is possible, which is where the guard belonged all along.

The inputs stayed live, so the card invited an answer it could not send. The
fieldset is now disabled with the rest.

The card said "Reconnecting to the colony…" whenever it could not answer,
including when the colony had finished and there was nothing to reconnect to.
It now distinguishes the two, and says the colony has finished.

The harness dropped such a command silently, which is what left the card
spinning: the browser had marked the question as sending and nothing ever came
back. It now answers with the session instead, so a client whose view is stale
corrects itself and stops offering to answer. The predicate has a name and a
test: commands only reach a colony whose microVM is up — publishing included,
since by then the VM is already gone.

Checked in the browser against the mock: stopping a colony with its question
card open leaves the card saying the colony has finished, all eight controls
disabled, a radio unresponsive to a click, and submitting the form the way Enter
does sends nothing.
@ParallelEntrepreneur
ParallelEntrepreneur merged commit 82f03cd into main Sep 18, 2026
@ParallelEntrepreneur
ParallelEntrepreneur deleted the fix/answer-after-end branch September 18, 2026 04:21
ParallelEntrepreneur added a commit that referenced this pull request Sep 23, 2026
An answer could still be submitted after a colony had ended, and the card then
sat there saying it was sending — for an agent that is gone.

Three things were wrong, and each was enough on its own.

The submit button was disabled, but the card is a form: Enter in any field
submits it, and a disabled button does not stop that. `submit()` now refuses
unless answering is possible, which is where the guard belonged all along.

The inputs stayed live, so the card invited an answer it could not send. The
fieldset is now disabled with the rest.

The card said "Reconnecting to the colony…" whenever it could not answer,
including when the colony had finished and there was nothing to reconnect to.
It now distinguishes the two, and says the colony has finished.

The harness dropped such a command silently, which is what left the card
spinning: the browser had marked the question as sending and nothing ever came
back. It now answers with the session instead, so a client whose view is stale
corrects itself and stops offering to answer. The predicate has a name and a
test: commands only reach a colony whose microVM is up — publishing included,
since by then the VM is already gone.

Checked in the browser against the mock: stopping a colony with its question
card open leaves the card saying the colony has finished, all eight controls
disabled, a radio unresponsive to a click, and submitting the form the way Enter
does sends nothing.

Co-authored-by: Nick <40026523+Nick-CHI@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant