Skip to content

fix: resolve bare tier names to full model strings before DB storage#2256

Merged
marcusquinn merged 1 commit intomainfrom
bugfix/model-tier-resolution
Feb 25, 2026
Merged

fix: resolve bare tier names to full model strings before DB storage#2256
marcusquinn merged 1 commit intomainfrom
bugfix/model-tier-resolution

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 25, 2026

Summary

  • batch.sh: cmd_add() extracted model:sonnet from TODO.md and stored the bare tier name in the DB. Workers received sonnet as the model string, causing model_config_error_sonnet_invalid_provider_format. Now resolves via resolve_model() before INSERT.
  • ai-actions.sh: _exec_escalate_model() used wrong column name (task_id instead of id) so the UPDATE silently matched 0 rows. Also stored bare tier name. Fixed column, added sql_escape(), and resolve_model().
  • dispatch.sh: Dispatch metadata logged resolved_model before it was set (fell back to bare $tmodel). Moved model resolution before metadata write.

Impact

  • Fixes model_config_error_sonnet_invalid_provider_format failures (t003.5, t009.1)
  • Fixes silent no-op in _exec_escalate_model() (wrong column name)
  • Dispatch logs now show the actual resolved model, not the bare tier name
  • Also cleaned up 13 existing bare tier names in the supervisor DB

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved model tier normalization before database persistence to ensure accurate record-keeping across agent operations
    • Enhanced resolution of bare model names to full model identifiers for consistency
    • Streamlined model resolution workflow to eliminate redundancy and ensure single source of truth for dispatched model selection

Three bugs caused model_config_error_sonnet_invalid_provider_format:

1. batch.sh cmd_add(): extracted model:sonnet from TODO.md and stored
   the bare tier name directly in the DB. Added resolve_model() call
   before INSERT to convert tier names to full strings.

2. ai-actions.sh _exec_escalate_model(): used wrong column name
   (task_id instead of id) so UPDATE silently matched 0 rows. Also
   stored bare tier name. Fixed column name, added sql_escape, and
   resolve_model() before UPDATE.

3. dispatch.sh cmd_dispatch(): wrote dispatch metadata using
   resolved_model before it was set (line 2874 vs 2906). Moved model
   resolution before metadata write so logs show the actual model.
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses several critical issues related to AI model name handling and database interactions within the supervisor scripts. The primary goal is to ensure that AI model tier names are consistently resolved to their full model strings before being stored in the database or logged, preventing model_config_error failures and improving data integrity. Additionally, it corrects a silent database update bug and enhances security by implementing SQL escaping.

Highlights

  • Model Resolution: Implemented logic to convert bare AI model tier names (e.g., "sonnet") into their full model strings (e.g., "anthropic/claude-sonnet-4-6") before database storage or logging, preventing model_config_error failures.
  • Database Update Correction: Fixed an issue in _exec_escalate_model() where the wrong primary key (task_id instead of id) was used for database updates, causing silent failures.
  • SQL Injection Prevention: Added sql_escape() to database update queries to properly sanitize input, enhancing security.
  • Dispatch Logging Accuracy: Adjusted the timing of model resolution in dispatch.sh to ensure dispatch logs accurately reflect the fully resolved AI model, not just the bare tier name.
Changelog
  • .agents/scripts/supervisor/ai-actions.sh
    • Resolved bare tier names to full model strings before updating the database.
    • Corrected the database update query to use the id column as the primary key instead of task_id.
    • Applied sql_escape() to task_id and resolved_to_tier for secure database operations.
    • Updated the log message to display the resolved model name.
  • .agents/scripts/supervisor/batch.sh
    • Introduced logic to resolve bare model tier names (e.g., "sonnet") to their fully qualified model strings (e.g., "anthropic/claude-sonnet-4-6") before inserting them into the database.
    • Added informational logging for successful model tier resolutions.
  • .agents/scripts/supervisor/dispatch.sh
    • Refactored the cmd_dispatch function to perform model resolution earlier, ensuring that the resolved_model is available and correctly logged in dispatch metadata.
    • Removed the redundant model resolution block that was previously located after metadata writing.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Walkthrough

These changes introduce model tier normalization across three supervisor scripts, resolving bare tier names (e.g., "sonnet", "opus") to full model strings using resolve_model before database persistence and dispatch operations.

Changes

