Always state the summary's voice: tag on the detail screen, Voice line in the saved report

This commit is contained in:
avi 2026-09-16 11:36:50 -05:00
commit 5ed4f31973
3 changed files with 21 additions and 8 deletions

View file

@ -12,7 +12,12 @@ fun renderReport(title: String, transcript: TranscriptData?, summary: SummaryDat
val out = mutableListOf("# $title", "")
if (summary != null) {
if (summary.short.isNotBlank()) {
out += listOf("## Summary", "", summary.short, "")
// Always state the voice: "neutral" when no persona was asked
// for — the summary is in a voice either way, and silence read
// as "unknown".
out += listOf("## Summary", "",
"*Voice: ${summary.tone ?: "neutral"}*", "",
summary.short, "")
}
for (key in SUMMARY_LIST_KEYS) {
val items = summary.list(key)

View file

@ -803,14 +803,13 @@ fun DetailScreen(state: DesktopState) {
if (s.short.isNotBlank()) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text("Summary", style = MaterialTheme.typography.titleMedium)
// Honest tag: which voice this summary was written in.
s.tone?.let {
// Honest tag: which voice this summary was written in
// — always shown; no persona = the neutral house voice.
Spacer(Modifier.width(8.dp))
Text("· in a $it voice",
Text("· in a ${s.tone ?: "neutral"} voice",
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.primary)
}
}
Text(s.short)
}
}

View file

@ -32,6 +32,15 @@ class ReportsTest {
assertTrue("_No transcript available._" in md)
}
@Test fun summarySectionAlwaysStatesVoice() {
val s = SummaryData(version = 1,
content = mapOf("short" to "Standup happened."))
// No persona: the neutral house voice, stated — not silence.
assertTrue("*Voice: neutral*" in renderReport("t", null, s))
val toned = s.copy(tone = "sarcastic")
assertTrue("*Voice: sarcastic*" in renderReport("t", null, toned))
}
@Test fun fmtTsShape() {
assertEquals("00:00:00", fmtTs(0.0))
assertEquals("00:01:05", fmtTs(65.0))