Skip to content

fix(tui): isolate OpenCode model config from profiles#1086

Open
RGutierrezWind wants to merge 2 commits into
Gentleman-Programming:mainfrom
RGutierrezWind:fix/opencode-model-profile-isolation
Open

fix(tui): isolate OpenCode model config from profiles#1086
RGutierrezWind wants to merge 2 commits into
Gentleman-Programming:mainfrom
RGutierrezWind:fix/opencode-model-profile-isolation

Conversation

@RGutierrezWind

@RGutierrezWind RGutierrezWind commented Jul 9, 2026

Copy link
Copy Markdown

🔗 Linked Issue

Closes #950


🏷️ PR Type

What kind of change does this PR introduce?

  • type:bug — Bug fix (non-breaking change that fixes an issue)
  • type:feature — New feature (non-breaking change that adds functionality)
  • type:docs — Documentation only
  • type:refactor — Code refactoring (no functional changes)
  • type:chore — Build, CI, or tooling changes
  • type:breaking-change — Breaking change (fix or feature that changes existing behavior)

📝 Summary

  • Reloads base/default OpenCode model assignments when entering Configure OpenCode Models after profile editing.
  • Clears stale profile assignment context so custom SDD profile assignments do not leak into the base OpenCode config screen.
  • Adds regression coverage for the profile-to-base OpenCode transition.

📂 Changes

File / Area What Changed
internal/tui/model.go Detects stale profile assignment context, reloads base OpenCode assignments, and clears profile draft/edit state when needed.
internal/tui/model_test.go Adds regression coverage ensuring profile assignments do not leak into standalone OpenCode model config.

🧪 Test Plan

Unit Tests

go test ./...

E2E Tests (Docker required)

cd e2e && ./docker-test.sh
  • Unit tests pass (go test ./...)
  • E2E tests pass (cd e2e && ./docker-test.sh)
  • Manually tested locally

Additional focused validation:

go test ./internal/tui -run 'TestModelConfigOpenCode(ReloadsBaseAssignmentsAfterProfileEdit|PrePopulatesAssignments|DoesNotOverwriteExistingSessionAssignments|NoPrePopulationWhenFileEmpty)$' -count=1

🤖 Automated Checks

The following checks run automatically on this PR:

Check Status Description
Check PR Cognitive Load PR should stay within 400 changed lines (additions + deletions) or use size:exception
Check Issue Reference PR body must contain Closes/Fixes/Resolves #N
Check Issue Has status:approved Linked issue must have been approved before work began
Check PR Has type:* Label Exactly one type:* label must be applied
Unit Tests go test ./... must pass
E2E Tests cd e2e && ./docker-test.sh must pass

✅ Contributor Checklist

  • PR is linked to an issue with status:approved
  • PR stays within 400 changed lines, or I have requested/obtained maintainer-applied size:exception with rationale documented
  • I have added the appropriate type:* label to this PR
  • Unit tests pass (go test ./...)
  • E2E tests pass (cd e2e && ./docker-test.sh)
  • I have updated documentation if necessary
  • My commits follow Conventional Commits format
  • My commits do not include Co-Authored-By trailers

💬 Notes for Reviewers

E2E tests were not run locally because this change is isolated to TUI model assignment state and regression coverage was added at the unit-test level.

This PR needs a maintainer to apply exactly one type:* label: type:bug. GitHub denied label application from this fork with AddLabelsToLabelable permission error.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed OpenCode model configuration to reload base assignments after profile edits.
    • Ensured profile-specific selections no longer carry into the standalone OpenCode configuration flow.
    • Improved pre-population logic to preserve in-session non-profile edits while refreshing defaults as needed.
  • Tests
    • Added a regression test covering the OpenCode reload behavior after profile assignment/edit mode interactions.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The TUI reloads base OpenCode assignments when configuration opens from profile context, clears profile state, and verifies that profile-specific assignments are removed.

Changes

OpenCode assignment isolation