Cohort / File(s) Summary
Model Resolution in Dispatch
.agents/scripts/supervisor/dispatch.sh
Adds early resolution of target model before dispatch metadata creation using resolve_model; removes previously duplicated resolution logic to establish single source of truth for dispatched model.
Batch Processing Normalization
.agents/scripts/supervisor/batch.sh
Introduces bare tier name resolution (e.g., "sonnet" → full model string) prior to database insertion using resolve_model with "opencode" context when model lacks slash delimiter.
Escalation Model Handling
.agents/scripts/supervisor/ai-actions.sh
Normalizes target model tier before database updates; computes escaped task_id, queries by escaped id, and stores resolved tier in database; adds clarifying comment about tasks table primary key structure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #2224: Modifies model-resolution logic in dispatch.sh including resolve_task_model, directly overlapping with this PR's changes
  • #384: Both PRs enhance supervisor dispatch/batch flows to resolve and propagate model tier names using resolve_model
  • #1359: Changes to model normalization and resolve_model/resolve_task_model functionality directly align with this PR's approach

Poem

🎯 Bare tiers transform to full model names,
Each script now speaks in unified frames,
No duplication clouds the way—
Resolved and normalized, come what may! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective: resolving bare tier names to full model strings before DB storage, which is the core fix across all three modified files (batch.sh, ai-actions.sh, dispatch.sh).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/model-tier-resolution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 58 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Wed Feb 25 01:48:02 UTC 2026: Code review monitoring started
Wed Feb 25 01:48:03 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 58

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 58
  • VULNERABILITIES: 0

Generated on: Wed Feb 25 01:48:05 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses several bugs related to model name resolution and database updates. The changes ensure that bare model tier names are resolved to their full identifiers before being stored, fix a silent database update failure due to an incorrect column name, and improve logging in the dispatch script. My review focuses on consistently applying the repository's guidelines regarding error handling. I've suggested removing instances of 2>/dev/null where appropriate to prevent the suppression of potentially important error messages, which will improve the debuggability of these scripts, while acknowledging specific exceptions for database operations.

# Resolve bare tier name to full model string before DB update
local resolved_to_tier="$to_tier"
if [[ -n "$to_tier" && "$to_tier" != *"/"* ]]; then
resolved_to_tier=$(resolve_model "$to_tier" "opencode" 2>/dev/null) || resolved_to_tier="$to_tier"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of 2>/dev/null here suppresses all error output from resolve_model. While the || resolved_to_tier="$to_tier" provides a fallback, it's better to allow errors (like syntax errors in helper scripts or configuration issues) to be visible for debugging. Consider removing 2>/dev/null to improve error visibility.

Suggested change
resolved_to_tier=$(resolve_model "$to_tier" "opencode" 2>/dev/null) || resolved_to_tier="$to_tier"
resolved_to_tier=$(resolve_model "$to_tier" "opencode") || resolved_to_tier="$to_tier"
References
  1. Avoid blanket suppression of errors with '2>/dev/null' to ensure that actual syntax or system errors remain visible for debugging.

# cause model_config_error when passed to the CLI at dispatch time.
if [[ -n "$model" && "$model" != *"/"* ]]; then
local resolved_model
resolved_model=$(resolve_model "$model" "opencode" 2>/dev/null) || resolved_model=""

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of 2>/dev/null suppresses all error output from resolve_model. While the || resolved_model="" provides a fallback, it's better to allow potential errors (like syntax errors in helper scripts or configuration issues) to be visible for debugging.

Suggested change
resolved_model=$(resolve_model "$model" "opencode" 2>/dev/null) || resolved_model=""
resolved_model=$(resolve_model "$model" "opencode") || resolved_model=""
References
  1. Avoid blanket suppression of errors with '2>/dev/null' to ensure that actual syntax or system errors remain visible for debugging.

# it discovers the work is incomplete, but starts cheap.
local resolved_model
if [[ "$verify_mode" == "true" ]]; then
resolved_model=$(resolve_model "coding" "$ai_cli" 2>/dev/null) || resolved_model=""

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of 2>/dev/null suppresses all error output from resolve_model. While the || resolved_model="" provides a fallback, it's better to allow potential errors (like syntax errors in helper scripts or configuration issues) to be visible for debugging. This would also make it consistent with the resolve_task_model call in the else block, which does not suppress stderr.

Suggested change
resolved_model=$(resolve_model "coding" "$ai_cli" 2>/dev/null) || resolved_model=""
resolved_model=$(resolve_model "coding" "$ai_cli") || resolved_model=""
References
  1. Avoid blanket suppression of errors with '2>/dev/null' to ensure that actual syntax or system errors remain visible for debugging.

@marcusquinn marcusquinn merged commit cd0322c into main Feb 25, 2026
17 of 18 checks passed
@marcusquinn marcusquinn deleted the bugfix/model-tier-resolution branch February 25, 2026 01:50
@augmentcode
Copy link

augmentcode bot commented Feb 25, 2026

🤖 Augment PR Summary

Summary: This PR prevents bare tier names (e.g. sonnet) from being stored/logged as model strings, which previously caused downstream CLI model-format errors.

