← back to Ticket System
Add local Qwen Run Now profiles
c6f392c483c924dd83e9d7e7d5dd2e94c81ffa0c · 2026-08-31 10:59:01 -0700 · Steve Abrams
Files touched
M board.htmlM run-ticket.shM server.jsM test/run-ticket-profiles.test.js
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 →