inspect: test explicit empty model session matching · Entire

inspect: test explicit empty model session matching

An explicit JSON model value of an empty string decodes to AgentRun.Model == , the same runtime representation as an omitted model. Add a regression test showing matchSessionsToRuns treats that as a default-model inspector and still lets the explicit-model inspector claim its matching session first.

Sessions

237cfee42956View transcript

Changes

1

1 unmodified line

2
3
4
5
6
7
8
964 unmodified lines

973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

1 unmodified line

import (
    "context"
    "encoding/json"
    "errors"
    "os"
    "path/filepath"
964 unmodified lines

t.Errorf("source = %#v, want sess-default / 'default finding'", manifest.Sources[0])
    }
}

// TestBuildLocalReviewManifestFromSummary_ExplicitEmptyModelIsDefault proves
// that a JSON value of "model": "" is indistinguishable from an omitted model
// once decoded into AgentRun.Model, and is therefore treated as a default-model
// inspector (not as an explicit-model inspector) by matchSessionsToRuns.
func TestBuildLocalReviewManifestFromSummary_ExplicitEmptyModelIsDefault(t *testing.T) {
    const (
        sessDefault = "sess-default"
        sessOpus    = "sess-opus"
    )
    started := time.Date(2026, 5, 7, 10, 0, 0, 0, time.UTC)
    type encodedRun struct {
        Name      string                  `json:"name"`
        AgentName string                  `json:"agent_name"`
        Model     string                  `json:"model"`
        Status    reviewtypes.AgentStatus `json:"status"`
    }
    var encoded []encodedRun
    if err := json.Unmarshal([]byte(`[\
        {"name":"claude-code","agent_name":"claude-code","model":"","status":1},\
        {"name":"claude-code","agent_name":"claude-code","model":"opus","status":1}\
    ]`), &encoded); err != nil {
        t.Fatalf("unmarshal runs: %v", err)
    }
    runs := make([]reviewtypes.AgentRun, len(encoded))
    for i, run := range encoded {
        runs[i] = reviewtypes.AgentRun{
            Name:      run.Name,
            AgentName: run.AgentName,
            Model:     run.Model,
            Status:    run.Status,
        }
    }
    if runs[0].Model != "" {
        t.Fatalf("explicit empty JSON model decoded as %q, want empty string", runs[0].Model)
    }
    summary := reviewtypes.RunSummary{StartedAt: started, AgentRuns: runs}
states := []*session.State{
    {
        SessionID:    sessDefault,
        Kind:         session.KindAgentReview,
        WorktreePath: "/repo",
        BaseCommit:   "abc123",
        StartedAt:    started.Add(time.Second),
        AgentType:    agenttypes.AgentType("Claude Code"),
        ModelName:    "claude-sonnet-4-5",
    },
    {
        SessionID:    sessOpus,
        Kind:         session.KindAgentReview,
        WorktreePath: "/repo",
        BaseCommit:   "abc123",
        StartedAt:    started.Add(2 * time.Second), // more recent, so a single-pass default match would steal it
        AgentType:    agenttypes.AgentType("Claude Code"),
        ModelName:    "claude-opus-4-1",
    },
}

manifest := buildLocalReviewManifestFromSummary("/repo", "abc123", summary, states, "")

if len(manifest.Sources) != 2 {
        t.Fatalf("sources = %d, want 2", len(manifest.Sources))
    }
    if manifest.Sources[0].SessionID != sessDefault {
        t.Errorf("explicit-empty/default inspector linked to %q, want %s", manifest.Sources[0].SessionID, sessDefault)
    }
    if manifest.Sources[1].SessionID != sessOpus {
        t.Errorf("opus inspector linked to %q, want %s", manifest.Sources[1].SessionID, sessOpus)
    }
}