review/settings: clarify model offset-matching; mergeReviewProfiles always returns non-nil · Entire

review/settings: clarify model offset-matching; mergeReviewProfiles always returns non-nil

f55c55a→main·

dipree·1mo ago·4 files·+24 added/-11 removed

Sessions

5cbbb55f9459View transcript

[?
Checkout the hand off doc that I just added.Pi·Opus 4.8·2 steps](/content/gh/entireio/cli/session/019eca64-8c2c-7b00-90c6-3aa49738c497#timeline-5cbbb55f9459/index.html)

Changes

4

478 unmodified lines

479
480
481
482
483
484
485
486
483
484
485
486
487
488
489
490
491
492
493
494

478 unmodified lines

// "claude-sonnet-4-5" while rejecting variant suffixes like "gpt-4o-mini" and
// bare version fragments like "4-5".
//
// `short` may appear at any offset in `long`, so a provider/family prefix on
// the recorded model does not block a match: "claude-sonnet" matches
// "anthropic-claude-sonnet-4-5" at offset 1 (the next component "4" is numeric).
//
// Equal-length cases are intentionally rejected here (`len(short) >= len(long)`):
// identical ids already returned true via reviewRunModelMatches's `want == got`
// short-circuit before this helper runs, and two *distinct* equal-length ids
// (e.g. "claude-sonnet" vs "claude-opus") are different models that must not
// match. Legitimate matches are always strict subsets, so `short` is shorter.
// two equal-length component arrays are either identical — already matched via
// reviewRunModelMatches's `want == got` short-circuit before this helper runs,
// since identical arrays imply identical normalized strings — or genuinely
// different models (e.g. "claude-sonnet" vs "claude-opus") that must not match.
// A strict subset needs a longer container, so `short` is always shorter.
func modelComponentsMatch(short, long []string) bool {
    if len(short) == 0 || len(short) >= len(long) {
        return false

Mcmd/entire/cli/review/manifest.go+9/-4

775 unmodified lines

776
777
778
779
780
781
782
783
784

775 unmodified lines

// Identical ids match regardless of component count (via the want==got
        // short-circuit), but two distinct equal-length ids must not.
        {"identical multi-component ids match", "claude-sonnet-4-5", "claude-sonnet-4-5", true},
        {"identical two-component ids match", "claude-sonnet", "claude-sonnet", true},
        {"slash provider prefix stripped then identical", "anthropic/claude-sonnet", "claude-sonnet", true},
        {"family matches across a provider component at offset", "claude-sonnet", "anthropic-claude-sonnet-4-5", true},
        {"thinking-suffix-only difference matches", "claude-sonnet:high", "claude-sonnet:low", true},
        {"equal-length different family does not match", "claude-sonnet", "claude-opus", false},
        {"equal-length different version does not match", "claude-sonnet-4", "claude-sonnet-5", false},

Mcmd/entire/cli/review/manifest_test.go+3

684 unmodified lines

685
686
687
688
688
689
690
691
690
691
692
692
693
694

684 unmodified lines

// hiding the others' profiles.
//
// Neither input map is mutated: callers (and the maps they own, e.g. a freshly
// loaded ClonePreferences) can rely on their maps being left untouched.
// loaded ClonePreferences) can rely on their maps being left untouched. The
// result is always a fresh, non-nil map (empty when both inputs are empty), so
// callers never receive nil from a non-nil input.
func mergeReviewProfiles(base, src map[string]ReviewProfileConfig) map[string]ReviewProfileConfig {
    if len(base) == 0 && len(src) == 0 {
        return base
    }
    out := make(map[string]ReviewProfileConfig, len(base)+len(src))
    for name, cfg := range base {
        out[name] = cfg

Mcmd/entire/cli/settings/settings.go+3/-4

1189 unmodified lines

1190
1191
1192
1193
1194
1195
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203

1189 unmodified lines

t.Errorf("src mutated: len = %d, want 2", len(src))
    }

// Both empty returns without allocating a non-nil map surprise.
    if got := mergeReviewProfiles(nil, nil); got != nil {
         t.Errorf("merge(nil,nil) = %v, want nil", got)
    // The result is always a fresh, non-nil map, even when both inputs are
    // empty/nil, so callers never receive nil from a non-nil input.
    if got := mergeReviewProfiles(nil, nil); got == nil {
        t.Error("merge(nil, nil) should return a non-nil empty map, got nil")
    } else if len(got) != 0 {
        t.Errorf("merge(nil, nil) = %v, want empty", got)
    }
    if got := mergeReviewProfiles(nil, map[string]ReviewProfileConfig{}); got == nil {
        t.Error("merge(nil, emptyNonNil) should return a non-nil empty map, got nil")
    }
}

Mcmd/entire/cli/settings/settings_test.go+9/-3