flaky(runtime-host): WorkHub delegation races the automatic Session title through the candidate-set identity
- Dominant language
- TypeScript
- Stars
- 5.4k
- Forks
- 502
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 716
Description
## What happened
`WorkHub correction replaces its link without stopping a shared manual Turn` (`packages/runtime-host/src/__tests__/execution-composition.test.ts:689`) fails intermittently on a clean `main` checkout. It is the most frequent Runtime Host flake on this machine: **10 of 13 full-suite runs** failed on it, and it reproduces in focused repetitions too (2 of 6, then 1 of 3).
The assertion that fails is `assert.equal(delegated.ok, true)` on the `workhub.coordination.act` call. The rejection is not a timeout:
```
{"ok":false,"error":{"code":"operation_conflict",
"message":"WorkHub Session candidates changed; refresh before delegating"}}
```
## Root cause: the candidate-set identity includes the Session name, and the automatic title lands asynchronously
`candidateSet` (`packages/runtime-host/src/server/workhub-coordination-action-gate.ts:960`) digests each eligible Session's `id`, `name`, workspace projection, `status` and `updatedAt` into `candidateSetId`. `workhub.coordination.act` rejects with `operation_conflict` when the id it is handed no longer matches (`:504`).
The test starts a manual Turn, reads the candidate set, then delegates into it. Starting the Turn also triggers the automatic Session title, which commits on its own schedule. Dumping both candidate sets at the moment of the rejection shows exactly one field moved, and it is the name:
```
BEFORE sha256:28184d9a… [{ id: 7f5f66ee…, name: "New Chat", status: running, updatedAt: 1788529087769 },
{ id: 232443e9…, name: "New Chat", status: active, updatedAt: 1788529087758 }]
AFTER sha256:daa2d376… [{ id: 7f5f66ee…, name: "__e2e_hold_open__", status: running, updatedAt: 1788529087769 },
{ id: 232443e9…, name: "New Chat", status: active, updatedAt: 1788529087758 }]
```
`7f5f66ee…` is the source Session. `updatedAt` is byte-identical across the two reads; the title commit is the whole difference. Whether the test passes is therefore decided by whether the title lands before or after the `act` call.
## Beyond the test
The conflict domain looks wider than the decision it protects. A delegation cares which Sessions are eligible and what state they are in; it does not depend on what any of them is called. As written, any automatic title committing anywhere in the workspace invalidates every in-flight WorkHub delegation, so a user who opens WorkHub and clicks delegate can lose the race to a title commit on an unrelated Session and be told to refresh. That is the same race the test loses, just with a human in it.
Two directions, and which one is right is a maintainer call:
1. Narrow the identity to the fields a delegation actually depends on — Session set, eligibility and status — and leave cosmetic fields such as `name` out of it. The candidate list would still be re-read; only the conflict would stop firing on a rename.
2. Keep the identity as it is and make the caller tolerate `operation_conflict` by re-reading candidates and retrying once, which is what the message already tells clients to do.
The test change follows from whichever is chosen: under (1) nothing is needed; under (2) the test should settle the title before reading candidates rather than racing it.
## How to reproduce
```bash
npm ci
npm --workspace @maka/runtime-host run build
# full suite; fails on this test in most runs
npm run test:dist --workspace @maka/runtime-host
# focused; fails in roughly one run in three
node --test \
--test-name-pattern="WorkHub correction replaces its link without stopping a shared manual Turn" \
packages/runtime-host/dist/__tests__/execution-composition.test.js
```
The candidate-set dump above comes from printing `workhub.coordination.candidates` again inside the failure branch; the harness is not committed.
## Environment
- Maka commit: `a9307d005` (source build), also seen on `4ed6255f2`
- OS: macOS, Darwin 25.6.0, arm64, 10 cores
- Surface: Runtime Host
- Node.js: v24.19.0
## Additional context
Found while investigating #4776, which is a different pair of tests; this one is unrelated to that fix and is filed separately as promised in #4784. #4776's own two tests did not fail once here in 42 focused repetitions and 19 full-suite runs.
_Analysis produced with Claude Code; the runs, the candidate-set dump and this report were reviewed by me._
Contributor guide
Assessment
This issue has not been assessed yet.