@@ -17,6 +17,7 @@ func incidentRow() map[string]any {
1717 "incident_severity" : "Critical" ,
1818 "progress" : "Triggered" ,
1919 "start_time" : 1712000000 ,
20+ "channel_id" : 12345 ,
2021 "description" : "root volume at 98%" ,
2122 "labels" : map [string ]any {"service" : "db" , "env" : "prod" },
2223 "responders" : []map [string ]any {
@@ -41,19 +42,84 @@ func alertRow() map[string]any {
4142 }
4243}
4344
44- // TestFieldsProjectionDefaultUnchanged is the conductor constraint: with NO
45- // --fields, the structured (toon and json) output must still be the full nested
46- // record — the nested blobs the proposal deliberately preserves as the default.
47- func TestFieldsProjectionDefaultUnchanged (t * testing.T ) {
45+ // TestIncidentListStructuredDefaultUsesCompactProjection is the default agent
46+ // path: incident list in json/toon mode must not dump the full nested SDK row
47+ // when --fields is omitted, while an explicit --fields still wins.
48+ func TestIncidentListStructuredDefaultUsesCompactProjection (t * testing.T ) {
49+ t .Run ("json default" , func (t * testing.T ) {
50+ saveAndResetGlobals (t )
51+ stub := newGFStub (t )
52+ stub .data = map [string ]any {"items" : []any {incidentRow ()}, "total" : 1 }
53+
54+ out , err := execCommand ("incident" , "list" , "--output-format" , "json" )
55+ if err != nil {
56+ t .Fatalf ("execCommand: %v" , err )
57+ }
58+
59+ assertProjectedJSONFields (t , out , []string {"incident_id" , "title" , "incident_severity" , "progress" , "start_time" , "channel_id" })
60+ })
61+
62+ t .Run ("toon default" , func (t * testing.T ) {
63+ saveAndResetGlobals (t )
64+ stub := newGFStub (t )
65+ stub .data = map [string ]any {"items" : []any {incidentRow ()}, "total" : 1 }
66+
67+ out , err := execCommand ("incident" , "list" , "--output-format" , "toon" )
68+ if err != nil {
69+ t .Fatalf ("execCommand: %v" , err )
70+ }
71+
72+ for _ , key := range []string {"incident_id" , "title" , "incident_severity" , "progress" , "start_time" , "channel_id" } {
73+ if ! strings .Contains (out , key ) {
74+ t .Errorf ("default toon output missing compact key %q, got:\n %s" , key , out )
75+ }
76+ }
77+ for _ , key := range []string {"responders" , "labels" , "description" } {
78+ if strings .Contains (out , key ) {
79+ t .Errorf ("default toon output should not contain full-record key %q, got:\n %s" , key , out )
80+ }
81+ }
82+ })
83+
84+ t .Run ("explicit fields win" , func (t * testing.T ) {
85+ saveAndResetGlobals (t )
86+ stub := newGFStub (t )
87+ stub .data = map [string ]any {"items" : []any {incidentRow ()}, "total" : 1 }
88+
89+ out , err := execCommand ("incident" , "list" , "--fields" , "incident_id,title" , "--output-format" , "json" )
90+ if err != nil {
91+ t .Fatalf ("execCommand: %v" , err )
92+ }
93+
94+ assertProjectedJSONFields (t , out , []string {"incident_id" , "title" })
95+ })
96+
97+ t .Run ("explicit empty fields errors" , func (t * testing.T ) {
98+ saveAndResetGlobals (t )
99+ stub := newGFStub (t )
100+ stub .data = map [string ]any {"items" : []any {incidentRow ()}, "total" : 1 }
101+
102+ _ , err := execCommand ("incident" , "list" , "--fields" , "" , "--output-format" , "json" )
103+ if err == nil {
104+ t .Fatal ("expected an error for empty --fields, got nil" )
105+ }
106+ if ! strings .Contains (err .Error (), "--fields" ) {
107+ t .Errorf ("error should name --fields, got: %v" , err )
108+ }
109+ })
110+ }
111+
112+ // TestAlertFieldsProjectionDefaultUnchanged is the conductor constraint for the
113+ // sibling command: with NO --fields, alert list structured output still emits
114+ // the full nested record. The compact default is incident-list-only.
115+ func TestAlertFieldsProjectionDefaultUnchanged (t * testing.T ) {
48116 cases := []struct {
49117 name string
50118 cmd []string
51119 data map [string ]any
52120 format string
53121 mustHave []string // nested keys that must survive in the full dump
54122 }{
55- {"incident toon" , []string {"incident" , "list" }, incidentRow (), "toon" , []string {"responders" , "labels" , "description" }},
56- {"incident json" , []string {"incident" , "list" }, incidentRow (), "json" , []string {"responders" , "labels" , "description" }},
57123 {"alert toon" , []string {"alert" , "list" }, alertRow (), "toon" , []string {"events" , "incident" , "labels" , "description" }},
58124 {"alert json" , []string {"alert" , "list" }, alertRow (), "json" , []string {"events" , "incident" , "labels" , "description" }},
59125 }
@@ -77,6 +143,27 @@ func TestFieldsProjectionDefaultUnchanged(t *testing.T) {
77143 }
78144}
79145
146+ func assertProjectedJSONFields (t * testing.T , out string , fields []string ) {
147+ t .Helper ()
148+
149+ var rows []map [string ]json.RawMessage
150+ if err := json .Unmarshal ([]byte (strings .TrimSpace (out )), & rows ); err != nil {
151+ t .Fatalf ("failed to parse projected json: %v\n raw:\n %s" , err , out )
152+ }
153+ if len (rows ) != 1 {
154+ t .Fatalf ("expected 1 projected row, got %d:\n %s" , len (rows ), out )
155+ }
156+ row := rows [0 ]
157+ if len (row ) != len (fields ) {
158+ t .Fatalf ("expected exactly %d keys, got %d (%v)" , len (fields ), len (row ), row )
159+ }
160+ for _ , f := range fields {
161+ if _ , ok := row [f ]; ! ok {
162+ t .Errorf ("projected row missing key %q, got keys %v" , f , row )
163+ }
164+ }
165+ }
166+
80167// TestFieldsProjectionTOON: --fields in toon mode emits exactly the requested
81168// keys and drops everything else.
82169func TestFieldsProjectionTOON (t * testing.T ) {
@@ -154,22 +241,7 @@ func TestFieldsProjectionJSON(t *testing.T) {
154241 t .Fatalf ("execCommand: %v" , err )
155242 }
156243
157- var rows []map [string ]json.RawMessage
158- if err := json .Unmarshal ([]byte (strings .TrimSpace (out )), & rows ); err != nil {
159- t .Fatalf ("failed to parse projected json: %v\n raw:\n %s" , err , out )
160- }
161- if len (rows ) != 1 {
162- t .Fatalf ("expected 1 projected row, got %d:\n %s" , len (rows ), out )
163- }
164- row := rows [0 ]
165- if len (row ) != len (tc .fields ) {
166- t .Fatalf ("expected exactly %d keys, got %d (%v)" , len (tc .fields ), len (row ), row )
167- }
168- for _ , f := range tc .fields {
169- if _ , ok := row [f ]; ! ok {
170- t .Errorf ("projected row missing key %q, got keys %v" , f , row )
171- }
172- }
244+ assertProjectedJSONFields (t , out , tc .fields )
173245 })
174246 }
175247}
0 commit comments