mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(story-mode): scheduled runs, work after a turn ended, and pages full of added prompts
From review round 4 (a 110 MB real session, about 23 turns, read through
all four tail steps):
- A scheduled task's run was drawn inside the /compact turn before it (96
minutes and 237 tool calls credited to "You run /compact."): its prompt is
a meta line, and work after an ended turn was appended to that turn. The
scheduled prompt now starts a turn of origin `scheduled` ("A scheduled
task starts this turn."), and work that comes more than 5 s after a turn
ended starts a turn of its own ("Claude carries on"); a line Claude Code
flushed a moment late still joins.
- A turn with seven prompts added mid-turn drew 14 panels (the cap is 12):
missions were never folded. An added prompt may now fold into a montage,
as the last resort after quiet panels and work panels, and the montage
says so ("Claude keeps going (you add 2 things): ..."); the turn's own
prompt and a question to you are never folded.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
50de4f16b3
commit
846749a912
4 files changed
+97
-12
No files matched your search
@@ -617,6 +617,72 @@ describe('buildStoryTurns', () => {
|
||||
expect(page.filesChanged).toBe(1);
|
||||
});
|
||||
|
||||
it('a scheduled task (its prompt a meta line) is a turn of its own, not part of the one before', () => {
|
||||
const turns = buildStoryTurns(
|
||||
entriesOf([
|
||||
prompt('/compact', { promptId: 'p1' }),
|
||||
prompt('<command-name>/compact</command-name>', { promptId: 'p1' }),
|
||||
prompt('<local-command-stdout>Compacted</local-command-stdout>', { promptId: 'p1' }),
|
||||
{
|
||||
type: 'system',
|
||||
subtype: 'scheduled_task_fire',
|
||||
timestamp: '2026-10-18T11:00:00.000Z',
|
||||
prompt: 'Resume the work',
|
||||
},
|
||||
prompt('Resume the work', {
|
||||
isMeta: true,
|
||||
turnOrigin: 'scheduled',
|
||||
promptSource: 'system',
|
||||
scheduledTaskId: 'abc',
|
||||
}),
|
||||
...bash('b', 'ls', 'List', 'a'),
|
||||
end(5000),
|
||||
])
|
||||
);
|
||||
expect(turns.map((t) => [t.prompt, t.origin, t.endedBy])).toEqual([
|
||||
['/compact', 'human', 'local command'],
|
||||
['Resume the work', 'scheduled', 'turn_duration'],
|
||||
]);
|
||||
expect(buildStoryPage(turns[1]).panels[0].caption.story).toBe('A scheduled task starts this turn.');
|
||||
});
|
||||
|
||||
it('work long after a turn ended is a turn of its own; a line flushed a moment late still joins', () => {
|
||||
const turns = buildStoryTurns(
|
||||
entriesOf([
|
||||
prompt('one'),
|
||||
end(1000),
|
||||
{ ...said('Late line.'), timestamp: undefined },
|
||||
{
|
||||
type: 'assistant',
|
||||
timestamp: '2026-10-18T12:00:00.000Z',
|
||||
message: { content: [{ type: 'tool_use', id: 'x', name: 'Bash', input: { command: 'ls' } }] },
|
||||
},
|
||||
])
|
||||
);
|
||||
expect(turns).toHaveLength(2);
|
||||
expect(turns[1]).toMatchObject({ origin: 'system', prompt: '', ended: false });
|
||||
expect(turns[1].events.map((e) => e.tool)).toEqual(['Bash']);
|
||||
});
|
||||
|
||||
it('a page with many prompts added mid-turn still fits, folding added prompts last', () => {
|
||||
const queued = (text: string, i: number) => ({
|
||||
type: 'attachment',
|
||||
timestamp: `2026-10-18T09:5${i}:00.000Z`,
|
||||
attachment: { type: 'queued_command', prompt: text, commandMode: 'prompt', origin: { kind: 'human' } },
|
||||
});
|
||||
const lines: unknown[] = [prompt('big job')];
|
||||
for (let i = 0; i < 8; i++) {
|
||||
lines.push(queued(`also do ${i}`, i));
|
||||
lines.push(...edit(`e${i}`, `/w/f${i}.ts`, ['+x']));
|
||||
lines.push(...bash(`b${i}`, 'npm test', 'Run tests', ' Tests 4 passed (4)'));
|
||||
}
|
||||
lines.push(end(60_000));
|
||||
const page = pageOf(lines);
|
||||
expect(page.panels.length).toBeLessThanOrEqual(STORY_LIMITS.panelsPerPage);
|
||||
expect(page.panels[0].kind).toBe('mission');
|
||||
expect(page.panels.some((p) => /you add \d+ things?/.test(p.caption.story))).toBe(true);
|
||||
});
|
||||
|
||||
it('an interrupt ends the turn', () => {
|
||||
const turns = buildStoryTurns(
|
||||
entriesOf([prompt('go'), ...bash('b', 'ls', 'List', 'a'), prompt('[Request interrupted by user]')])
|
||||
|
||||
Reference in new issue
Block a user