Skip to content

flaky(runtime-host): WorkHub delegation races the automatic Session title through the candidate-set identity #4785

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions