@rajat-rastogi/maestro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +254 -0
  3. package/defaults/agents/documentation.txt +18 -0
  4. package/defaults/agents/implementation.txt +16 -0
  5. package/defaults/agents/quality.txt +19 -0
  6. package/defaults/agents/simplification.txt +19 -0
  7. package/defaults/agents/testing.txt +16 -0
  8. package/defaults/config +46 -0
  9. package/defaults/plan-tips.md +50 -0
  10. package/defaults/prompts/finalize.txt +14 -0
  11. package/defaults/prompts/hint_analysis.txt +38 -0
  12. package/defaults/prompts/plan_create.txt +36 -0
  13. package/defaults/prompts/review_first.txt +37 -0
  14. package/defaults/prompts/review_second.txt +36 -0
  15. package/defaults/prompts/task.txt +23 -0
  16. package/dist/backend/backend.d.ts +29 -0
  17. package/dist/backend/backend.d.ts.map +1 -0
  18. package/dist/backend/backend.js +9 -0
  19. package/dist/backend/backend.js.map +1 -0
  20. package/dist/backend/claude.d.ts +12 -0
  21. package/dist/backend/claude.d.ts.map +1 -0
  22. package/dist/backend/claude.js +155 -0
  23. package/dist/backend/claude.js.map +1 -0
  24. package/dist/backend/copilot.d.ts +11 -0
  25. package/dist/backend/copilot.d.ts.map +1 -0
  26. package/dist/backend/copilot.js +110 -0
  27. package/dist/backend/copilot.js.map +1 -0
  28. package/dist/backend/factory.d.ts +4 -0
  29. package/dist/backend/factory.d.ts.map +1 -0
  30. package/dist/backend/factory.js +13 -0
  31. package/dist/backend/factory.js.map +1 -0
  32. package/dist/config/configserver.d.ts +9 -0
  33. package/dist/config/configserver.d.ts.map +1 -0
  34. package/dist/config/configserver.js +141 -0
  35. package/dist/config/configserver.js.map +1 -0
  36. package/dist/config/dump.d.ts +2 -0
  37. package/dist/config/dump.d.ts.map +1 -0
  38. package/dist/config/dump.js +24 -0
  39. package/dist/config/dump.js.map +1 -0
  40. package/dist/config/loader.d.ts +11 -0
  41. package/dist/config/loader.d.ts.map +1 -0
  42. package/dist/config/loader.js +119 -0
  43. package/dist/config/loader.js.map +1 -0
  44. package/dist/config/prompts.d.ts +19 -0
  45. package/dist/config/prompts.d.ts.map +1 -0
  46. package/dist/config/prompts.js +128 -0
  47. package/dist/config/prompts.js.map +1 -0
  48. package/dist/config/reset.d.ts +3 -0
  49. package/dist/config/reset.d.ts.map +1 -0
  50. package/dist/config/reset.js +23 -0
  51. package/dist/config/reset.js.map +1 -0
  52. package/dist/config/template.d.ts +5 -0
  53. package/dist/config/template.d.ts.map +1 -0
  54. package/dist/config/template.js +11 -0
  55. package/dist/config/template.js.map +1 -0
  56. package/dist/config/types.d.ts +35 -0
  57. package/dist/config/types.d.ts.map +1 -0
  58. package/dist/config/types.js +42 -0
  59. package/dist/config/types.js.map +1 -0
  60. package/dist/config/write.d.ts +5 -0
  61. package/dist/config/write.d.ts.map +1 -0
  62. package/dist/config/write.js +59 -0
  63. package/dist/config/write.js.map +1 -0
  64. package/dist/dashboard/assets/config.html +1012 -0
  65. package/dist/dashboard/assets/dashboard.html +871 -0
  66. package/dist/dashboard/assets/help.html +657 -0
  67. package/dist/dashboard/assets.d.ts +2 -0
  68. package/dist/dashboard/assets.d.ts.map +1 -0
  69. package/dist/dashboard/assets.js +5 -0
  70. package/dist/dashboard/assets.js.map +1 -0
  71. package/dist/dashboard/event-bus.d.ts +11 -0
  72. package/dist/dashboard/event-bus.d.ts.map +1 -0
  73. package/dist/dashboard/event-bus.js +4 -0
  74. package/dist/dashboard/event-bus.js.map +1 -0
  75. package/dist/dashboard/replay-parser.d.ts +6 -0
  76. package/dist/dashboard/replay-parser.d.ts.map +1 -0
  77. package/dist/dashboard/replay-parser.js +56 -0
  78. package/dist/dashboard/replay-parser.js.map +1 -0
  79. package/dist/dashboard/server.d.ts +14 -0
  80. package/dist/dashboard/server.d.ts.map +1 -0
  81. package/dist/dashboard/server.js +178 -0
  82. package/dist/dashboard/server.js.map +1 -0
  83. package/dist/dashboard/watcher.d.ts +17 -0
  84. package/dist/dashboard/watcher.d.ts.map +1 -0
  85. package/dist/dashboard/watcher.js +73 -0
  86. package/dist/dashboard/watcher.js.map +1 -0
  87. package/dist/executor/hints.d.ts +21 -0
  88. package/dist/executor/hints.d.ts.map +1 -0
  89. package/dist/executor/hints.js +102 -0
  90. package/dist/executor/hints.js.map +1 -0
  91. package/dist/executor/task.d.ts +19 -0
  92. package/dist/executor/task.d.ts.map +1 -0
  93. package/dist/executor/task.js +119 -0
  94. package/dist/executor/task.js.map +1 -0
  95. package/dist/executor/validation.d.ts +18 -0
  96. package/dist/executor/validation.d.ts.map +1 -0
  97. package/dist/executor/validation.js +73 -0
  98. package/dist/executor/validation.js.map +1 -0
  99. package/dist/git/branch.d.ts +23 -0
  100. package/dist/git/branch.d.ts.map +1 -0
  101. package/dist/git/branch.js +64 -0
  102. package/dist/git/branch.js.map +1 -0
  103. package/dist/git/commit.d.ts +21 -0
  104. package/dist/git/commit.d.ts.map +1 -0
  105. package/dist/git/commit.js +37 -0
  106. package/dist/git/commit.js.map +1 -0
  107. package/dist/git/diff.d.ts +15 -0
  108. package/dist/git/diff.d.ts.map +1 -0
  109. package/dist/git/diff.js +26 -0
  110. package/dist/git/diff.js.map +1 -0
  111. package/dist/git/git.d.ts +9 -0
  112. package/dist/git/git.d.ts.map +1 -0
  113. package/dist/git/git.js +20 -0
  114. package/dist/git/git.js.map +1 -0
  115. package/dist/git/gitignore.d.ts +2 -0
  116. package/dist/git/gitignore.d.ts.map +1 -0
  117. package/dist/git/gitignore.js +66 -0
  118. package/dist/git/gitignore.js.map +1 -0
  119. package/dist/git/worktree.d.ts +3 -0
  120. package/dist/git/worktree.d.ts.map +1 -0
  121. package/dist/git/worktree.js +17 -0
  122. package/dist/git/worktree.js.map +1 -0
  123. package/dist/main.d.ts +3 -0
  124. package/dist/main.d.ts.map +1 -0
  125. package/dist/main.js +212 -0
  126. package/dist/main.js.map +1 -0
  127. package/dist/orchestrator/orchestrator.d.ts +21 -0
  128. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  129. package/dist/orchestrator/orchestrator.js +218 -0
  130. package/dist/orchestrator/orchestrator.js.map +1 -0
  131. package/dist/plan/creator.d.ts +27 -0
  132. package/dist/plan/creator.d.ts.map +1 -0
  133. package/dist/plan/creator.js +251 -0
  134. package/dist/plan/creator.js.map +1 -0
  135. package/dist/plan/parser.d.ts +11 -0
  136. package/dist/plan/parser.d.ts.map +1 -0
  137. package/dist/plan/parser.js +151 -0
  138. package/dist/plan/parser.js.map +1 -0
  139. package/dist/plan/types.d.ts +23 -0
  140. package/dist/plan/types.d.ts.map +1 -0
  141. package/dist/plan/types.js +2 -0
  142. package/dist/plan/types.js.map +1 -0
  143. package/dist/plan/updater.d.ts +16 -0
  144. package/dist/plan/updater.d.ts.map +1 -0
  145. package/dist/plan/updater.js +59 -0
  146. package/dist/plan/updater.js.map +1 -0
  147. package/dist/progress/colors.d.ts +9 -0
  148. package/dist/progress/colors.d.ts.map +1 -0
  149. package/dist/progress/colors.js +39 -0
  150. package/dist/progress/colors.js.map +1 -0
  151. package/dist/progress/logger.d.ts +17 -0
  152. package/dist/progress/logger.d.ts.map +1 -0
  153. package/dist/progress/logger.js +101 -0
  154. package/dist/progress/logger.js.map +1 -0
  155. package/dist/progress/notify.d.ts +2 -0
  156. package/dist/progress/notify.d.ts.map +1 -0
  157. package/dist/progress/notify.js +37 -0
  158. package/dist/progress/notify.js.map +1 -0
  159. package/dist/progress/timestamp.d.ts +5 -0
  160. package/dist/progress/timestamp.d.ts.map +1 -0
  161. package/dist/progress/timestamp.js +13 -0
  162. package/dist/progress/timestamp.js.map +1 -0
  163. package/dist/review/agents.d.ts +18 -0
  164. package/dist/review/agents.d.ts.map +1 -0
  165. package/dist/review/agents.js +43 -0
  166. package/dist/review/agents.js.map +1 -0
  167. package/dist/review/pipeline.d.ts +36 -0
  168. package/dist/review/pipeline.d.ts.map +1 -0
  169. package/dist/review/pipeline.js +210 -0
  170. package/dist/review/pipeline.js.map +1 -0
  171. package/dist/sea.d.ts +19 -0
  172. package/dist/sea.d.ts.map +1 -0
  173. package/dist/sea.js +41 -0
  174. package/dist/sea.js.map +1 -0
  175. package/package.json +57 -0
