Repository navigation
Description
Problem
The reusable pm-dispatch composite actions document a numeric priority form they can never deliver (main 65d87df, actions added in PR #2678):
.github/actions/pm-dispatch-queue/action.yml— inputpriority: "Optional priority: 10-90 or critical|high|normal|low.".github/actions/pm-dispatch-start/action.yml— same documented input.
Both actions build the request payload with jq --arg (queue action.yml payload step; start action.yml payload step):
payload="$(jq -n --arg priority "$INPUT_PRIORITY" ... \
'{...} + (if $priority != "" then {priority: $priority} else {} end)')"--arg always produces a JSON string, so a caller passing the documented numeric form sends {"priority": "50"}. The server's resolvePriority (pm-stack/dispatch/src/validate.ts:28-48) only accepts a string that is a scale name (critical|high|normal|low); a numeric string falls into the name lookup, misses, and throws ValidationError → HTTP 400 priority: unknown name "50". The numeric path (integer 10-90, snapped to the scale) is only reachable from raw API callers who send a real JSON number — never through the Actions, which are the sanctioned cross-repo entry point under the grants mesh.
So any workflow in any allowlisted repo that follows the action documentation and passes priority: "10" … "90" gets a hard 400 from both /v1/tasks and /v1/sessions, while the name form works.
Evidence (verified this run)
Laptop probe importing the real validate.ts (md5 c1f61d5acf5c85da71de798f4c7056b8, identical in the sandbox clone at main 65d87df and the laptop primary; probe at ~/git/fleet/probe-2026-10-30-laneB-priority/ on the laptop), feeding each parser the exact payload shape the actions construct:
A priority-input "50" (documented numeric form, via action) parseTaskRequest: THROW ValidationError status=400 msg=priority: unknown name "50" (use critical|high|normal|low or a number 10-90)
A priority-input "50" (documented numeric form, via action) parseSessionRequest: THROW ValidationError status=400 msg=priority: unknown name "50" (...)
B priority-input "10" (documented critical numeric, via action) parseTaskRequest: THROW ValidationError status=400 ...
B priority-input "10" (documented critical numeric, via action) parseSessionRequest: THROW ValidationError status=400 ...
C priority-input "high" (documented name form, via action) parseTaskRequest: OK priority=20
C priority-input "high" (documented name form, via action) parseSessionRequest: OK priority=20
D direct API numeric 50 (no action) parseTaskRequest: OK priority=50
D direct API numeric 50 (no action) parseSessionRequest: OK priority=50
E omitted priority (via action) parseTaskRequest: OK priority=40
E omitted priority (via action) parseSessionRequest: OK priority=40
No in-repo workflow passes priority to the actions yet (grep over .github/workflows/), so this bites the next caller — most likely another allowlisted repo following the published action docs — rather than a current in-repo call site.
Why it matters
The actions are the documented, OIDC-authenticated way for any allowlisted repo to enqueue or launch dispatch work, and their input contract advertises the queue's full 10-90 scale. A caller using it gets an opaque 400 ("unknown name") for a value the docs told them was valid, with the failing layer (action jq typing vs server validation) not obvious from either side alone.
Acceptance criteria
- Passing any documented priority form through either composite action — numeric string
"10"-"90"and the names — produces a request the server accepts, resolving to the same scale value a raw API caller gets for the numeric form. - The fix layer is pinned by triage: actions emit a JSON number for numeric input (e.g. a numeric branch in the jq construction), or the server accepts numeric strings in
resolvePriority— one canonical behaviour, tested at that layer. (If the server route is chosen, note it also changes raw-API behaviour for"50"string callers; if the action route, both actions must change identically.) - Tests pin the through-the-action payload for a numeric priority (payload-shape test or a validate test fed the action-constructed JSON), plus the existing name/omitted cases.
- The action input descriptions and the server contract agree after the fix; existing dispatch tests still pass.
Related: #2668 (dispatch launch-pipeline boundary-validation design) — this is a concrete instance of a request the boundary mis-classifies, filed separately because the defect is in the action/server contract, not the launch pipeline ordering.
Activity
dezren39 commentedon Oct 30, 2026
🤖 Agent note · state: filed
8 remaining items
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
/home/user/git/fleet/4416-2679-numeric-priority, branchqueue/4416-2679-numeric-priority, local commit1c8061768; push commit, revalidate ownership, and open PR. Remote branch currently contains only the base commit.bun test: 59 passed. No PR opened.dezren39 commentedon Oct 31, 2026
🤖 Agent note · picked up
fix(dispatch): resolvePriority accepts numeric strings (#2679) (#3154)
dezren39 commentedon Oct 31, 2026
🤖 Agent note · done