From f724ef4c8c928ec1bea3972a3719cc3b34f50b5c Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Fri, 26 Dec 2025 10:07:57 -0600 Subject: [PATCH] ## CHANGES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Refreshed Maestro tagline across README and package metadata for clarity ✨ - Reset-on-completion now writes working copies into `Runs/` folder consistently 📁 - Auto Run working-copy IPC handler updated for new `Runs/` directory naming 🧭 - Working-copy relative paths now return `Runs/...` for downstream consumers 🔗 - Preload API docs updated to reflect `Runs/` working-copy location 🧩 - AutoRunner Help Modal now points users to `Runs/` audit-log folder 🪟 - Batch processor tracking/comments updated for `Runs/` audit log behavior 🧾 - Test suite updated to expect `Runs/` working-copy paths reliably 🧪 --- README.md | 4 ++-- package.json | 2 +- .../renderer/hooks/useBatchProcessor.test.ts | 6 +++--- src/main/ipc/handlers/autorun.ts | 12 ++++++------ src/main/preload.ts | 2 +- src/renderer/components/AutoRunnerHelpModal.tsx | 2 +- src/renderer/global.d.ts | 2 +- src/renderer/hooks/batch/useBatchProcessor.ts | 14 +++++++------- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index db200d02..c118ff5a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Made with Maestro](docs/assets/made-with-maestro.svg)](https://github.com/pedramamini/Maestro) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-5865F2?logo=discord&logoColor=white)](https://discord.gg/SrBsykvG) -> Run AI coding agents autonomously for days. +> Maestro hones fractured attention into focused intent. Maestro is a cross-platform desktop app for orchestrating your fleet of AI agents and projects. It's a high-velocity solution for hackers who are juggling multiple projects in parallel. Designed for power users who live on the keyboard and rarely touch the mouse. @@ -459,7 +459,7 @@ Auto Run supports running multiple documents in sequence: 2. Click **+ Add Docs** to add more documents to the queue 3. Drag to reorder documents as needed 4. Configure options per document: - - **Reset on Completion** - Creates a working copy in `runs/` subfolder instead of modifying the original. The original document is never touched, and working copies (e.g., `TASK-1735192800000-loop-1.md`) serve as audit logs. + - **Reset on Completion** - Creates a working copy in `Runs/` subfolder instead of modifying the original. The original document is never touched, and working copies (e.g., `TASK-1735192800000-loop-1.md`) serve as audit logs. - **Duplicate** - Add the same document multiple times 5. Enable **Loop Mode** to cycle back to the first document after completing the last 6. Click **Go** to start the batch run diff --git a/package.json b/package.json index b345bbcd..a0d8a37b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "maestro", "version": "0.12.1", - "description": "Run AI coding agents autonomously for days.", + "description": "Maestro hones fractured attention into focused intent.", "main": "dist/main/index.js", "author": { "name": "Pedram Amini", diff --git a/src/__tests__/renderer/hooks/useBatchProcessor.test.ts b/src/__tests__/renderer/hooks/useBatchProcessor.test.ts index 8355d852..82f6a7ec 100644 --- a/src/__tests__/renderer/hooks/useBatchProcessor.test.ts +++ b/src/__tests__/renderer/hooks/useBatchProcessor.test.ts @@ -620,7 +620,7 @@ describe('useBatchProcessor hook', () => { // Set up window.maestro mocks mockReadDoc = vi.fn().mockResolvedValue({ success: true, content: '# Tasks\n- [ ] Task 1\n- [ ] Task 2' }); mockWriteDoc = vi.fn().mockResolvedValue({ success: true }); - mockCreateWorkingCopy = vi.fn().mockResolvedValue({ workingCopyPath: 'runs/tasks-run-1.md' }); + mockCreateWorkingCopy = vi.fn().mockResolvedValue({ workingCopyPath: 'Runs/tasks-run-1.md' }); mockStatus = vi.fn().mockResolvedValue({ stdout: '' }); mockBranch = vi.fn().mockResolvedValue({ stdout: 'main' }); mockBroadcastAutoRunState = vi.fn(); @@ -1366,7 +1366,7 @@ describe('useBatchProcessor hook', () => { describe('reset on completion', () => { it('should create working copy when resetOnCompletion is enabled', async () => { - // Note: Reset-on-completion now uses working copies in /runs/ directory + // Note: Reset-on-completion now uses working copies in /Runs/ directory // instead of modifying the original document. This preserves the original // and allows the agent to work on a copy. const sessions = [createMockSession()]; @@ -3205,7 +3205,7 @@ describe('useBatchProcessor hook', () => { describe('reset-on-completion in loop mode', () => { it('should create working copy when document has resetOnCompletion enabled', async () => { - // Note: Reset-on-completion now uses working copies in /runs/ directory + // Note: Reset-on-completion now uses working copies in /Runs/ directory // instead of modifying the original document. This preserves the original // and allows the agent to work on a copy each loop iteration. const sessions = [createMockSession()]; diff --git a/src/main/ipc/handlers/autorun.ts b/src/main/ipc/handlers/autorun.ts index 3fa248ff..2c335155 100644 --- a/src/main/ipc/handlers/autorun.ts +++ b/src/main/ipc/handlers/autorun.ts @@ -570,7 +570,7 @@ export function registerAutorunHandlers(deps: { ); // Create a working copy of a document for reset-on-completion loops - // Working copies are stored in /runs/ subdirectory with format: {name}-{timestamp}-loop-{N}.md + // Working copies are stored in /Runs/ subdirectory with format: {name}-{timestamp}-loop-{N}.md ipcMain.handle( 'autorun:createWorkingCopy', createIpcHandler( @@ -604,10 +604,10 @@ export function registerAutorunHandlers(deps: { throw new Error('Source file not found'); } - // Create runs directory (with subdirectory if needed) + // Create Runs directory (with subdirectory if needed) const runsDir = subDir - ? path.join(folderPath, 'runs', subDir) - : path.join(folderPath, 'runs'); + ? path.join(folderPath, 'Runs', subDir) + : path.join(folderPath, 'Runs'); await fs.mkdir(runsDir, { recursive: true }); // Generate working copy filename: {name}-{timestamp}-loop-{N}.md @@ -625,8 +625,8 @@ export function registerAutorunHandlers(deps: { // Return the relative path (without .md for consistency with other APIs) const relativePath = subDir - ? `runs/${subDir}/${workingCopyName.slice(0, -3)}` - : `runs/${workingCopyName.slice(0, -3)}`; + ? `Runs/${subDir}/${workingCopyName.slice(0, -3)}` + : `Runs/${workingCopyName.slice(0, -3)}`; logger.info(`Created Auto Run working copy: ${relativePath}`, LOG_CONTEXT); return { workingCopyPath: relativePath, originalPath: baseName }; diff --git a/src/main/preload.ts b/src/main/preload.ts index 32690c32..939b6de8 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -1050,7 +1050,7 @@ contextBridge.exposeInMainWorld('maestro', { deleteBackups: (folderPath: string) => ipcRenderer.invoke('autorun:deleteBackups', folderPath), // Working copy operations for reset-on-completion documents (preferred) - // Creates a copy in /runs/ subdirectory: {name}-{timestamp}-loop-{N}.md + // Creates a copy in /Runs/ subdirectory: {name}-{timestamp}-loop-{N}.md createWorkingCopy: (folderPath: string, filename: string, loopNumber: number): Promise<{ workingCopyPath: string; originalPath: string }> => ipcRenderer.invoke('autorun:createWorkingCopy', folderPath, filename, loopNumber), }, diff --git a/src/renderer/components/AutoRunnerHelpModal.tsx b/src/renderer/components/AutoRunnerHelpModal.tsx index 3efaec66..03f6f7a4 100644 --- a/src/renderer/components/AutoRunnerHelpModal.tsx +++ b/src/renderer/components/AutoRunnerHelpModal.tsx @@ -283,7 +283,7 @@ export function AutoRunnerHelpModal({ theme, onClose }: AutoRunnerHelpModalProps

