Configurable default dispatch agent (unassigned → codex, not claude) — Task 207 - #1
Configurable default dispatch agent (unassigned → codex, not claude) — Task 207#1e-fu wants to merge 1 commit into
Conversation
… to codex, not claude (Task 207)
|
Merged directly to development (3c22a81) — PR not needed. |
There was a problem hiding this comment.
Pull request overview
This PR makes the “no capability-score data” fallback implementer agent configurable (defaulting to :codex) so unassigned tasks don’t silently route to :claude and consume higher-cost tokens. It introduces a new Harness.Config key for the default dispatch agent and exposes it in the dashboard settings UI, while keeping reviewer eligibility behavior unchanged.
Changes:
- Add
{:dispatch, :default_agent}as a:agent-typed config entry (default:codex) with validation against a closed implementer set. - Update
CapabilityScore’s no-data fallback to use the configured default dispatch agent unless an explicit:fallback_agentopt is provided. - Add a dedicated “Dispatch default” settings card + event handler and extend test coverage for config validation, UI persistence, and fallback behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
lib/harness/config/entry.ex |
Extends config value types to include :agent. |
lib/harness/config.ex |
Adds dispatch default agent schema entry, closed implementer set, and validation. |
lib/harness/capability_score.ex |
Switches fallback agent from hardcoded to config-driven default. |
lib/harness/dashboard/settings_live.ex |
Adds dashboard UI + handler for setting the default dispatch agent; excludes :agent from numeric config editor. |
test/harness/config_test.exs |
Adds validation and defaulting tests for :agent-typed dispatch default. |
test/harness/capability_score_test.exs |
Verifies fallback uses configured dispatch default when no :fallback_agent is provided. |
test/harness/dashboard/settings_live_test.exs |
Verifies UI renders the card, persists selection, and rejects unknown agent values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 79977e3c65
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @spec fallback_recommendation(CapabilityDomain.t(), [map()], keyword()) :: map() | ||
| defp fallback_recommendation(domain, rows, opts) do | ||
| fallback_agent = Keyword.get(opts, :fallback_agent, @fallback_agent) | ||
| fallback_agent = Keyword.get(opts, :fallback_agent, Config.get({:dispatch, :default_agent})) |
There was a problem hiding this comment.
Wire dispatch default into cron poller
This only updates the no-data CapabilityScore.recommend fallback; autonomous roadmap polling does not go through this path. I checked lib/harness/cron/roadmap_poller.ex, where task_agent/1 still maps a missing assignee to the module attribute @default_agent :claude, so an rmap ready task with assignee: nil will still enqueue Claude regardless of the new setting/UI. Please route that missing-assignee branch through Config.get({:dispatch, :default_agent}) too, or share one helper, so the setting actually protects cron-dispatched unassigned work.
Useful? React with 👍 / 👎.
Problem
An unassigned roadmap task dispatched via the default `recommend` adapter hits `CapabilityScore.recommend` with no measured scores and falls back to the hardcoded `@fallback_agent :claude` (`capability_score.ex:51`) — silently spending precious Claude tokens. Agents also frequently omit `assignee` at task creation, so this path is common.
Fix (configurable, by layer)