fix(story-mode): a remark about committing stays on its save

"Commits are in." landed on the check panel after the save it reports on;
the rule that keeps a result remark on its check now covers saves too.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-18 11:12:46 +02:00
1 parent a2db03cda5
commit ea104c8965
2 files changed
+21 -3

No files matched your search

+9 -3
View File
@@ -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<Record<StoryPanelKind, RegExp>> = { 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 };
+12
View File
@@ -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'),