@@ -0,0 +1,119 @@
1
+ import * as path from 'path';
2
+ import { markTaskComplete, reloadPlan } from '../plan/updater.js';
3
+ import { loadPrompt } from '../config/prompts.js';
4
+ import { expandTemplate } from '../config/template.js';
5
+ import { stageAndCommit, taskCommitMessage, hasChanges } from '../git/commit.js';
6
+ import { git } from '../git/git.js';
7
+ import { addNoisyArtifactPatterns } from '../git/gitignore.js';
8
+ import { runValidationCommands } from './validation.js';
9
+ import { analyzeValidationFailure, displayHint } from './hints.js';
10
+ export class TaskExecutor {
11
+ opts;
12
+ constructor(opts) {
13
+ this.opts = opts;
14
+ }
15
+ async executeTask(plan, task) {
16
+ const { config, backend, logger, cwd } = this.opts;
17
+ const maxAttempts = config.task_retry_count + 1;
18
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
19
+ if (attempt > 1) {
20
+ logger.warn(`Retrying task ${task.index} (attempt ${attempt}/${maxAttempts})...`);
21
+ }
22
+ try {
23
+ await this.runTaskSession(plan, task);
24
+ }
25
+ catch (err) {
26
+ // Re-throw auth errors immediately — no point retrying
27
+ if (err instanceof Error && err.name === 'AIProviderError') {
28
+ throw err;
29
+ }
30
+ if (attempt === maxAttempts)
31
+ throw err;
32
+ logger.warn(`Task ${task.index} backend error: ${err instanceof Error ? err.message : String(err)}`);
33
+ continue;
34
+ }
35
+ // Reload plan to pick up checkbox updates made by Claude
36
+ reloadPlan(plan);
37
+ // Run validation commands (global + per-task)
38
+ const allValidationCommands = [
39
+ ...plan.validationCommands,
40
+ ...(task.validationCommands ?? []),
41
+ ];
42
+ if (allValidationCommands.length > 0) {
43
+ logger.log('Running validation commands...', 'task');
44
+ const summary = await runValidationCommands(allValidationCommands, cwd, config.validation_timeout_ms);
45
+ for (const result of summary.results) {
46
+ if (result.passed) {
47
+ logger.log(` ✓ ${result.command}`, 'task');
48
+ }
49
+ else {
50
+ const label = result.timedOut ? 'TIMEOUT' : `exit ${result.exitCode}`;
51
+ logger.error(` ✗ ${result.command} (${label})`);
52
+ if (result.stdout)
53
+ logger.error(` stdout: ${result.stdout.slice(0, 500)}`);
54
+ if (result.stderr)
55
+ logger.error(` stderr: ${result.stderr.slice(0, 500)}`);
56
+ }
57
+ }
58
+ if (!summary.allPassed) {
59
+ if (attempt === maxAttempts) {
60
+ const hint = await analyzeValidationFailure(summary.results, plan, task, backend, config, logger);
61
+ if (hint)
62
+ displayHint(logger, hint);
63
+ throw new Error(`Task ${task.index} validation failed after ${maxAttempts} attempt(s).`);
64
+ }
65
+ logger.warn(`Validation failed, will retry...`);
66
+ continue;
67
+ }
68
+ }
69
+ // Mark checkboxes complete in plan file (if Claude didn't already)
70
+ markTaskComplete(plan, task);
71
+ // Commit
72
+ if (hasChanges(cwd)) {
73
+ // Auto-update .gitignore for well-known build artifacts before staging
74
+ const statusOutput = git(['status', '--porcelain'], cwd).stdout;
75
+ const addedPatterns = addNoisyArtifactPatterns(statusOutput, cwd);
76
+ if (addedPatterns.length > 0) {
77
+ logger.warn(`Auto-added to .gitignore: ${addedPatterns.join(', ')}`);
78
+ }
79
+ const msg = taskCommitMessage(task.index, task.title);
80
+ stageAndCommit(msg, cwd);
81
+ logger.log(`Committed: ${msg}`, 'task');
82
+ }
83
+ else {
84
+ logger.warn(`Task ${task.index}: no file changes to commit.`);
85
+ }
86
+ return; // success
87
+ }
88
+ }
89
+ async runTaskSession(plan, task) {
90
+ const { config, backend, logger, defaultBranch, progressFilePath, cwd } = this.opts;
91
+ const promptTemplate = loadPrompt('task', config);
92
+ const prompt = expandTemplate(promptTemplate, {
93
+ PLAN_FILE: path.resolve(plan.filePath),
94
+ GOAL: plan.goal,
95
+ PROGRESS_FILE: progressFilePath,
96
+ DEFAULT_BRANCH: defaultBranch,
97
+ TASK_INDEX: task.index,
98
+ TASK_TITLE: task.title,
99
+ TASK_CONTENT: task.rawText,
100
+ });
101
+ await backend.run(prompt, (line) => {
102
+ if (line.type === 'text' && line.text.trim()) {
103
+ // Split multi-line text blocks into individual logged lines
104
+ for (const textLine of line.text.split('\n')) {
105
+ if (textLine.trim()) {
106
+ logger.log(textLine, 'task');
107
+ }
108
+ }
109
+ }
110
+ else if (line.type === 'error') {
111
+ logger.error(line.text);
112
+ }
113
+ else if (line.type === 'debug' && config.debug) {
114
+ logger.debug(line.text);
115
+ }
116
+ });
117
+ }
118
+ }
119
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/executor/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface ValidationResult {
2
+ command: string;
3
+ exitCode: number;
4
+ stdout: string;
5
+ stderr: string;
6
+ passed: boolean;
7
+ timedOut?: boolean;
8
+ }
9
+ export interface ValidationSummary {
10
+ allPassed: boolean;
11
+ results: ValidationResult[];
12
+ }
13
+ /**
14
+ * Run all validation commands and return individual and overall results.
15
+ * All commands run even if earlier ones fail (to collect all errors).
16
+ */
17
+ export declare function runValidationCommands(commands: string[], cwd?: string, timeout?: number): Promise<ValidationSummary>;
18
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/executor/validation.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAAE,EAClB,GAAG,GAAE,MAAsB,EAC3B,OAAO,SAAQ,GACd,OAAO,CAAC,iBAAiB,CAAC,CAY5B"}
@@ -0,0 +1,73 @@
1
+ import { spawn } from 'child_process';
2
+ /**
3
+ * Run all validation commands and return individual and overall results.
4
+ * All commands run even if earlier ones fail (to collect all errors).
5
+ */
6
+ export async function runValidationCommands(commands, cwd = process.cwd(), timeout = 60000) {
7
+ const results = [];
8
+ for (const command of commands) {
9
+ const result = await runCommand(command, cwd, timeout);
10
+ results.push(result);
11
+ }
12
+ return {
13
+ allPassed: results.every(r => r.passed),
14
+ results,
15
+ };
16
+ }
17
+ function runCommand(command, cwd, timeout) {
18
+ return new Promise((resolve) => {
19
+ const proc = spawn(command, [], {
20
+ cwd,
21
+ shell: true, // use shell so npm/go/dotnet etc. work on Windows
22
+ stdio: ['ignore', 'pipe', 'pipe'],
23
+ windowsHide: true,
24
+ });
25
+ let stdout = '';
26
+ let stderr = '';
27
+ let timedOut = false;
28
+ const timer = timeout > 0
29
+ ? setTimeout(() => {
30
+ timedOut = true;
31
+ proc.kill();
32
+ }, timeout)
33
+ : undefined;
34
+ proc.stdout.on('data', (chunk) => { stdout += chunk.toString('utf8'); });
35
+ proc.stderr.on('data', (chunk) => { stderr += chunk.toString('utf8'); });
36
+ proc.on('close', () => {
37
+ if (timer)
38
+ clearTimeout(timer);
39
+ if (timedOut) {
40
+ resolve({
41
+ command,
42
+ exitCode: 1,
43
+ stdout: stdout.trim(),
44
+ stderr: `timed out after ${timeout}ms`,
45
+ passed: false,
46
+ timedOut: true,
47
+ });
48
+ }
49
+ else {
50
+ const exitCode = proc.exitCode ?? 1;
51
+ resolve({
52
+ command,
53
+ exitCode,
54
+ stdout: stdout.trim(),
55
+ stderr: stderr.trim(),
56
+ passed: exitCode === 0,
57
+ });
58
+ }
59
+ });
60
+ proc.on('error', (err) => {
61
+ if (timer)
62
+ clearTimeout(timer);
63
+ resolve({
64
+ command,
65
+ exitCode: 1,
66
+ stdout: '',
67
+ stderr: `Spawn error: ${err.message}`,
68
+ passed: false,
69
+ });
70
+ });
71
+ });
72
+ }
73
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/executor/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Derive a branch name from a plan filename.
3
+ * docs/plans/add-jwt-authentication.md → feature/add-jwt-authentication
4
+ */
5
+ export declare function branchNameFromPlan(planFile: string): string;
6
+ /**
7
+ * Create and checkout a new branch, or checkout if it already exists.
8
+ */
9
+ export declare function createOrCheckoutBranch(branchName: string, cwd?: string): void;
10
+ /**
11
+ * Get current branch name.
12
+ */
13
+ export declare function getCurrentBranch(cwd?: string): string;
14
+ /**
15
+ * Auto-detect the default branch (main, master, or from remote HEAD).
16
+ * Returns empty string if detection fails.
17
+ */
18
+ export declare function detectDefaultBranch(cwd?: string): string;
19
+ /**
20
+ * Get the short commit hash of HEAD.
21
+ */
22
+ export declare function getShortCommitHash(cwd?: string): string;
23
+ //# sourceMappingURL=branch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch.d.ts","sourceRoot":"","sources":["../../src/git/branch.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAQ5F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEpE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAevE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAGtE"}
@@ -0,0 +1,64 @@
1
+ import * as path from 'path';
2
+ import { git, gitRequired } from './git.js';
3
+ /**
4
+ * Derive a branch name from a plan filename.
5
+ * docs/plans/add-jwt-authentication.md → feature/add-jwt-authentication
6
+ */
7
+ export function branchNameFromPlan(planFile) {
8
+ const base = path.basename(planFile, '.md');
9
+ // Sanitize: lowercase, replace spaces/underscores with hyphens, strip unsafe chars
10
+ const sanitized = base
11
+ .toLowerCase()
12
+ .replace(/[\s_]+/g, '-')
13
+ .replace(/[^a-z0-9-]/g, '')
14
+ .replace(/-+/g, '-')
15
+ .replace(/^-|-$/g, '');
16
+ return `feature/${sanitized}`;
17
+ }
18
+ /**
19
+ * Create and checkout a new branch, or checkout if it already exists.
20
+ */
21
+ export function createOrCheckoutBranch(branchName, cwd = process.cwd()) {
22
+ // Check if branch exists locally
23
+ const existing = git(['branch', '--list', branchName], cwd);
24
+ if (existing.stdout.includes(branchName)) {
25
+ gitRequired(['checkout', branchName], cwd);
26
+ }
27
+ else {
28
+ gitRequired(['checkout', '-b', branchName], cwd);
29
+ }
30
+ }
31
+ /**
32
+ * Get current branch name.
33
+ */
34
+ export function getCurrentBranch(cwd = process.cwd()) {
35
+ return gitRequired(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
36
+ }
37
+ /**
38
+ * Auto-detect the default branch (main, master, or from remote HEAD).
39
+ * Returns empty string if detection fails.
40
+ */
41
+ export function detectDefaultBranch(cwd = process.cwd()) {
42
+ // Try to read from remote HEAD symref
43
+ const remoteHead = git(['symbolic-ref', 'refs/remotes/origin/HEAD'], cwd);
44
+ if (remoteHead.success && remoteHead.stdout) {
45
+ const m = remoteHead.stdout.match(/refs\/remotes\/origin\/(.+)/);
46
+ if (m)
47
+ return m[1];
48
+ }
49
+ // Fallback: check if 'main' or 'master' exists
50
+ for (const candidate of ['main', 'master']) {
51
+ const r = git(['rev-parse', '--verify', candidate], cwd);
52
+ if (r.success)
53
+ return candidate;
54
+ }
55
+ return 'main';
56
+ }
57
+ /**
58
+ * Get the short commit hash of HEAD.
59
+ */
60
+ export function getShortCommitHash(cwd = process.cwd()) {
61
+ const result = git(['rev-parse', '--short', 'HEAD'], cwd);
62
+ return result.success ? result.stdout : 'unknown';
63
+ }
64
+ //# sourceMappingURL=branch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch.js","sourceRoot":"","sources":["../../src/git/branch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5C,mFAAmF;IACnF,MAAM,SAAS,GAAG,IAAI;SACnB,WAAW,EAAE;SACb,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;SAC1B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,WAAW,SAAS,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACpF,iCAAiC;IACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5D,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,WAAW,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,OAAO,WAAW,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC7D,sCAAsC;IACtC,MAAM,UAAU,GAAG,GAAG,CAAC,CAAC,cAAc,EAAE,0BAA0B,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1E,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjE,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACpD,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Stage all changes and create a commit.
3
+ */
4
+ export declare function stageAndCommit(message: string, cwd?: string): void;
5
+ /**
6
+ * Format a task completion commit message.
7
+ */
8
+ export declare function taskCommitMessage(taskIndex: string, taskTitle: string): string;
9
+ /**
10
+ * Format a review fix commit message.
11
+ */
12
+ export declare function reviewCommitMessage(phase: 'first' | 'second', iteration: number): string;
13
+ /**
14
+ * Push a branch to origin.
15
+ */
16
+ export declare function pushBranch(branchName: string, cwd?: string): void;
17
+ /**
18
+ * Check if there are any staged or unstaged changes to commit.
19
+ */
20
+ export declare function hasChanges(cwd?: string): boolean;
21
+ //# sourceMappingURL=commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../src/git/commit.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAGjF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKxF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CAEhF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAG/D"}
@@ -0,0 +1,37 @@
1
+ import { gitRequired } from './git.js';
2
+ /**
3
+ * Stage all changes and create a commit.
4
+ */
5
+ export function stageAndCommit(message, cwd = process.cwd()) {
6
+ gitRequired(['add', '-A'], cwd);
7
+ gitRequired(['commit', '-m', message], cwd);
8
+ }
9
+ /**
10
+ * Format a task completion commit message.
11
+ */
12
+ export function taskCommitMessage(taskIndex, taskTitle) {
13
+ return `feat: Task ${taskIndex} — ${taskTitle} [maestro]`;
14
+ }
15
+ /**
16
+ * Format a review fix commit message.
17
+ */
18
+ export function reviewCommitMessage(phase, iteration) {
19
+ if (phase === 'first') {
20
+ return `fix(review): first review pass ${iteration} [maestro]`;
21
+ }
22
+ return `fix(review): second review pass ${iteration} [maestro]`;
23
+ }
24
+ /**
25
+ * Push a branch to origin.
26
+ */
27
+ export function pushBranch(branchName, cwd = process.cwd()) {
28
+ gitRequired(['push', '-u', 'origin', branchName], cwd);
29
+ }
30
+ /**
31
+ * Check if there are any staged or unstaged changes to commit.
32
+ */
33
+ export function hasChanges(cwd = process.cwd()) {
34
+ const result = gitRequired(['status', '--porcelain'], cwd);
35
+ return result.trim().length > 0;
36
+ }
37
+ //# sourceMappingURL=commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/git/commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACzE,WAAW,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAChC,WAAW,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,SAAiB;IACpE,OAAO,cAAc,SAAS,MAAM,SAAS,YAAY,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAyB,EAAE,SAAiB;IAC9E,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,kCAAkC,SAAS,YAAY,CAAC;IACjE,CAAC;IACD,OAAO,mCAAmC,SAAS,YAAY,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,UAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACxE,WAAW,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACpD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Get the full diff of the current branch against the base branch.
3
+ * Used as context for review prompts.
4
+ */
5
+ export declare function getBranchDiff(baseBranch: string, cwd?: string): string;
6
+ /**
7
+ * Get the diff of uncommitted changes (working tree + staged).
8
+ * Used on subsequent review iterations.
9
+ */
10
+ export declare function getUncommittedDiff(cwd?: string): string;
11
+ /**
12
+ * Get a stat summary of changed files for logging.
13
+ */
14
+ export declare function getDiffStat(baseBranch: string, cwd?: string): string;
15
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/git/diff.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAGrF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAItE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAGnF"}
@@ -0,0 +1,26 @@
1
+ import { git } from './git.js';
2
+ /**
3
+ * Get the full diff of the current branch against the base branch.
4
+ * Used as context for review prompts.
5
+ */
6
+ export function getBranchDiff(baseBranch, cwd = process.cwd()) {
7
+ const result = git(['diff', `${baseBranch}...HEAD`], cwd);
8
+ return result.stdout;
9
+ }
10
+ /**
11
+ * Get the diff of uncommitted changes (working tree + staged).
12
+ * Used on subsequent review iterations.
13
+ */
14
+ export function getUncommittedDiff(cwd = process.cwd()) {
15
+ const staged = git(['diff', '--cached'], cwd);
16
+ const unstaged = git(['diff'], cwd);
17
+ return [staged.stdout, unstaged.stdout].filter(Boolean).join('\n');
18
+ }
19
+ /**
20
+ * Get a stat summary of changed files for logging.
21
+ */
22
+ export function getDiffStat(baseBranch, cwd = process.cwd()) {
23
+ const result = git(['diff', '--stat', `${baseBranch}...HEAD`], cwd);
24
+ return result.stdout;
25
+ }
26
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/git/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAC3E,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,UAAU,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACpC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACzE,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface GitResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ success: boolean;
6
+ }
7
+ export declare function git(args: string[], cwd?: string): GitResult;
8
+ export declare function gitRequired(args: string[], cwd?: string): string;
9
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/git/git.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,SAAS,CAY1E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAM/E"}
@@ -0,0 +1,20 @@
1
+ import { spawnSync } from 'child_process';
2
+ export function git(args, cwd = process.cwd()) {
3
+ const result = spawnSync('git', args, {
4
+ cwd,
5
+ encoding: 'utf8',
6
+ windowsHide: true,
7
+ });
8
+ const stdout = (result.stdout ?? '').trim();
9
+ const stderr = (result.stderr ?? '').trim();
10
+ const exitCode = result.status ?? 1;
11
+ return { stdout, stderr, exitCode, success: exitCode === 0 };
12
+ }
13
+ export function gitRequired(args, cwd = process.cwd()) {
14
+ const result = git(args, cwd);
15
+ if (!result.success) {
16
+ throw new Error(`git ${args.join(' ')} failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
17
+ }
18
+ return result.stdout;
19
+ }
20
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/git/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS1C,MAAM,UAAU,GAAG,CAAC,IAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QACpC,GAAG;QACH,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IAEpC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,KAAK,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACrE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,QAAQ,MAAM,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/G,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function addNoisyArtifactPatterns(porcelainOutput: string, cwd: string): string[];
2
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/git/gitignore.ts"],"names":[],"mappings":"AAgCA,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA2CvF"}
@@ -0,0 +1,66 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ const NOISY_PATTERNS = [
4
+ 'node_modules/', // npm/yarn/pnpm packages
5
+ '__pycache__/', // Python bytecode cache
6
+ '*.pyc', // Python compiled files
7
+ '.venv/', // Python virtual environment
8
+ 'venv/', // Python virtual environment (alternate name)
9
+ '.DS_Store', // macOS Finder metadata
10
+ 'Thumbs.db', // Windows thumbnail cache
11
+ '*.tsbuildinfo', // TypeScript incremental build info
12
+ ];
13
+ function normalize(s) {
14
+ return s.endsWith('/') ? s.slice(0, -1) : s;
15
+ }
16
+ function matchesPattern(entry, pattern) {
17
+ if (pattern.startsWith('*.')) {
18
+ // Glob: *.ext
19
+ const ext = pattern.slice(1); // e.g. ".pyc"
20
+ return path.basename(entry).endsWith(ext);
21
+ }
22
+ else if (pattern.endsWith('/')) {
23
+ // Directory pattern
24
+ return normalize(entry) === normalize(pattern);
25
+ }
26
+ else {
27
+ // Exact match on basename
28
+ return path.basename(entry) === pattern;
29
+ }
30
+ }
31
+ export function addNoisyArtifactPatterns(porcelainOutput, cwd) {
32
+ // Extract untracked paths from `git status --porcelain`
33
+ const untracked = porcelainOutput
34
+ .split('\n')
35
+ .filter(line => line.startsWith('?? '))
36
+ .map(line => line.slice(3).trim());
37
+ // Find which NOISY_PATTERNS are triggered by any untracked path
38
+ const triggered = NOISY_PATTERNS.filter(pattern => untracked.some(entry => matchesPattern(entry, pattern)));
39
+ if (triggered.length === 0)
40
+ return [];
41
+ // Read existing .gitignore
42
+ const gitignorePath = path.join(cwd, '.gitignore');
43
+ let existing = '';
44
+ try {
45
+ existing = fs.readFileSync(gitignorePath, 'utf8');
46
+ }
47
+ catch {
48
+ // File doesn't exist yet — that's fine
49
+ }
50
+ // Build set of normalized existing entries
51
+ const existingNormalized = new Set(existing
52
+ .split('\n')
53
+ .map(line => line.trim())
54
+ .filter(line => line.length > 0 && !line.startsWith('#'))
55
+ .map(normalize));
56
+ // Filter to patterns not already covered
57
+ const toAdd = triggered.filter(p => !existingNormalized.has(normalize(p)));
58
+ if (toAdd.length === 0)
59
+ return [];
60
+ // Append block to .gitignore
61
+ const prefix = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
62
+ const block = `${prefix}\n# Auto-added by maestro — build artifacts\n${toAdd.join('\n')}\n`;
63
+ fs.appendFileSync(gitignorePath, block, 'utf8');
64
+ return toAdd;
65
+ }
66
+ //# sourceMappingURL=gitignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/git/gitignore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function createWorktree(branchName: string, cwd: string): string;
2
+ export declare function removeWorktree(worktreePath: string, cwd: string): void;
3
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/git/worktree.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAWtE;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtE"}
@@ -0,0 +1,17 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs';
3
+ import { git, gitRequired } from './git.js';
4
+ export function createWorktree(branchName, cwd) {
5
+ const worktreePath = path.join(cwd, '.maestro', 'worktrees', branchName.replace(/\//g, '-'));
6
+ fs.mkdirSync(path.dirname(worktreePath), { recursive: true });
7
+ // Try create new branch in worktree; fall back to checkout if branch exists
8
+ const result = git(['worktree', 'add', '-b', branchName, worktreePath], cwd);
9
+ if (!result.success) {
10
+ gitRequired(['worktree', 'add', worktreePath, branchName], cwd);
11
+ }
12
+ return worktreePath;
13
+ }
14
+ export function removeWorktree(worktreePath, cwd) {
15
+ git(['worktree', 'remove', '--force', worktreePath], cwd);
16
+ }
17
+ //# sourceMappingURL=worktree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/git/worktree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,GAAW;IAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,EACzD,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,4EAA4E;IAC5E,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,WAAW,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,YAAoB,EAAE,GAAW;IAC9D,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5D,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}