docs(plans): decision 79, CHAT-01 engine-exit stop mode as row 52

Row 51 needs a CHAT-01 rule changed to record `stopped` at engine exit.
The engine-exit proof moves to its own row with a CHAT-01 amendment and
contract review; row 51 keeps the crash window, the close PID fix and
the mutant tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-10 00:21:21 -05:00
co-authored by Claude Opus 5.5
parent 2edee47b12
commit 5a7d5f1c2a
2 changed files with 124 additions and 14 deletions
+31
View File
@@ -1617,3 +1617,34 @@ which stay with him. Each item names who decided it and what happened.
- S6's gate uses a scratch business with no tracker, so it doesn't wait
on the tasks.mosaicstack.dev vs tasks.woltje.com ruling. Dogfooding
against the live mosaic-stack business does.
79. **CHAT-01 gets an `engine-exit` stop mode; the EOF proof moves to row
52 (2026-10-10).** Dewey stopped row 51 (#1537) at rev 292. Recording
`stopped` at engine exit needs a CHAT-01 rule changed:
`cohortProof.stop` must name a stop, no stop mode means "the engine
exited", and `confirm-stopped` (`check.mjs` line 337) accepts only a
confirmed `force-stop`. Ruling: amend CHAT-01, and don't narrow the
brief to evidence-only.
- Why: every conversation that ends on its own otherwise keeps a
scope and an idle shim until someone force-stops it. The force-stop
confirmation guards a destructive act, and at EOF the controller
kills nothing; it reads the cohort and releases only if it is empty.
The proof stays the cohort and effects observation, so "EOF does not
prove death" holds.
- Authority: CHAT-01 is a reviewed draft. Jason approved the drafting
(#1507), and Q21 covers publishing reviewed, green refactor work.
An additive stop mode with its own contract review is a design call
like item 30's C-5 move, so it's mine. It authorizes no deployment,
and it changes no role, policy or credential.
- Shape: one new row 52, owner Dewey, reviewers Darkwing (CHAT-01's
author) and Filbert, after row 51 because the two share
`cohort.mjs` and `controller.mjs`. The CHAT-01 commit comes before
the conversation code, and each approval names all four CHAT-01
hashes. Brief: `docs/plans/2026-10-10_cohort-release-follow-ups.md`,
section "CHAT-01 engine-exit stop and release at engine exit".
- Row 51 keeps the crash window and retry, the close PID fix, and the
relok, closeany, noprooffkind and nopush tests. Its brief section
drops the engine-exit item and its two tests, re-pinned by
`queue set 51 brief`.
- Dewey's rejected workarounds stay rejected: labelling the EOF stop
`force-stop` without a confirmation, and `stopped` on the claim while
the binding stays `uncertain`.
@@ -1,7 +1,10 @@
# Conversation cohort: release follow-ups after row 50 (2026-10-10)
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`
and amends no section of the slice 1 brief. One row.
and amends no section of the slice 1 brief. Two rows. Row 51 was briefed
with the engine-exit proof in it. Dewey found that the proof needs a
CHAT-01 rule changed, so lead decision 79 (2026-10-10) moved it to row 52,
which carries the CHAT-01 amendment and its own contract review.
## Cohort release follow-ups: engine exit, crash window and close
@@ -45,14 +48,8 @@ Owner: Dewey. Reviewers: Darkwing and Filbert.
### What ships
- Engine exit. On EOF the controller runs the same cohort proof the force
stop uses. If the cohort reads empty, it records `stopped` with that
`cohortProof` and releases the scope. Nothing is killed, so no client
confirmation is needed. If the cohort isn't empty, the binding stays
`uncertain` as today. Before writing code, the packet names every
claim-protocol rule this touches (K6 included). If one of them needs a
change to a rule written in the slice 1 brief, stop and report to Sage
first.
- Engine exit isn't in this row. It moved to row 52 (decision 79), and
this row leaves the EOF path as row 50 left it.
- Crash window and retry. The start and recover paths release a claim
recorded `stopped` with a `cohortProof` whose scope is still listed. A
release that ended `unavailable` or `still listed` is retried there,
@@ -61,9 +58,6 @@ Owner: Dewey. Reviewers: Darkwing and Filbert.
signal the recorded PID, or it checks that the PID is still the same
engine before it does. The packet says which and why.
- Tests:
- an engine that exits on its own leaves no unit and records `stopped`;
- an engine that exits while another member still runs stays
`uncertain`, and nothing is released;
- a restart after a crash between `stopped` and the release removes the
unit;
- close after a proven stop doesn't signal a PID it can't show is the
@@ -72,11 +66,96 @@ Owner: Dewey. Reviewers: Darkwing and Filbert.
### Out of scope
The force-stop phases, the pgroup fallback, and the release polling cost
(Darkwing note 2).
The engine-exit proof (row 52), the force-stop phases, the pgroup
fallback, and the release polling cost (Darkwing note 2).
### Gate
Darkwing and Filbert approve on the row's issue. The conversation and
webui node suites and every `scripts/test-*.sh` green on Sage's gate rerun.
No `mosaic-chat-*` scope left after the suites.
## CHAT-01 engine-exit stop and release at engine exit
### Problem
A normal engine exit leaves the scope and an idle shim, one per
conversation that ends on its own (row 50 deviation, comment 27054). The
fix is the cohort proof at EOF, but CHAT-01 has no way to record it
(Dewey, row 51, rev 292):
- `cohortProof.stop` must name a stop record, and a stop's `mode` is
`interrupt`, `force-stop` or `revocation`. None of them means the engine
exited.
- `confirm-stopped` in `docs/plans/chat-01/check.mjs` refuses any stop
whose mode isn't `force-stop`, and a force stop needs exact client
confirmation (K6). So every route to `stopped` today runs through a
confirmed force stop.
The confirmation guards a destructive act. At EOF the controller kills
nothing: it reads the cohort, and it releases only if the cohort is empty.
Labelling that a force stop without a confirmation, or recording `stopped`
on the claim while the binding stays `uncertain`, would break a rule
instead of changing it. This row changes it in the contract first.
### Owner and reviewer
Owner: Dewey. Reviewers: Darkwing (CHAT-01's author) and Filbert. As the
CHAT-01 README requires, each approval names all four current hashes of
`docs/plans/chat-01/`.
### Files owned
- `docs/plans/chat-01/contracts.schema.json`, `check.mjs`, `fixtures.json`
and `README.md`
- `packages/conversation/src/cohort.mjs`, `packages/conversation/src/controller.mjs`
- `packages/conversation/src/shim.mjs`, only if the EOF proof needs a shim op
- `packages/conversation/tests/` and `packages/conversation/README.md`
### What ships
- CHAT-01, in its own commit before any conversation code:
- Stop mode `engine-exit`. The server starts it, as it does a
revocation (`request: null`). It needs no confirmation, since nothing
is signalled.
- Starting one closes admission and takes the one escalation slot
(H10). A force-stop confirmation issued before it goes stale (H17). A
request already dispatched to the engine ends with an `uncertain`
receipt, never an invented outcome.
- `confirm-stopped` accepts `engine-exit` under the same `stopped(w, s)`
check as `force-stop`: complete membership, the epoch and verified
effects.
- Recover after an `engine-exit` stop still needs its own exact
confirmation, bound to that stop's ID (K6, K17, K18).
- The README rule "SIGTERM, EOF, abort acknowledgment or idle does not
prove death" stays. EOF starts the observation, and only the cohort
and effects observations prove. K15 (an unreadable `engine` cgroup is
absent, never empty) and K2 (pgroup never proves) are unchanged.
- Fixtures: an empty cohort reaches `stopped`. A non-empty or unreadable
cohort stays `uncertain`. A pending force-stop confirmation goes stale,
and recover without a confirmation is refused.
- Conversation: on EOF the controller runs the same cohort proof the force
stop uses, with `hello`, `events` and `members` only, and no freeze or
kill. If the cohort reads empty, it records the `engine-exit` stop
`stopped` with that `cohortProof` and releases the scope through
`#releaseScope`. If the cohort isn't empty, the binding stays
`uncertain`, as it does today, and nothing is released.
- Tests:
- an engine that exits on its own leaves no unit and records `stopped`;
- an engine that exits while another member still runs stays
`uncertain`, and nothing is released;
- an EOF proof racing a client force stop takes one escalation slot,
not two.
### Out of scope
Any other change to CHAT-01, CHAT-01C or the slice 1 brief. If the work
needs one, stop and report to Sage.
### Gate
Darkwing and Filbert approve on the row's issue, each naming the four
CHAT-01 hashes. `node docs/plans/chat-01/check.mjs` passes. The
conversation and webui node suites and every `scripts/test-*.sh` are
green on Sage's gate rerun, and no `mosaic-chat-*` scope is left after the
suites.