Layer / File(s) Summary
Base assignment loading
internal/tui/model.go
Adds helpers to detect profile context, load sanitized assignments from opencode.json, and clear profile edit state.
Model configuration entry behavior
internal/tui/model.go, internal/tui/model_test.go
Reloads base assignments when entering OpenCode configuration from profile context and adds regression coverage for removing profile-specific values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Model
  participant Assignments
  participant Selection
  participant Picker
  Model->>Assignments: Read base OpenCode assignments
  Assignments->>Selection: Populate ModelAssignments
  Model->>Selection: Clear profile edit and draft state
  Model->>Picker: Open OpenCode model configuration
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes isolating OpenCode model config from profiles.
Linked Issues check ✅ Passed The code reloads base OpenCode assignments and clears profile state as required by #950.
Out of Scope Changes check ✅ Passed The only changes are the targeted logic fix and a matching regression test.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/model_test.go`:
- Around line 2258-2268: Extend the test around confirmSelection to explicitly
assert that profile context is cleared, not just that model assignments are
replaced. Inspect the state fields managed by withoutProfileAssignmentContext
and add assertions verifying each relevant profile-state field is empty or unset
after reload, alongside the existing ModelAssignments checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d2dddb4a-4bf0-4125-b7fe-0bd1b93530af

📥 Commits

Reviewing files that changed from the base of the PR and between b22a7eb and 6cc24a2.

📒 Files selected for processing (2)
  • internal/tui/model.go
  • internal/tui/model_test.go

Comment thread internal/tui/model_test.go
@RGutierrezWind RGutierrezWind force-pushed the fix/opencode-model-profile-isolation branch from fdb5093 to 2ff7a1b Compare July 12, 2026 03:05
@RGutierrezWind RGutierrezWind force-pushed the fix/opencode-model-profile-isolation branch from 2ff7a1b to 1519b54 Compare July 12, 2026 03:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/model.go`:
- Around line 169-176: Update withBaseOpenCodeModelAssignments to handle errors
from readCurrentAssignmentsFn by surfacing the same ConfigWarning behavior used
by NewModelPickerState for opencode.json read/parse failures, while preserving
the existing assignment sanitization for successful non-empty reads.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5d6f17c4-40b0-433a-9b6e-e34df04aa4e7

📥 Commits

Reviewing files that changed from the base of the PR and between 2ff7a1b and 1519b54.

📒 Files selected for processing (2)
  • internal/tui/model.go
  • internal/tui/model_test.go

Comment thread internal/tui/model.go
Comment on lines +169 to +176
func (m Model) withBaseOpenCodeModelAssignments() Model {
m.Selection.ModelAssignments = nil
settingsPath := opencode.DefaultSettingsPath()
if current, err := readCurrentAssignmentsFn(settingsPath); err == nil && len(current) > 0 {
m.Selection.ModelAssignments = sanitizeKnownModelEfforts(current, m.ModelPicker.SDDModels)
}
return m
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Silent failure on opencode.json read error.

When readCurrentAssignmentsFn returns an error, the assignments are silently dropped with no indication to the user. Elsewhere in the same subsystem, NewModelPickerState surfaces a ConfigWarning for the equivalent read/parse failure of opencode.json. Since this helper feeds directly into a user-initiated action ("Configure OpenCode models"), a silent empty picker on read failure could look identical to a config with no assignments, hiding the real cause.

♻️ Suggested fix
 func (m Model) withBaseOpenCodeModelAssignments() Model {
 	m.Selection.ModelAssignments = nil
 	settingsPath := opencode.DefaultSettingsPath()
-	if current, err := readCurrentAssignmentsFn(settingsPath); err == nil && len(current) > 0 {
-		m.Selection.ModelAssignments = sanitizeKnownModelEfforts(current, m.ModelPicker.SDDModels)
+	current, err := readCurrentAssignmentsFn(settingsPath)
+	if err != nil {
+		m.ModelPicker.ConfigWarning = fmt.Sprintf("Could not load current OpenCode model assignments: %v", err)
+	} else if len(current) > 0 {
+		m.Selection.ModelAssignments = sanitizeKnownModelEfforts(current, m.ModelPicker.SDDModels)
 	}
 	return m
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (m Model) withBaseOpenCodeModelAssignments() Model {
m.Selection.ModelAssignments = nil
settingsPath := opencode.DefaultSettingsPath()
if current, err := readCurrentAssignmentsFn(settingsPath); err == nil && len(current) > 0 {
m.Selection.ModelAssignments = sanitizeKnownModelEfforts(current, m.ModelPicker.SDDModels)
}
return m
}
func (m Model) withBaseOpenCodeModelAssignments() Model {
m.Selection.ModelAssignments = nil
settingsPath := opencode.DefaultSettingsPath()
current, err := readCurrentAssignmentsFn(settingsPath)
if err != nil {
m.ModelPicker.ConfigWarning = fmt.Sprintf("Could not load current OpenCode model assignments: %v", err)
} else if len(current) > 0 {
m.Selection.ModelAssignments = sanitizeKnownModelEfforts(current, m.ModelPicker.SDDModels)
}
return m
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/model.go` around lines 169 - 176, Update
withBaseOpenCodeModelAssignments to handle errors from readCurrentAssignmentsFn
by surfacing the same ConfigWarning behavior used by NewModelPickerState for
opencode.json read/parse failures, while preserving the existing assignment
sanitization for successful non-empty reads.

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.

fix(tui): isolate default OpenCode model config from custom SDD profiles

1 participant