[object Object]

← back to Ticket System

Add local Qwen Run Now profiles

c6f392c483c924dd83e9d7e7d5dd2e94c81ffa0c · 2026-08-31 10:59:01 -0700 · Steve Abrams

Files touched

Diff

commit c6f392c483c924dd83e9d7e7d5dd2e94c81ffa0c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 31 10:59:01 2026 -0700

    Add local Qwen Run Now profiles
---
 board.html                       | 3 ++-
 run-ticket.sh                    | 4 +++-
 server.js                        | 2 +-
 test/run-ticket-profiles.test.js | 2 ++
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/board.html b/board.html
index 71fb54b6..63e74e4e 100644
--- a/board.html
+++ b/board.html
@@ -106,7 +106,8 @@
 <div id="actionbar">
   <span><span class="n" id="seln">0</span> selected</span>
   <select class="gsel" id="runProfile" title="Model used for Run Now">
-    <option value="claude-sonnet">Claude Sonnet</option><option value="claude-opus">Claude Opus</option><option value="claude-haiku">Claude Haiku</option><option value="codex">Codex (default)</option>
+    <optgroup label="Cloud"><option value="claude-sonnet">Claude Sonnet</option><option value="claude-opus">Claude Opus</option><option value="claude-haiku">Claude Haiku</option><option value="codex">Codex (default)</option></optgroup>
+    <optgroup label="Local · Ollama"><option value="local-qwen-27b">Local Qwen 27B Heretic</option><option value="local-qwen-14b">Local Qwen 14B</option></optgroup>
   </select>
   <button class="btn run" id="runBtn" title="Open a new iTerm2 window with the selected model, one per selected ticket">▶ Run Now</button>
   <button class="btn dtd" id="dtdBtn" title="Batched /dtd — clear yes/no 'run now' verdict per recent ticket">🧠 Analyze w/ DTD</button>
diff --git a/run-ticket.sh b/run-ticket.sh
index 5fde3c79..0bcc3ba8 100755
--- a/run-ticket.sh
+++ b/run-ticket.sh
@@ -5,7 +5,7 @@
 # authored ticket title ever reaches a shell). Steve, TK-10527 (2026-08-13):
 # "run ticket like the approvals opens a new iterm2 terminal with claude loaded first."
 #
-# Usage: run-ticket.sh <TK-id> [start-dir] [claude-sonnet|claude-opus|claude-haiku|codex]
+# Usage: run-ticket.sh <TK-id> [start-dir] [claude-sonnet|claude-opus|claude-haiku|codex|local-qwen-27b|local-qwen-14b]
 set -euo pipefail
 
 ID="${1:?usage: run-ticket.sh <TK-id> [start-dir]}"
@@ -28,6 +28,8 @@ case "$PROFILE" in
   claude-opus)   RUNNER=(claude --model opus);   AGENT_PREFIX=claude-run ;;
   claude-haiku)  RUNNER=(claude --model haiku);  AGENT_PREFIX=claude-run ;;
   codex)         RUNNER=(/Users/macstudio3/.local/bin/codex); AGENT_PREFIX=codex-run ;;
+  local-qwen-27b) RUNNER=(/Users/macstudio3/.local/bin/codex --oss --local-provider ollama --model qwen3.8-27b-heretic:latest); AGENT_PREFIX=local-qwen-27b-run ;;
+  local-qwen-14b) RUNNER=(/Users/macstudio3/.local/bin/codex --oss --local-provider ollama --model qwen3:14b); AGENT_PREFIX=local-qwen-14b-run ;;
   *) echo "run-ticket: refusing unknown profile '$PROFILE'" >&2; exit 2 ;;
 esac
 
diff --git a/server.js b/server.js
index 4aa28404..eca6fea8 100644
--- a/server.js
+++ b/server.js
@@ -12,7 +12,7 @@ const VERDICTS = path.join(DATA_DIR, 'dtd-verdicts.json');       // last batched
 const DTD_RUNNING = path.join(DATA_DIR, 'dtd-verdicts.running'); // present while a sweep is in flight
 const RUN_SH = path.join(__dirname, 'run-ticket.sh');           // opens an iTerm2 Claude session
 const DTD_RUN = path.join(__dirname, 'dtd-run.js');             // batched panel.sh sweep
-const RUN_PROFILES = new Set(['claude-sonnet', 'claude-opus', 'claude-haiku', 'codex']);
+const RUN_PROFILES = new Set(['claude-sonnet', 'claude-opus', 'claude-haiku', 'codex', 'local-qwen-27b', 'local-qwen-14b']);
 const DEFAULT_RUN_PROFILE = 'claude-sonnet';
 // IDRE / REFRE / resolveList now live in ./lib.js (co-located with resolveId).
 const json = (res, code, obj) => { res.writeHead(code, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obj)); };
diff --git a/test/run-ticket-profiles.test.js b/test/run-ticket-profiles.test.js
index d6a610d7..63e84809 100644
--- a/test/run-ticket-profiles.test.js
+++ b/test/run-ticket-profiles.test.js
@@ -12,6 +12,8 @@ test('allowlisted launcher profiles map to fixed commands', () => {
   assert.match(run('claude-opus'), /profile=claude-opus[\s\S]*claude --model opus/);
   assert.match(run('claude-haiku'), /profile=claude-haiku[\s\S]*claude --model haiku/);
   assert.match(run('codex'), /profile=codex[\s\S]*\/Users\/macstudio3\/\.local\/bin\/codex/);
+  assert.match(run('local-qwen-27b'), /profile=local-qwen-27b[\s\S]*--oss --local-provider ollama --model qwen3\.8-27b-heretic:latest/);
+  assert.match(run('local-qwen-14b'), /profile=local-qwen-14b[\s\S]*--oss --local-provider ollama --model qwen3:14b/);
 });
 
 test('unknown launcher profile is rejected before AppleScript', () => {

← c9aa7c59 Record Run Now model picker proof  ·  back to Ticket System  ·  Record local model picker proof 4559663c →