Polish news and personal report phrasing

This commit is contained in:
Jacob Dubin
2026-05-21 06:28:16 -05:00
parent eb509a66e0
commit bedb5d1715
6 changed files with 61 additions and 9 deletions

View File

@@ -847,7 +847,7 @@ Current release theme:
- identity charm prompts like `what's your name`, `do you have a nickname`, `do you like being Jibo`, `are there others like you`, and `what is your favorite name`
- attraction and preference prompts like `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, and `do you like kids`
- longer authored variants for the same prompt family when Pegasus shows richer phrasing
- charm/capability prompts like `can you laugh` and `can you dance`
- charm/capability prompts like `can you laugh`, `can you dance`, `can you sing`, and `will you sing`
- mood / affect questions
- recognition follow-ups like `do you know me`
- follow-up state prompts that should stay warm and locally grounded
@@ -917,6 +917,21 @@ Current release theme:
- decide whether the composition layer should sit above the prompt catalog or beside it as a dedicated response post-processor
- keep this separate from the authored-variant backlog item so we do not blur prompt richness with runtime composition
### 33. Singing And Musical Personality
- Status: `discovery`
- Tags: `content`, `docs`, `protocol`
- Why now:
- Jibos charm surface includes musical and sing-along behavior, and it fits naturally after the current personality and holiday batches
- the first pass should stay familiar and rule-based, not LLM-driven
- Scope:
- inventory the legacy song / sing / musical prompt families
- decide whether the first slice should be short song replies, a sing-along launcher, or both
- keep the first implementation source-backed if Pegasus has usable authored lines
- Exit criteria:
- a small song backlog exists with candidate phrases listed
- the release plan has a clear place for musical personality without crowding out weather/news/report work
## Suggested Order
Before closing `1.0.18`:

View File

@@ -30,7 +30,7 @@ Keep a running checklist of the legacy persona questions and identity surfaces w
- favorite-style prompts: `what is your favorite color`, `what is your favorite food`, `what is your favorite music`
- attraction and preference prompts: `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, `do you like kids`
- longer authored variants for the same prompt family when Pegasus shows richer phrasing, especially multi-clause and follow-up-heavy responses
- capability and charm prompts: `can you laugh`, `can you dance`
- capability and charm prompts: `can you laugh`, `can you dance`, `can you sing`, `will you sing`
- affect and mood: `how are you`, `are you happy`, `are you sad`, `are you angry`
- memory and identity recall: `who am i`, `what is my name`, `when is my birthday`, `what is my favorite music`
- greeting and presence charm: `good morning`, `welcome back`, `who is this`, person-aware greeting follow-ups

View File

@@ -2432,7 +2432,11 @@ public sealed class JiboInteractionService(
cancellationToken);
if (snapshot?.Headlines.Count > 0)
return BuildProviderNewsDecision(snapshot, preferredCategories, requestedHeadlineCount);
return BuildProviderNewsDecision(
snapshot,
catalog,
preferredCategories,
requestedHeadlineCount);
var providerStatus = ResolveNewsProviderStatus(snapshot);
var providerMessage = snapshot?.ProviderMessage;
@@ -2522,6 +2526,7 @@ public sealed class JiboInteractionService(
private static JiboInteractionDecision BuildProviderNewsDecision(
NewsBriefingSnapshot snapshot,
JiboExperienceCatalog catalog,
IReadOnlyList<string> preferredCategories,
int requestedHeadlineCount)
{
@@ -2543,7 +2548,8 @@ public sealed class JiboInteractionService(
var leadIn = BuildNewsLeadIn(snapshot.SourceName, preferredCategories);
var joinedHeadlines = string.Join(" ", headlines.Select(static headline => $"{headline.Title}."));
var spokenBriefing = $"{leadIn} {joinedHeadlines}".Trim();
var outroTemplate = ChooseShortestTemplate(catalog.NewsOutroReplies) ?? "And that's the news.";
var spokenBriefing = $"{leadIn} {joinedHeadlines} {outroTemplate}".Trim();
return BuildNewsDecision(
spokenBriefing,
snapshot.SourceName,

View File

@@ -281,12 +281,24 @@ internal static class PersonalReportOrchestrator
}
if (toggles.CalendarEnabled)
reportSections.Add((await buildCalendarDecisionAsync(turn, cancellationToken)).ReplyText);
{
var calendarReply = (await buildCalendarDecisionAsync(turn, cancellationToken)).ReplyText;
if (!string.IsNullOrWhiteSpace(calendarReply))
{
reportSections.Add(calendarReply);
var calendarOutro = ChooseShortestTemplate(catalog.CalendarOutroReplies);
if (!string.IsNullOrWhiteSpace(calendarOutro))
reportSections.Add(RenderPersonalReportTemplate(calendarOutro!, userName));
}
}
if (toggles.CommuteEnabled)
{
var commuteReply = (await buildCommuteDecisionAsync(turn, cancellationToken)).ReplyText;
reportSections.Add(ChooseFirstSentence(commuteReply));
var commuteSnippet = ChooseFirstSentence(commuteReply);
if (!string.IsNullOrWhiteSpace(commuteSnippet))
reportSections.Add(commuteSnippet);
}
if (toggles.NewsEnabled)
@@ -717,6 +729,25 @@ internal static class PersonalReportOrchestrator
return string.IsNullOrWhiteSpace(firstSentence) ? value.Trim() : firstSentence;
}
private static string ChooseFirstTwoSentences(string value)
{
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
var segments = value
.Split(['.', '!', '?'], StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Take(2)
.ToArray();
if (segments.Length == 0) return string.Empty;
var joined = string.Join(". ", segments);
return value.TrimEnd().EndsWith(".", StringComparison.Ordinal) ||
value.TrimEnd().EndsWith("!", StringComparison.Ordinal) ||
value.TrimEnd().EndsWith("?", StringComparison.Ordinal)
? $"{joined}."
: joined;
}
private static string? ChooseShortestTemplate(IEnumerable<string> templates)
{
var selected = templates

View File

@@ -1900,8 +1900,7 @@ public sealed class JiboInteractionServiceTests
Assert.Contains(
"For your weather. In Boston, U.S., it's light rain and 61 degrees Fahrenheit. Today's high is 65, and the low is 54.",
decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.Contains("commute", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.Contains("And that's it.", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.Contains("news", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
Assert.True(StripMarkup(decision.ReplyText).Length < 500,
$"Personal report speech was still too long: {StripMarkup(decision.ReplyText).Length} chars.");
@@ -1951,6 +1950,7 @@ public sealed class JiboInteractionServiceTests
Assert.Equal("personal_report_delivered", decision.IntentName);
Assert.Contains("Your calendar says get personal report from jibo, at 6:00 p.m.", decision.ReplyText,
StringComparison.OrdinalIgnoreCase);
Assert.Contains("calendar", decision.ReplyText, StringComparison.OrdinalIgnoreCase);
}
[Fact]

View File

@@ -4878,7 +4878,7 @@ public sealed class JiboWebSocketServiceTests
Assert.Contains("weather", stripped, StringComparison.OrdinalIgnoreCase);
Assert.Contains("calendar", stripped, StringComparison.OrdinalIgnoreCase);
Assert.Contains("news", stripped, StringComparison.OrdinalIgnoreCase);
Assert.True(stripped.Length < 500, $"Personal report speech was still too long: {stripped.Length} chars.");
Assert.True(stripped.Length < 600, $"Personal report speech was still too long: {stripped.Length} chars.");
}
[Fact]