Skip to content

XERK-515 [Qwen I]: a board ticket can run on the qwen runtime - #547

Merged
xerhab merged 3 commits into
mainfrom
XERK-515
Aug 29, 2026
Merged

XERK-515 [Qwen I]: a board ticket can run on the qwen runtime#547
xerhab merged 3 commits into
mainfrom
XERK-515

Conversation

@xerhab

@xerhab xerhab commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

XERK-515 [Qwen I] — a board ticket can run on the qwen runtime

Extends the per-ticket board runtime pin (previously claude/dsh, XERK-473 [I]) to also accept
qwen (Qwen Code, XERK-504), so a board ticket dispatches to the qwen runtime through the same
spawnTicket path. The runtime choice is presentational plumbing over the existing spawn path — the
dsh [I] analogue, mirrored field-for-field.

Hub (turma/server.js)

  • POST /api/jira/<siteKey>/<issueKey>/runtime accepts {runtime:"qwen"}, gated by the new
    orgOffersQwen (the orgOffersDsh twin). setTicketRuntime needed no body change — only
    claude/{auto} release, so a qwen pin stores/carries exactly like a dsh one and rides the
    spawnTicket command as agentType.
  • findTicketHost generalises its single wantDsh gate into a wantRuntime string + a
    runtimeOfferedBy(a) check (dshAvailable/qwenAvailable), so a qwen-pinned ticket routes only
    to a qwen.available host — checked ahead of capacity so "no host offers qwen" reads as blocked
    (ages out) not full. A pinned host lacking qwen is reported, never routed around.

Board (turma/public/board.js + board.html; glasses board.cjs kept byte-identical)

  • mergeSites gains qwenAvailable; the Runtime picker a "Qwen Code" option gated on it;
    prettyRuntime("qwen") → "Qwen Code". An existing qwen pin is always carried back so it stays
    releasable after the last qwen host leaves.

Android (core/Board.kt, ui/BoardScreen.kt) — Web ⇄ Android parity

  • BoardSite.qwenAvailable + qwenBySite (gated on Runtime.QWEN_ENABLED),
    runtimeEditable(dshAvailable, qwenAvailable, pin) (signature change — every caller updated), and
    the RuntimePicker qwen row. PARITY.md updated.

Agent side — unchanged (the point of the [A]/[B] shape)

spawn_ticket already forwards agentType to spawn(), resolve_agent_type already validates
qwen, and _launch_tmux already dispatches to _launch_qwen (which appends the ticket-branch
directive + delivers the ticket prompt). No new launch code. Collectors, the two tracker writes and
the _board_column mirrors are runtime-agnostic and untouched.

Note: QWEN_ENABLED ships False fleet-wide (and Runtime.QWEN_ENABLED=false on Android), so the
whole qwen surface is inert in production until a later fleet-enable milestone — verified below in
both states.

Verification

  • Unit tests: node --test turma/tests/server.test.js turma/tests/board.test.js808/808 pass
    (new qwen /runtime + spawnTicket + findTicketHost cases in server.test.js; qwen runtime
    picker cases in board.test.js; qwen board cases in BoardTest.kt).
  • QA agent verdict: PASS, no defects. It drove the real hub over HTTP in both kill-switch
    states:
    • QWEN_ENABLED off (standalone hub): a host reporting qwen:{available:true} is served
      {available:false} on /api/agents; a qwen pin is refused 400 — the surface is fully inert.
    • QWEN_ENABLED on (__setQwenEnabled(true)): {runtime:"qwen"} → 200, pin stored, rides
      ticketRuntimes; the queued spawnTicket carried agentType:"qwen"; findTicketHost routed a
      qwen ticket only to a qwen host and returned a blocked (not full) 503 when none offered it;
      gpt → 400 "runtime must be claude, dsh or qwen"; unknown org → 404.
    • Mutation-probed all four new decision arms (break orgOffersQwen, the findTicketHost qwen
      arm, the /runtime org-check, the /runtime value check) → each turns a test red; tree restored.
  • Glasses vendored copy byte-identical (cmp turma/public/board.js glasses/src/vendor/board.cjs).

Not verified (out of scope / no tooling in the pod)

  • Android/Kotlin at runtime — no gradle/emulator available; the diff is a mechanical 1:1 parity
    port with matching BoardTest.kt cases, but not run here. Covered by android-ci.yml.
  • A live qwen ticket launchQWEN_ENABLED is False and qwen isn't installed, so no launch is
    reachable; the agent side is unchanged from [Qwen A]/[B].

Docs: [Qwen I] section added to .claude/rules/qwen.md; turma-board.md, agent-board.md,
android/PARITY.md updated.

xerhab added 3 commits August 28, 2026 21:50
Extend the per-ticket runtime pin (XERK-473 dsh) to accept qwen, so a board
ticket dispatches to the Qwen Code runtime through the same spawn path. The
runtime choice is presentational plumbing over the existing spawnTicket agentType.

Hub (turma/server.js):
- POST /api/jira/<siteKey>/<issueKey>/runtime accepts {runtime:qwen}, gated by
  the new orgOffersQwen (the orgOffersDsh twin); setTicketRuntime unchanged.
- findTicketHost generalises its wantDsh gate into a per-runtime wantRuntime plus
  runtimeOfferedBy check, so a qwen-pinned ticket routes only to a qwen.available
  host - blocked (not full) when none offers it, checked ahead of capacity.

Board (board.js + board.html, vendored board.cjs kept byte-identical):
- mergeSites gains qwenAvailable; the Runtime picker a Qwen Code option gated on
  it; prettyRuntime(qwen) renders Qwen Code.

Android (core/Board.kt, ui/BoardScreen.kt):
- BoardSite.qwenAvailable plus qwenBySite (gated on Runtime.QWEN_ENABLED),
  runtimeEditable(dshAvailable, qwenAvailable, pin), RuntimePicker qwen row.

Agent side unchanged: spawn_ticket already forwards agentType to spawn(),
resolve_agent_type already validates qwen, _launch_tmux already dispatches to
_launch_qwen which appends the ticket-branch directive - no new launch code.

Tests: qwen /runtime + spawnTicket + findTicketHost cases in server.test.js,
qwen runtime picker cases in board.test.js, qwen board cases in BoardTest.kt.
Docs: [Qwen I] in .claude/rules/qwen.md, turma-board/agent-board/PARITY updates.
# Conflicts:
#	.claude/rules/qwen.md
# Conflicts:
#	.claude/rules/qwen.md
@xerhab
xerhab merged commit 0cd01ef into main Aug 29, 2026
7 checks passed
@xerhab
xerhab deleted the XERK-515 branch August 29, 2026 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant