Skip to content

Commit 2c0114b

Browse files
Claudeclaude
authored andcommitted
fix: redesign session_close display — kill ceremony, surface insights
Drop the compliance checklist (internal validation noise), promote reflection highlights to top position, compact decisions to title-only, hide transcript/write-health unless failures. Half the line count. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 00e1069 commit 2c0114b

1 file changed

Lines changed: 42 additions & 77 deletions

File tree

src/tools/session-close.ts

Lines changed: 42 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -309,110 +309,75 @@ function formatCloseDisplay(
309309
): string {
310310
const lines: string[] = [];
311311

312-
// Header
313-
const closeLabel = compliance.close_type.toUpperCase();
312+
// Header: branded product line
314313
const status = success ? STATUS.complete : STATUS.failed;
315-
lines.push(productLine("close", `${closeLabel} · ${status}`));
316-
lines.push(dimText(`Session ${sessionId.slice(0, 8)} · ${compliance.agent}`));
314+
lines.push(productLine("close", status));
315+
316+
// Stats line: compact one-liner with key counts
317+
const stats: string[] = [];
318+
const scarsApplied = params.scars_to_record?.filter(s => s.reference_type !== "none").length || 0;
319+
if (scarsApplied > 0) stats.push(`${scarsApplied} scars applied`);
320+
if (learningsCount > 0) stats.push(`${learningsCount} learnings`);
321+
if (params.decisions?.length) stats.push(`${params.decisions.length} decision${params.decisions.length > 1 ? "s" : ""}`);
322+
const threads = params.open_threads || [];
323+
const openCount = threads.filter(t => typeof t === "string" || t.status === "open").length;
324+
if (openCount > 0) stats.push(`${openCount} threads`);
325+
if (stats.length > 0) {
326+
lines.push(stats.join(" · "));
327+
}
328+
lines.push(dimText(`${sessionId.slice(0, 8)} · ${compliance.agent} · ${compliance.close_type}`));
317329

330+
// Errors — only on failure
318331
if (!success && errors?.length) {
319332
lines.push("");
320-
for (const e of errors) lines.push(` !! ${e}`);
333+
for (const e of errors) lines.push(` ${STATUS.miss} ${e}`);
321334
}
322335

323-
// Checklist (compact)
324-
lines.push("");
325-
const ok = STATUS.pass;
326-
const no = STATUS.miss;
327-
if (compliance.close_type === "standard") {
328-
lines.push(` ${ok} Session state read`);
329-
lines.push(` ${compliance.questions_answered_by_agent ? ok : no} Reflection (9 questions)`);
330-
lines.push(` ${compliance.human_asked_for_corrections ? ok : no} Human corrections`);
331-
lines.push(` ${success ? ok : no} Persisted`);
332-
} else {
333-
lines.push(` ${success ? ok : no} Persisted (${compliance.close_type})`);
336+
// Reflection highlights FIRST — the most interesting part
337+
if (params.closing_reflection) {
338+
const r = params.closing_reflection;
339+
if (r.what_worked || r.do_differently) {
340+
lines.push("");
341+
if (r.what_worked) {
342+
lines.push(`${ANSI.green}+${ANSI.reset} ${truncate(r.what_worked, 72)}`);
343+
}
344+
if (r.do_differently) {
345+
lines.push(`${ANSI.yellow}>${ANSI.reset} ${truncate(r.do_differently, 72)}`);
346+
}
347+
}
334348
}
335349

336-
// Decisions table
350+
// Decisions — title only, one line each
337351
if (params.decisions?.length) {
338352
lines.push("");
339-
lines.push(boldText("Decisions"));
340353
for (const d of params.decisions) {
341-
lines.push(` ${truncate(d.title, 60)}`);
342-
lines.push(` ${truncate(d.decision, 70)}`);
354+
lines.push(` ${dimText("d")} ${truncate(d.title, 68)}`);
343355
}
344356
}
345357

346-
// Learnings created
347-
if (params.learnings_created?.length) {
358+
// Scars applied — compact table, only if any were applied
359+
if (scarsApplied > 0) {
348360
lines.push("");
349-
lines.push(boldText(`Learnings (${params.learnings_created.length})`));
350-
for (const l of params.learnings_created) {
351-
// learnings_created is (string | Record)[] — show truncated ID or object key
352-
const label = typeof l === "string" ? (l.length > 12 ? l.slice(0, 8) : l) : String(l);
353-
lines.push(` ${label}`);
354-
}
355-
}
356-
357-
// Scars applied
358-
if (params.scars_to_record?.length) {
359-
const acknowledged = params.scars_to_record.filter(s => s.reference_type !== "none");
360-
const ignored = params.scars_to_record.length - acknowledged.length;
361-
lines.push("");
362-
lines.push(boldText(`Scars (${acknowledged.length} applied${ignored > 0 ? `, ${ignored} surfaced-only` : ""})`));
363-
for (const s of acknowledged) {
361+
for (const s of params.scars_to_record!.filter(s => s.reference_type !== "none")) {
364362
const ref = s.reference_type === "explicit" ? "applied" :
365363
s.reference_type === "implicit" ? "implicit" :
366364
s.reference_type === "acknowledged" ? "ack'd" :
367-
s.reference_type === "refuted" ? "REFUTED" : (s.reference_type || "?");
368-
const scarId = s.scar_identifier || "(unknown)";
369-
const id = scarId.length > 12 ? scarId.slice(0, 8) : scarId;
370-
lines.push(` ${id} ${ref.padEnd(8)} ${truncate(s.reference_context || "", 50)}`);
365+
s.reference_type === "refuted" ? `${ANSI.yellow}REFUTED${ANSI.reset}` : (s.reference_type || "?");
366+
lines.push(` ${dimText(ref.padEnd(8))} ${truncate(s.reference_context || "", 60)}`);
371367
}
372368
}
373369

374-
// Transcript status
375-
if (transcriptStatus) {
370+
// Transcript — only on failure
371+
if (transcriptStatus && !transcriptStatus.saved) {
376372
lines.push("");
377-
lines.push(`### Transcript`);
378-
if (transcriptStatus.saved) {
379-
let line = `- [done] Saved (${transcriptStatus.size_kb}KB) -> ${transcriptStatus.path}`;
380-
if (transcriptStatus.patch_warning) {
381-
line += ` (warning: session record not updated)`;
382-
}
383-
lines.push(line);
384-
} else {
385-
lines.push(`- [FAILED] ${transcriptStatus.error || "Unknown error"}`);
386-
}
373+
lines.push(`${STATUS.fail} transcript: ${transcriptStatus.error || "Unknown error"}`);
387374
}
388375

389-
// Threads summary
390-
const threads = params.open_threads || [];
391-
if (threads.length > 0) {
392-
const openCount = threads.filter(t => typeof t === "string" || t.status === "open").length;
393-
const resolvedCount = threads.length - openCount;
394-
lines.push("");
395-
lines.push(`${boldText("Threads")}: ${openCount} open${resolvedCount > 0 ? `, ${resolvedCount} resolved` : ""}`);
396-
}
397-
398-
// Write health — only surface when there are failures (dev diagnostic)
376+
// Write health — only on failure
399377
const healthReport = getEffectTracker().getHealthReport();
400378
if (healthReport.overall.failed > 0) {
401379
lines.push("");
402-
lines.push(`${boldText("Write Health")} (${healthReport.overall.failed} failure${healthReport.overall.failed > 1 ? "s" : ""})`);
403-
lines.push(getEffectTracker().formatSummary());
404-
}
405-
406-
// Reflection highlights (Q4 what worked, Q3 do differently)
407-
if (params.closing_reflection) {
408-
const r = params.closing_reflection;
409-
if (r.what_worked) {
410-
lines.push("");
411-
lines.push(`${boldText("What worked")}: ${truncate(r.what_worked, 80)}`);
412-
}
413-
if (r.do_differently) {
414-
lines.push(`${boldText("Next time")}: ${truncate(r.do_differently, 80)}`);
415-
}
380+
lines.push(`${STATUS.warn} ${healthReport.overall.failed} write failure${healthReport.overall.failed > 1 ? "s" : ""}`);
416381
}
417382

418383
return wrapDisplay(lines.join("\n"));

0 commit comments

Comments
 (0)