From e5b72625482032a2924b1721873b5b8fbe9a1838 Mon Sep 17 00:00:00 2001 From: roboomp Date: Wed, 3 Jun 2026 12:46:21 +0000 Subject: [PATCH] fix(coding-agent): marked forked resume sessions Added a fork tag to child session rows in the resume picker so sessions with parentSessionPath are distinguishable from their parent. Covered the rendered picker contract with a focused component test. Fixes #1792 --- packages/coding-agent/CHANGELOG.md | 4 ++++ .../src/modes/components/session-selector.ts | 3 +++ .../components/session-selector-scope.test.ts | 24 ++++++++++++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 82be92a17..55f6e25cf 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed `/resume` rendering forked child sessions without a fork tag, making them indistinguishable from their parent when titles match ([#1792](https://github.com/can1357/oh-my-pi/issues/1792)). + ## [15.8.2] - 2026-06-03 ### Added diff --git a/packages/coding-agent/src/modes/components/session-selector.ts b/packages/coding-agent/src/modes/components/session-selector.ts index 7dc036d51..9dc2930cb 100644 --- a/packages/coding-agent/src/modes/components/session-selector.ts +++ b/packages/coding-agent/src/modes/components/session-selector.ts @@ -230,6 +230,9 @@ class SessionList implements Component { // Metadata line: date + file size (+ project dir in all-projects scope) const modified = formatDate(session.modified); let metadata = ` ${modified} ${theme.sep.dot} ${formatBytes(session.size)}`; + if (session.parentSessionPath) { + metadata += ` ${theme.sep.dot} ${theme.icon.branch} fork`; + } if (this.#showCwd && session.cwd) { metadata += ` ${theme.sep.dot} ${shortenPath(session.cwd)}`; } diff --git a/packages/coding-agent/test/modes/components/session-selector-scope.test.ts b/packages/coding-agent/test/modes/components/session-selector-scope.test.ts index a7a999dbd..a9a105ce8 100644 --- a/packages/coding-agent/test/modes/components/session-selector-scope.test.ts +++ b/packages/coding-agent/test/modes/components/session-selector-scope.test.ts @@ -3,11 +3,11 @@ import { SessionSelectorComponent } from "../../../src/modes/components/session- import { initTheme } from "../../../src/modes/theme/theme"; import type { SessionInfo } from "../../../src/session/session-manager"; -beforeAll(() => { - initTheme(); +beforeAll(async () => { + await initTheme(); }); -function createSession(id: string, title: string, cwd: string): SessionInfo { +function createSession(id: string, title: string, cwd: string, parentSessionPath?: string): SessionInfo { return { path: `${cwd}/${id}.jsonl`, id, @@ -19,6 +19,7 @@ function createSession(id: string, title: string, cwd: string): SessionInfo { size: 0, firstMessage: `${title} first message`, allMessagesText: `${title} first message`, + ...(parentSessionPath ? { parentSessionPath } : {}), }; } @@ -104,4 +105,21 @@ describe("SessionSelectorComponent scope toggle", () => { expect(rendered).toContain("(all projects)"); expect(rendered).toContain("other-project"); }); + + it("marks forked child sessions in the rendered list", () => { + const parent = createSession("root", "Incident", "/work/current"); + const child = createSession("child", "Incident", "/work/current", parent.path); + const selector = new SessionSelectorComponent( + [parent, child], + () => {}, + () => {}, + () => {}, + ); + + const rendered = selector.render(120).join("\n"); + const forkLines = rendered.split("\n").filter(line => line.includes("fork")); + + expect(forkLines).toHaveLength(1); + expect(forkLines[0]).toContain("fork"); + }); });