Skip to content

Commit 3b6f5b5

Browse files
committed
fix(cli): bound incident summary detail
1 parent 2cd4021 commit 3b6f5b5

5 files changed

Lines changed: 25 additions & 17 deletions

File tree

internal/cli/fieldproject_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ func TestIncidentDetailFieldsProjection(t *testing.T) {
297297
row["images"] = []map[string]any{{"src": strings.Repeat("https://example.test/image/", 100)}}
298298
stub.data = row
299299

300-
out, err := execCommand("incident", "detail", "inc-1", "--fields", "incident_id,title,root_cause", "--output-format", "json")
300+
fields := []string{"incident_id", "title", "incident_severity", "progress", "ai_summary", "root_cause", "resolution", "alert_cnt", "start_time", "channel_id"}
301+
out, err := execCommand("incident", "detail", "inc-1", "--fields", strings.Join(fields, ","), "--output-format", "json")
301302
if err != nil {
302303
t.Fatalf("execCommand: %v", err)
303304
}
@@ -308,8 +309,13 @@ func TestIncidentDetailFieldsProjection(t *testing.T) {
308309
if err := json.Unmarshal([]byte(strings.TrimSpace(out)), &detail); err != nil {
309310
t.Fatalf("parse projected detail json: %v\n%s", err, out)
310311
}
311-
if len(detail) != 3 || detail["incident_id"] == nil || detail["title"] == nil || detail["root_cause"] == nil {
312-
t.Fatalf("projected detail = %v, want exactly incident_id,title,root_cause", detail)
312+
if len(detail) != len(fields) {
313+
t.Fatalf("projected detail keys = %v, want exactly %v", detail, fields)
314+
}
315+
for _, field := range fields {
316+
if detail[field] == nil {
317+
t.Errorf("projected detail missing %q: %v", field, detail)
318+
}
313319
}
314320
if _, ok := detail["description"]; ok {
315321
t.Errorf("projected detail includes description: %v", detail)

internal/cli/incident_summary_script_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ func TestIncidentSummaryScriptCompactOutput(t *testing.T) {
3939
if len(lines) != 6 {
4040
t.Fatalf("fduty calls = %d, want 6:\n%s", len(lines), invocations)
4141
}
42-
if strings.Contains(string(invocations), "--output-format toon") {
43-
t.Fatalf("summary forces toon instead of each command's compact default:\n%s", invocations)
42+
wantDetail := "incident detail inc-1 --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon"
43+
if lines[0] != wantDetail {
44+
t.Fatalf("detail call = %q, want compact projection %q", lines[0], wantDetail)
45+
}
46+
if strings.Contains(strings.Join(lines[1:], "\n"), "--output-format toon") {
47+
t.Fatalf("non-detail reads force raw toon instead of their compact defaults:\n%s", invocations)
4448
}
4549
}

internal/skilldoc/incident_projection_guidance_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ func TestIncidentCardAvoidsUnboundedStructuredHotFlows(t *testing.T) {
1616
body := string(card)
1717
for description, command := range map[string]string{
1818
"triage list": "incident list --severity Critical --progress Triggered --since 4h --fields incident_id,title,incident_severity,progress,start_time,channel_id --output-format toon",
19-
"triage detail": "incident detail <incident-id> --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time --output-format toon",
20-
"summary detail": `incident detail "$ID" --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time --output-format toon`,
19+
"triage detail": "incident detail <incident-id> --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon",
20+
"summary detail": `incident detail "$ID" --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon`,
2121
} {
2222
if !strings.Contains(body, command) {
2323
t.Errorf("incident %s must project structured output to the fields needed by the workflow", description)

skills/flashduty/reference/incident.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Prereq: `SKILL.md` read. Read verbs are free. **Mutating verbs notify responders
4545
fduty incident list --severity Critical --progress Triggered --since 4h --fields incident_id,title,incident_severity,progress,start_time,channel_id --output-format toon
4646

4747
# 2. Get AI summary + full detail (use the 24-char incident_id from step 1)
48-
fduty incident detail <incident-id> --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time --output-format toon
48+
fduty incident detail <incident-id> --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon
4949

5050
# 3. See contributing alerts
5151
fduty incident alerts <incident-id>
@@ -77,7 +77,7 @@ If you fetch the pieces by hand instead, run **all six** — they are cheap read
7777

7878
```bash
7979
ID=<incident-id> # 24-char id from `incident list`
80-
fduty incident detail "$ID" --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time --output-format toon # ① 详情 + AI summary + alert counts + channel
80+
fduty incident detail "$ID" --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon # ① 详情 + AI summary + alert counts + channel
8181
fduty incident alerts "$ID" # ② contributing alerts (detail's embedded alerts are empty here)
8282
fduty incident timeline "$ID" # ④ timeline (or `incident feed "$ID"` for the paginated view)
8383
fduty incident similar "$ID" --limit 5 --output-format toon # ⑤ similar past incidents (channel-backed; see Gotchas; compact by default)

skills/flashduty/scripts/incident-summary.sh

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
# usage: bash incident-summary.sh <incident-id>
99
#
1010
# Section ⑥ lists recent post-mortems account-wide. To scope them to THIS incident's
11-
# channel, read its channel_id (fduty incident info --incident-id <id> --output-format
12-
# toon | grep '^channel_id:') and re-run: fduty incident post-mortem-list --channel-ids <id>
11+
# channel, read channel_id from the projected detail section and re-run:
12+
# fduty incident post-mortem-list --channel-ids <id>
1313
#
1414
# Note: errexit (-e) is intentionally NOT set — every section must run even if one
1515
# command fails, so the summary stays as complete as possible. Each command's own
@@ -22,14 +22,12 @@ if [ -z "$ID" ]; then
2222
exit 2
2323
fi
2424

25-
# Print each command's DEFAULT renderer (a curated table/summary that projects the
26-
# summary-relevant fields), NOT --output-format toon: toon dumps the full raw objects
27-
# — every empty field plus heavy blobs like a change's labels.steps — which overflowed
28-
# the output cap and forced repeated paging. For these read verbs the lean default IS
29-
# the field projection a fault summary needs (id/severity/status/title/channel/times/…).
25+
# Project detail explicitly because its default table includes unbounded narrative
26+
# fields. The other read verbs use their compact default renderers; raw toon dumps
27+
# every empty field plus heavy blobs like a change's labels.steps.
3028
run() { echo "===== fduty $* ====="; fduty "$@" 2>&1; echo; }
3129

32-
run incident detail "$ID" # ① 详情 + AI summary + alert counts + channel
30+
run incident detail "$ID" --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon # ① 详情 + AI summary + alert counts + channel
3331
run incident alerts "$ID" # ② contributing alerts
3432
run incident timeline "$ID" # ④ timeline
3533
run incident similar "$ID" --limit 5 # ⑤ similar past incidents (channel-backed)

0 commit comments

Comments
 (0)