feat(kanban): per-task model override on create - #95
Conversation
Wire the missing write path for tasks.model_override. The column, the Task dataclass field, the dispatcher spawn (-m <model>), and the kanban-show print already existed, but nothing could SET the value: no --model CLI flag, no create_task() kwarg, no kanban_create tool prop. This finishes the feature (mirrors the --reasoning / --skill plumbing). - create_task(model_override=...): new kwarg + INSERT column/value; blank string coerces to NULL so the worker falls back to the profile model. - CLI: hermes kanban create --model <MODEL>. - Tool: kanban_create 'model' string prop + handler passthrough. - Test: round-trip + NULL-on-omit/blank behavior contract. Lets a lane default to opus while an individual simple card runs on a cheaper model, e.g. --model claude-sonnet-5-0.
|
Claude finished @exiao's task in 52s —— View job Review — PR #95: per-task model override on create
LGTM. This cleanly completes the write side of an already-landed read/spawn feature — no new column, no migration, no dispatcher change. Verified against the focus invariants:
0 blocking, 0 minor. |
There was a problem hiding this comment.
Code Review
This pull request introduces a per-task model override feature to the Kanban system. It adds a --model command-line argument to the task creation parser, updates the database schema and task creation logic to persist the model_override value, and exposes this parameter in the tool schema. Additionally, a unit test has been added to verify that the model override is correctly persisted and defaults to None when omitted or blank. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
LGTM — write path (CLI --model, create_task(model_override=), kanban_create tool model prop) cleanly completes the already-landed read/spawn side. Verified INSERT column/placeholder/value alignment (21 each), blank→NULL coercion matches the read mapping, and the new test is a genuine round-trip behavior contract (no frozen model catalog). No new env vars, no new core tool, no prompt-cache surface. 0 blocking, 0 minor.
Code Review — PR #95 (per-task model override on create)Local Codex/Claude-persona review ran the repo's rubric against live PR HEAD ( Verdict: APPROVE-WITH-NOTES (0 P0/P1/P2, 1 P3). Do not merge from this lane — flagging for a write lane / Eric. Verified (the 4 focus points all hold)
Tests: P3 (non-blocking) —
|
Review of #95 flagged that _task_to_dict omitted model_override, so create/show/list --json couldn't read back a value --model had just written (plain-text show already printed it). Add the field to _task_to_dict for observability parity + a JSON-surface round-trip test. Write path was already correct; this is read-side serialization only.
|
Addressed the P3 from review ( Write path was already correct; this is read-side serialization only. |
There was a problem hiding this comment.
LGTM — write path (CLI --model, create_task(model_override=), kanban_create tool model prop) cleanly completes the already-landed read/spawn side. Verified INSERT column/placeholder/value alignment (21 each, model_override last), blank→NULL coercion centralized in create_task and re-guarded on read, dispatcher -m consumption pre-exists, and P3 (task_to_dict JSON parity) addressed in 9144d21. No new core tool, no prompt-cache mutation, no HERMES* env var. Tests are behavior contracts. 0 blocking, 0 minor.
What
Finishes the half-landed per-task model override feature on Kanban
create.tasks.model_overridealready exists end-to-end on the read/spawn side:the column, the
Taskdataclass field, the dispatcher spawn (cmd.extend(["-m", task.model_override])), and thekanban showprint. But there was no write path — nothing could set the value:--modelflag onhermes kanban createmodel_overridekwarg oncreate_task()modelproperty on thekanban_createtool schemaSo the override could be honored but never created (grep finds zero
UPDATE ... SET model_overrideand zero rows with a value in practice). This PR wires the write path, mirroring the existing--reasoning(NousResearch#47476) and--skillplumbing.Changes
hermes_cli/kanban_db.py—create_task()gains amodel_overridekwarg; added to the INSERT column list + values tuple. A blank/whitespace string coerces toNULLso the worker falls back to the profile'smodel.default.hermes_cli/kanban.py—hermes kanban create --model <MODEL>flag + handler passthrough.tools/kanban_tools.py—kanban_createtool gains amodelstring property + handler passthrough.tests/hermes_cli/test_kanban_db.py— behavior-contract test: override round-trips; omitted/blank leaves the columnNULL.No new column or migration (already present). No dispatcher change (already reads it).
Why
Lets a worker lane default to a strong model (e.g.
claude-opus-4-8) while an individual simple card runs on a cheaper one, without cloning a whole profile:Test
pytest tests/hermes_cli/test_kanban_db.py→ 283 passed (282 + new).HERMES_HOME:--helpshows--model; real CLIcreate --model claude-sonnet-5-0persists to the row;create_task(model_override=...)and thekanban_createtool ({'model': ...}) both persist; blank/omitted →NULL; spawn builder emits-m.