(entries: MakaPiTranscriptEntry[])
| 874 | } |
| 875 | |
| 876 | function foldStoredShellRunChildren(entries: MakaPiTranscriptEntry[]): MakaPiTranscriptEntry[] { |
| 877 | const folded: MakaPiTranscriptEntry[] = []; |
| 878 | for (const entry of entries) { |
| 879 | // An errored poll never folds: its failed payload must not mutate the parent |
| 880 | // and its error card must survive replay, mirroring the live path's "failure |
| 881 | // is never swallowed" invariant. |
| 882 | if (entry.kind === 'tool' && entry.result?.kind === 'shell_run' && entry.status !== 'error') { |
| 883 | const shellRun = entry.result; |
| 884 | const parent = [...folded] |
| 885 | .reverse() |
| 886 | .find( |
| 887 | (candidate): candidate is MakaPiToolEntry => |
| 888 | candidate.kind === 'tool' && |
| 889 | candidate.toolName === 'Bash' && |
| 890 | candidate.result?.kind === 'shell_run' && |
| 891 | candidate.result.ref === shellRun.ref, |
| 892 | ); |
| 893 | if (parent) { |
| 894 | applyShellRunResult(parent, shellRun); |
| 895 | if (entry.toolName === 'Read' || entry.toolName === 'StopBackgroundTask') continue; |
| 896 | } |
| 897 | } |
| 898 | folded.push(entry); |
| 899 | } |
| 900 | return folded; |
| 901 | } |
| 902 | |
| 903 | function transcriptToolStatus(status: ToolActivityItem['status']): MakaPiToolEntry['status'] { |
| 904 | switch (status) { |
no test coverage detected