Enable the reset toggle () on any document to keep it available for repeated runs. When enabled, Auto Run creates a working copy in - the runs/ subfolder and processes that copy—the original document is never modified. + the Runs/ subfolder and processes that copy—the original document is never modified.

Working copies are named with timestamps (e.g., TASK-1735192800000-loop-1.md) and diff --git a/src/renderer/global.d.ts b/src/renderer/global.d.ts index af02183d..67147b37 100644 --- a/src/renderer/global.d.ts +++ b/src/renderer/global.d.ts @@ -787,7 +787,7 @@ interface MaestroAPI { restoreBackup: (folderPath: string, filename: string) => Promise<{ success: boolean; error?: string }>; deleteBackups: (folderPath: string) => Promise<{ success: boolean; deletedCount?: number; error?: string }>; // Working copy operations for reset-on-completion documents (preferred) - // Creates a copy in /runs/ subdirectory: {name}-{timestamp}-loop-{N}.md + // Creates a copy in /Runs/ subdirectory: {name}-{timestamp}-loop-{N}.md createWorkingCopy: (folderPath: string, filename: string, loopNumber: number) => Promise<{ workingCopyPath: string; originalPath: string }>; }; // Playbooks API (saved batch run configurations) diff --git a/src/renderer/hooks/batch/useBatchProcessor.ts b/src/renderer/hooks/batch/useBatchProcessor.ts index 3ddebf41..aeef4392 100644 --- a/src/renderer/hooks/batch/useBatchProcessor.ts +++ b/src/renderer/hooks/batch/useBatchProcessor.ts @@ -557,7 +557,7 @@ export function useBatchProcessor({ const stalledDocuments: Map = new Map(); // Track working copies for reset-on-completion documents (original filename -> working copy path) - // Working copies are stored in /runs/ and serve as audit logs + // Working copies are stored in /Runs/ and serve as audit logs const workingCopies: Map = new Map(); // Helper to add final loop summary (defined here so it has access to tracking vars) @@ -643,7 +643,7 @@ export function useBatchProcessor({ let effectiveFilename = docEntry.filename; // Create working copy for reset-on-completion documents - // Working copies are stored in /runs/ and the original is never modified + // Working copies are stored in /Runs/ and the original is never modified if (docEntry.resetOnCompletion) { try { const { workingCopyPath } = await window.maestro.autorun.createWorkingCopy( @@ -912,7 +912,7 @@ export function useBatchProcessor({ // Skip document handling if this document stalled (it didn't complete normally) if (stalledDocuments.has(docEntry.filename)) { - // Working copy approach: stalled working copy stays in /runs/ as audit log + // Working copy approach: stalled working copy stays in /Runs/ as audit log // Original document is untouched, so nothing to restore workingCopies.delete(docEntry.filename); // Reset consecutive no-change counter for next document @@ -921,14 +921,14 @@ export function useBatchProcessor({ } if (skipCurrentDocumentAfterError) { - // Working copy approach: errored working copy stays in /runs/ as audit log + // Working copy approach: errored working copy stays in /Runs/ as audit log // Original document is untouched, so nothing to restore workingCopies.delete(docEntry.filename); continue; } // Document complete - for reset-on-completion docs, original is untouched - // Working copy in /runs/ serves as the audit log of this loop's work + // Working copy in /Runs/ serves as the audit log of this loop's work if (docEntry.resetOnCompletion && docTasksCompleted > 0) { // AUTORUN LOG: Document loop completed window.maestro.logger.autorun( @@ -956,7 +956,7 @@ export function useBatchProcessor({ })); } - // Clear tracking - working copy stays in /runs/ as audit log + // Clear tracking - working copy stays in /Runs/ as audit log workingCopies.delete(docEntry.filename); } else if (docEntry.resetOnCompletion) { // Document had reset enabled but no tasks were completed @@ -1104,7 +1104,7 @@ export function useBatchProcessor({ // Working copy approach: no cleanup needed // - Original documents are never modified - // - Working copies in /runs/ serve as audit logs and are kept + // - Working copies in /Runs/ serve as audit logs and are kept // - User can delete them manually if desired // Create PR if worktree was used, PR creation is enabled, and not stopped