diff --git a/src/story-mode.ts b/src/story-mode.ts index c2550a72..4fefb620 100644 --- a/src/story-mode.ts +++ b/src/story-mode.ts @@ -1444,6 +1444,10 @@ function applyTextBudget(events: StoryEvent[]): boolean { /** Claude reporting how a check went ("All 7 tests pass"), as opposed to announcing its next step. */ const TALKS_RESULTS = /\b(pass(es|ed|ing)?|fail(s|ed|ing|ures?)?|green|clean)\b/i; +/** Claude reporting a save ("Commits are in.", "Pushed to origin."). */ +const TALKS_SAVES = /\b(commit(s|ted)?|pushed|merged|tagged)\b/i; +/** The remark that reports on a panel of this kind, if any. */ +const REPORT_TALK: Partial> = { check: TALKS_RESULTS, save: TALKS_SAVES }; const ANNOUNCES = /\b(I'll|I will|let me|let's|I'm going to|next,? I|now I)\b/i; function groupPanels(events: StoryEvent[]): { panels: DraftPanel[]; trailingSay?: string } { @@ -1463,11 +1467,13 @@ function groupPanels(events: StoryEvent[]): { panels: DraftPanel[]; trailingSay? } else { const panel: DraftPanel = { kind, events: [idx] }; // A sentence about how the check just before went belongs to that check, not to what comes next. + const talk = last ? REPORT_TALK[last.kind] : undefined; const reportsBack = pendingSay && - last?.kind === 'check' && - (!last.balloon || !TALKS_RESULTS.test(last.balloon.text)) && - TALKS_RESULTS.test(pendingSay) && + talk && + last && + (!last.balloon || !talk.test(last.balloon.text)) && + talk.test(pendingSay) && !ANNOUNCES.test(pendingSay); if (kind === 'mission') panel.balloon = { who: 'you', text: clip(ev.label, 220) }; else if (reportsBack && last && pendingSay) last.balloon = { who: 'claude', text: pendingSay }; diff --git a/test/story-mode.test.ts b/test/story-mode.test.ts index 804324bf..4363a061 100644 --- a/test/story-mode.test.ts +++ b/test/story-mode.test.ts @@ -726,6 +726,18 @@ describe('buildStoryPage', () => { expect(turns[1].durationMs).toBeGreaterThan(0); }); + it('a remark about committing stays on the save it reports on', () => { + const page = pageOf([ + prompt('commit then test'), + ...bash('b1', 'git commit -qm a', 'Commit', 'ok'), + said('Commits are in.'), + ...bash('b2', 'pytest -q', 'Run tests', '3 passed in 0.1s'), + end(1000), + ]); + expect(page.panels.find((p) => p.kind === 'save')!.balloon?.text).toBe('Commits are in.'); + expect(page.panels.find((p) => p.kind === 'check')!.balloon).toBeUndefined(); + }); + it('a result remark replaces a step announcement on its check', () => { const page = pageOf([ prompt('steps'),