Changes:

  • Resolve model: tiers to full provider/model strings before inserting/updating tasks in the supervisor DB
  • Fix _exec_escalate_model DB updates to target tasks.id (not task_id) and escape inputs
  • Move dispatch model resolution before metadata logging so logs reflect the resolved model
Technical Notes: Uses resolve_model()/resolve_task_model() for tier→model mapping and sql_escape() for SQLite literal safety.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

# Resolve bare tier names (e.g., "sonnet", "opus") to full model strings
# (e.g., "anthropic/claude-sonnet-4-6") before storing in DB. Bare tier names
# cause model_config_error when passed to the CLI at dispatch time.
if [[ -n "$model" && "$model" != *"/"* ]]; then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition treats any model value without a / as a tier; since resolve_model always echoes a non-empty default even for unknown inputs, it can silently coerce unexpected values (e.g. a bare model id) to the default model before DB storage.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

# Resolve bare tier name to full model string before DB update
local resolved_to_tier="$to_tier"
if [[ -n "$to_tier" && "$to_tier" != *"/"* ]]; then
resolved_to_tier=$(resolve_model "$to_tier" "opencode" 2>/dev/null) || resolved_to_tier="$to_tier"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve_model appears to always return success and echo a model string, so the || resolved_to_tier="$to_tier" fallback likely never triggers; any non-/ to_tier (even if it’s not a known tier) will get coerced to the default resolved model.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

# it discovers the work is incomplete, but starts cheap.
local resolved_model
if [[ "$verify_mode" == "true" ]]; then
resolved_model=$(resolve_model "coding" "$ai_cli" 2>/dev/null) || resolved_model=""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In verify mode this resolves the coding tier, but resolve_model’s static mapping treats coding as opus; if verify-mode is meant to start cheaper (sonnet), this may not hold when the chain/availability helpers don’t resolve differently.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/supervisor/dispatch.sh:
- Around line 2860-2872: The verify-mode dispatch incorrectly calls
resolve_model with the "coding" tier (via resolve_model "coding"), causing Opus
to be selected; change the resolve_model invocation in the verify-mode branch to
use the intended cheaper tier name (e.g., "sonnet" or the project's verify-tier
identifier) so resolved_model is set to the low-cost model; update the call site
that sets resolved_model (the block referencing verify_mode, resolved_model, and
resolve_model) to pass the correct tier string and keep the existing logging
behavior.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bf6537 and 19da6e5.

📒 Files selected for processing (3)
  • .agents/scripts/supervisor/ai-actions.sh
  • .agents/scripts/supervisor/batch.sh
  • .agents/scripts/supervisor/dispatch.sh

Comment on lines +2860 to +2872
# Resolve model via frontmatter + fallback chain (t132.5)
# Moved before metadata write so dispatch log has the resolved model, not bare tier.
# t1008: For verify-mode dispatches, prefer sonnet tier (cheaper, sufficient for
# verification checks). The verify worker can escalate to full implementation if
# it discovers the work is incomplete, but starts cheap.
local resolved_model
if [[ "$verify_mode" == "true" ]]; then
resolved_model=$(resolve_model "coding" "$ai_cli" 2>/dev/null) || resolved_model=""
log_info "Verify mode: using coding-tier model ($resolved_model) instead of task-specific model"
else
resolved_model=$(resolve_task_model "$task_id" "$tmodel" "${trepo:-.}" "$ai_cli")
fi

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Verify mode is still resolving to coding (Opus), not the intended cheaper tier.

Line 2867 uses resolve_model "coding", which maps to Opus in this file. That conflicts with the verify-mode cost-saving intent and will over-spend on verification dispatches.

Suggested fix
  if [[ "$verify_mode" == "true" ]]; then
-		resolved_model=$(resolve_model "coding" "$ai_cli" 2>/dev/null) || resolved_model=""
-		log_info "Verify mode: using coding-tier model ($resolved_model) instead of task-specific model"
+		resolved_model=$(resolve_model "sonnet" "$ai_cli" 2>/dev/null) || resolved_model=""
+		log_info "Verify mode: using sonnet-tier model ($resolved_model) instead of task-specific model"
  else
 		resolved_model=$(resolve_task_model "$task_id" "$tmodel" "${trepo:-.}" "$ai_cli")
  fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/supervisor/dispatch.sh around lines 2860 - 2872, The
verify-mode dispatch incorrectly calls resolve_model with the "coding" tier (via
resolve_model "coding"), causing Opus to be selected; change the resolve_model
invocation in the verify-mode branch to use the intended cheaper tier name
(e.g., "sonnet" or the project's verify-tier identifier) so resolved_model is
set to the low-cost model; update the call site that sets resolved_model (the
block referencing verify_mode, resolved_model, and resolve_model) to pass the
correct tier string and keep the existing logging behavior.

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