Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
494 changes: 254 additions & 240 deletions docs/releases.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ describe('HistoryEntryItem', () => {
const sessionButton = screen.getByTitle('session-abc-123');
fireEvent.click(sessionButton);

expect(onOpenSessionAsTab).toHaveBeenCalledWith('session-abc-123');
expect(onOpenSessionAsTab).toHaveBeenCalledWith('session-abc-123', '/test/project');
});

it('shows elapsed time when present', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/renderer/components/HistoryPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1135,7 +1135,7 @@ describe('HistoryPanel', () => {

fireEvent.click(screen.getByText('ABC12345'));

expect(onOpenSessionAsTab).toHaveBeenCalledWith('abc12345-def-789');
expect(onOpenSessionAsTab).toHaveBeenCalledWith('abc12345-def-789', '/test/project');
});

it('should render summary with truncation', async () => {
Expand Down
4 changes: 2 additions & 2 deletions src/main/storage/codex-session-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ export class CodexSessionStorage extends BaseSessionStorage {
const firstLine = content.split('\n')[0];
if (firstLine) {
const metadata = JSON.parse(firstLine) as CodexSessionMetadata;
if (metadata.id === sessionId) {
if (metadata.id === sessionId || metadata.payload?.id === sessionId) {
return filePath;
}
}
Expand Down Expand Up @@ -1242,7 +1242,7 @@ export class CodexSessionStorage extends BaseSessionStorage {
const firstLine = result.data.split('\n')[0];
if (firstLine) {
const metadata = JSON.parse(firstLine) as CodexSessionMetadata;
if (metadata.id === sessionId) {
if (metadata.id === sessionId || metadata.payload?.id === sessionId) {
return filePath;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/prompts/maestro-system-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ To recall recent work, read the file and scan the most recent entries by timesta

When a user wants an auto-run document (or playbook), create a detailed multi-document, multi-point Markdown implementation plan in the `{{AUTORUN_FOLDER}}` folder. Use the format `$PREFIX-XX.md`, where `XX` is the two-digit phase number (01, 02, etc.) and `$PREFIX` is the effort name. Always zero-pad phase numbers to ensure correct lexicographic sorting. Break phases by relevant context; do not mix unrelated task results in the same document. If working within a file, group and fix all type issues in that file together. If working with an MCP, keep all related tasks in the same document. Each task must be written as `- [ ] ...` so auto-run can execute and check them off with comments on completion.

**Multi-phase efforts:** When creating 3 or more phase documents for a single effort, place them in a dedicated subdirectory prefixed with today's date (e.g., `{{AUTORUN_FOLDER}}/YYYY-MM-DD-Feature-Name/FEATURE-NAME-01.md`). This allows users to add the entire folder at once and keeps related documents organized with a clear creation date.
**Multi-phase efforts:** When creating 3 or more phase documents for a single effort, place them in a single flat subdirectory directly under `{{AUTORUN_FOLDER}}`, prefixed with today's date (e.g., `{{AUTORUN_FOLDER}}/YYYY-MM-DD-Feature-Name/FEATURE-NAME-01.md`). Do NOT create nested subdirectories — all phase documents for a given effort go into one folder, never `project/feature/` nesting. This allows users to add the entire folder at once and keeps related documents organized with a clear creation date.

**Context efficiency:** Each checkbox task runs in a fresh agent context. Group logically related work under a single checkbox when: (1) tasks modify the same file(s), (2) tasks follow the same pattern/approach, or (3) understanding one task is prerequisite to the next. Keep tasks separate when they're independent or when a single task would exceed reasonable scope (~500 lines of change). A good task is self-contained and can be verified in isolation.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export const UnifiedHistoryTab = forwardRef<TabFocusHandle, UnifiedHistoryTabPro

// Navigate to a session tab — looks up sourceSessionId from the unified entry
const handleOpenSessionAsTab = useCallback(
(agentSessionId: string) => {
(agentSessionId: string, _projectPath?: string) => {
if (!onResumeSession) return;
const entry = entries.find((e) => e.agentSessionId === agentSessionId) as
| UnifiedHistoryEntry
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/components/History/HistoryEntryItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface HistoryEntryItemProps {
isSelected: boolean;
theme: Theme;
onOpenDetailModal: (entry: HistoryEntry, index: number) => void;
onOpenSessionAsTab?: (agentSessionId: string) => void;
onOpenSessionAsTab?: (agentSessionId: string, projectPath?: string) => void;
onOpenAboutModal?: () => void;
/** When true, displays the agentName field prominently in the entry header (used in unified history view) */
showAgentName?: boolean;
Expand Down Expand Up @@ -117,7 +117,7 @@ export const HistoryEntryItem = memo(function HistoryEntryItem({
<button
onClick={(e) => {
e.stopPropagation();
onOpenSessionAsTab?.(entry.agentSessionId!);
onOpenSessionAsTab?.(entry.agentSessionId!, entry.projectPath);
}}
className={`flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold transition-colors hover:opacity-80 min-w-0 flex-shrink ${entry.sessionName ? '' : 'font-mono uppercase'}`}
style={{
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/HistoryPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface HistoryPanelProps {
theme: Theme;
onJumpToAgentSession?: (agentSessionId: string) => void;
onResumeSession?: (agentSessionId: string) => void;
onOpenSessionAsTab?: (agentSessionId: string) => void;
onOpenSessionAsTab?: (agentSessionId: string, projectPath?: string) => void;
onOpenAboutModal?: () => void; // For opening About/achievements panel from history entries
// File linking props for history detail modal
fileTree?: any[];
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ interface RightPanelProps {
onResumeAfterError?: () => void;
onJumpToAgentSession?: (agentSessionId: string) => void;
onResumeSession?: (agentSessionId: string) => void;
onOpenSessionAsTab?: (agentSessionId: string) => void;
onOpenSessionAsTab?: (agentSessionId: string, projectPath?: string) => void;

// Modal handlers
onOpenAboutModal?: () => void;
Expand Down
23 changes: 13 additions & 10 deletions src/renderer/hooks/agent/useAgentSessionManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ export interface UseAgentSessionManagementReturn {
providedMessages?: LogEntry[],
sessionName?: string,
starred?: boolean,
usageStats?: UsageStats
usageStats?: UsageStats,
projectPath?: string
) => Promise<void>;
}

Expand Down Expand Up @@ -165,10 +166,14 @@ export function useAgentSessionManagement(
providedMessages?: LogEntry[],
sessionName?: string,
starred?: boolean,
usageStats?: UsageStats
usageStats?: UsageStats,
projectPath?: string
) => {
// Use projectRoot (not cwd) for consistent session storage access
if (!activeSession?.projectRoot) return;
// Need an active session for tab management
if (!activeSession) return;
// Use provided projectPath (e.g. from history entry) or fall back to activeSession.projectRoot
const resolvedProjectRoot = projectPath || activeSession.projectRoot;
if (!resolvedProjectRoot) return;

// Check if a tab with this agentSessionId already exists
const existingTab = activeSession.aiTabs?.find(
Expand All @@ -194,11 +199,11 @@ export function useAgentSessionManagement(
messages = providedMessages;
} else {
// Load the session messages using the generic agentSessions API
// Use projectRoot (not cwd) for consistent session storage access
// Use resolvedProjectRoot which may come from the history entry's projectPath
const agentId = activeSession.toolType || 'claude-code';
const result = await window.maestro.agentSessions.read(
agentId,
activeSession.projectRoot,
resolvedProjectRoot,
agentSessionId,
{ offset: 0, limit: 100 }
);
Expand All @@ -225,10 +230,8 @@ export function useAgentSessionManagement(
try {
// Look up session metadata from session origins (name, starred, contextUsage)
// Note: getSessionOrigins is still Claude-specific until we add generic origin tracking
// Use projectRoot (not cwd) for consistent session storage access
const origins = await window.maestro.claude.getSessionOrigins(
activeSession.projectRoot
);
// Use resolvedProjectRoot which may come from the history entry's projectPath
const origins = await window.maestro.claude.getSessionOrigins(resolvedProjectRoot);
const originData = origins[agentSessionId];
if (originData && typeof originData === 'object') {
if (sessionName === undefined && originData.sessionName) {
Expand Down
19 changes: 17 additions & 2 deletions src/renderer/hooks/props/useRightPanelProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,14 @@ export interface UseRightPanelPropsDeps {
handleAbortBatchOnError: () => void;
handleResumeAfterError: () => void;
handleJumpToAgentSession: (agentSessionId: string) => void;
handleResumeSession: (agentSessionId: string) => void;
handleResumeSession: (
agentSessionId: string,
providedMessages?: any[],
sessionName?: string,
starred?: boolean,
usageStats?: any,
projectPath?: string
) => void;

// Modal handlers
handleOpenAboutModal: () => void;
Expand Down Expand Up @@ -134,7 +141,15 @@ export function useRightPanelProps(deps: UseRightPanelPropsDeps) {
onResumeAfterError: deps.handleResumeAfterError,
onJumpToAgentSession: deps.handleJumpToAgentSession,
onResumeSession: deps.handleResumeSession,
onOpenSessionAsTab: deps.handleResumeSession,
onOpenSessionAsTab: (agentSessionId: string, projectPath?: string) =>
deps.handleResumeSession(
agentSessionId,
undefined,
undefined,
undefined,
undefined,
projectPath
),

// Modal handlers
onOpenAboutModal: deps.handleOpenAboutModal,
Expand Down
Loading