Repository navigation
Queen wiring: record the exit reason of every dispatch in the activity event and run the spec's conformance rows #1708
Copy link
Copy link
Open
Labels
Description
Problem
On 2026-10-07, 33 of 51 finished dispatches in /queen/public-activity ended as ended unexpectedly (cause undetermined) (gHashTag/t27#7494). queen-dispatch.ts sees the stream close without a completion frame and writes no reason. A finished event exposes only id, kind, issue, title, at, state. It has no provider, model, duration, agent or last frame. So nobody can tell an outage from a hung turn from a dropped connection, and no retry rule can tell them apart either.
Spec
gHashTag/t27#8043 adds specs/queen/dispatch_exit.t27 (module QueenDispatchExit):
exit_reason(completion, error_frame, http_class, elapsed, timeout, lease_held, heartbeat_age)returns one of NORMAL 0, SHUTDOWN 1, KILLED 3, NOCONNECTION 6, TIMEOUT 7, PROVIDER_ERROR 8 or UNKNOWN 9. Codes 0, 1, 3 and 6 are actors.t27's X_* codes.restart_decision(reason, http_class, runs, streak)returns NONE 0, NOW 1, LATER 2 or GIVE_UP 3.restart_wait_secondsgives the wait for LATER.test conformance_rowsis 24 rows, one assert per row, mapping inputs to a code.
Requirements
- FR-001: at the end of every dispatch, the host computes the exit reason with the spec's table, using the observations it already has: completion frame seen, kind of the last error frame, the provider's last HTTP status class, elapsed against the timeout, whether the task lease is held, and the age of the last heartbeat.
- FR-002: the
finishedevent in/queen/public-activitycarries the reason code, plus the observation fields it was computed from: provider, model, duration seconds, last frame kind and HTTP status class. These must contain no secrets and no prompt text. - FR-003: a host test runs all 24 rows of
conformance_rowsagainst the host classifier and fails on any mismatch. The rows are the spec's, copied by a generator or read from the spec. They are not retyped by hand. - FR-004: the retry path uses
restart_decision. This applies only after one hour of reasons is measured, because Queen scheduler: 31 of 70 bees idle because no issue is eligible; 33 of 51 dispatches ended without a completion frame t27#7494 requires measuring before any retry change.
Success criteria
- Every
finishedevent in/queen/public-activityhas a reason code.stateno longer readscause undetermined. - The conformance test passes with 24 of 24 rows.
- In one hour of events, UNKNOWN is under 5% of finished dispatches.
Boundary
- The code lives in gHashTag/BrowserOS (trios/agent-server: the queen-dispatch.ts finish path, the public-activity serializer, one new test file); the owner merges there.
- Do not edit specs/queen/dispatch_exit.t27 from the wiring change; a disagreement with a row is a new issue here.
Refs gHashTag/t27#7494, gHashTag/t27#8043
User Scenarios
- Given a Queen dispatch runs to completion, When the host finishes the dispatch, Then the
finishedevent written to/queen/public-activitycontains areason_codefield (0, 1, 3, 6, 7, 8, or 9) computed byexit_reasonfrom the observed completion frame, last error frame kind, provider HTTP status class, elapsed vs timeout, lease held, and heartbeat age. - Given a dispatch ends without a completion frame, When the host serializes the
finishedevent, Then the event also includesprovider,model,duration_seconds,last_frame_kind, andhttp_status_classfields with no secrets or prompt text. - Given the spec
specs/queen/dispatch_exit.t27defines 24conformance_rows, When the host test suite runs, Then all 24 rows are executed against the host'sexit_reasonimplementation and any mismatch fails the test.
Success Criteria
grep -r 'reason_code' /queen/public-activity --include='*.json' | wc -lequals the total number offinishedevents (every event has a reason code);grep 'cause undetermined' /queen/public-activity --include='*.json' | wc -lreturns0(exit 0)t27c test specs/queen/dispatch_exit.t27 --host(or the project's equivalent test command) runs 24 conformance rows and exits withexit 0- Over a one-hour window of
finishedevents,jq '[.[] | select(.reason_code==9)] | length / ([.[]] | length) * 100' /queen/public-activity/*.jsonyields a value< 5(UNKNOWN under 5%)
Reactions are currently unavailable
Activity
[-]BrowserOS wiring: record the exit reason of every Queen dispatch in the activity event and run the spec's conformance rows[/-][+]Queen wiring: record the exit reason of every dispatch in the activity event and run the spec's conformance rows[/+]