diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 2cf549aab..7ec5de3a2 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -1992,6 +1992,10 @@ - Changed the `todo-write` prompt to require initializing every item from a user-supplied multi-step plan as an individual todo task before execution - Changed context compaction (prune/shake) to protect reads of the active plan file the same way it already protects `skill://` reads, so the plan stays intact through automatic and manual compaction. Both the canonical `local://PLAN.md` alias and the session's current plan reference path (e.g. a titled `local://.md` after approval) are kept, tolerating read selectors and `local:/` scheme spelling. +### 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 b60b2e0af..c6f403894 100644 --- a/packages/coding-agent/src/modes/components/session-selector.ts +++ b/packages/coding-agent/src/modes/components/session-selector.ts @@ -353,6 +353,9 @@ class SessionList implements Component { if (status) { metadata += ` ${dot} ${status}`; } + if (session.parentSessionPath) { + metadata += ` ${dot} ${dim(`${theme.icon.branch} fork`)}`; + } if (this.#showCwd && session.cwd) { metadata += ` ${dot} ${dim(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 33dfdce26..f9664c1f0 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 "@oh-my-pi/pi-coding-agent/modes/compon import { initTheme } from "@oh-my-pi/pi-coding-agent/modes/theme/theme"; import type { SessionInfo } from "@oh-my-pi/pi-coding-agent/session/session-listing"; -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 } : {}), }; } @@ -116,4 +117,21 @@ describe("SessionSelectorComponent scope toggle", () => { expect(rendered).toContain("No sessions in current folder"); expect(rendered).toContain("Press Tab to view all"); }); + + 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"); + }); });