millhouse 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 (88) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +248 -0
  3. package/commands/millhouse.md +223 -0
  4. package/dist/analysis/graph-builder.d.ts +42 -0
  5. package/dist/analysis/graph-builder.d.ts.map +1 -0
  6. package/dist/analysis/graph-builder.js +98 -0
  7. package/dist/analysis/graph-builder.js.map +1 -0
  8. package/dist/analysis/issue-analyzer.d.ts +20 -0
  9. package/dist/analysis/issue-analyzer.d.ts.map +1 -0
  10. package/dist/analysis/issue-analyzer.js +167 -0
  11. package/dist/analysis/issue-analyzer.js.map +1 -0
  12. package/dist/analysis/plan-parser.d.ts +8 -0
  13. package/dist/analysis/plan-parser.d.ts.map +1 -0
  14. package/dist/analysis/plan-parser.js +112 -0
  15. package/dist/analysis/plan-parser.js.map +1 -0
  16. package/dist/cli/cleanup.d.ts +20 -0
  17. package/dist/cli/cleanup.d.ts.map +1 -0
  18. package/dist/cli/cleanup.js +186 -0
  19. package/dist/cli/cleanup.js.map +1 -0
  20. package/dist/cli/commands/clean.d.ts +2 -0
  21. package/dist/cli/commands/clean.d.ts.map +1 -0
  22. package/dist/cli/commands/clean.js +16 -0
  23. package/dist/cli/commands/clean.js.map +1 -0
  24. package/dist/cli/commands/resume.d.ts +2 -0
  25. package/dist/cli/commands/resume.d.ts.map +1 -0
  26. package/dist/cli/commands/resume.js +82 -0
  27. package/dist/cli/commands/resume.js.map +1 -0
  28. package/dist/cli/commands/run.d.ts +10 -0
  29. package/dist/cli/commands/run.d.ts.map +1 -0
  30. package/dist/cli/commands/run.js +352 -0
  31. package/dist/cli/commands/run.js.map +1 -0
  32. package/dist/cli/commands/setup.d.ts +6 -0
  33. package/dist/cli/commands/setup.d.ts.map +1 -0
  34. package/dist/cli/commands/setup.js +74 -0
  35. package/dist/cli/commands/setup.js.map +1 -0
  36. package/dist/cli/commands/status.d.ts +7 -0
  37. package/dist/cli/commands/status.d.ts.map +1 -0
  38. package/dist/cli/commands/status.js +83 -0
  39. package/dist/cli/commands/status.js.map +1 -0
  40. package/dist/cli/progress-display.d.ts +93 -0
  41. package/dist/cli/progress-display.d.ts.map +1 -0
  42. package/dist/cli/progress-display.js +318 -0
  43. package/dist/cli/progress-display.js.map +1 -0
  44. package/dist/core/orchestrator.d.ts +79 -0
  45. package/dist/core/orchestrator.d.ts.map +1 -0
  46. package/dist/core/orchestrator.js +389 -0
  47. package/dist/core/orchestrator.js.map +1 -0
  48. package/dist/core/scheduler.d.ts +72 -0
  49. package/dist/core/scheduler.d.ts.map +1 -0
  50. package/dist/core/scheduler.js +234 -0
  51. package/dist/core/scheduler.js.map +1 -0
  52. package/dist/execution/claude-runner.d.ts +41 -0
  53. package/dist/execution/claude-runner.d.ts.map +1 -0
  54. package/dist/execution/claude-runner.js +241 -0
  55. package/dist/execution/claude-runner.js.map +1 -0
  56. package/dist/execution/worktree-manager.d.ts +52 -0
  57. package/dist/execution/worktree-manager.d.ts.map +1 -0
  58. package/dist/execution/worktree-manager.js +208 -0
  59. package/dist/execution/worktree-manager.js.map +1 -0
  60. package/dist/github/client.d.ts +27 -0
  61. package/dist/github/client.d.ts.map +1 -0
  62. package/dist/github/client.js +178 -0
  63. package/dist/github/client.js.map +1 -0
  64. package/dist/github/issue-discoverer.d.ts +20 -0
  65. package/dist/github/issue-discoverer.d.ts.map +1 -0
  66. package/dist/github/issue-discoverer.js +83 -0
  67. package/dist/github/issue-discoverer.js.map +1 -0
  68. package/dist/github/label-manager.d.ts +44 -0
  69. package/dist/github/label-manager.d.ts.map +1 -0
  70. package/dist/github/label-manager.js +93 -0
  71. package/dist/github/label-manager.js.map +1 -0
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +54 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/storage/config.d.ts +4 -0
  77. package/dist/storage/config.d.ts.map +1 -0
  78. package/dist/storage/config.js +25 -0
  79. package/dist/storage/config.js.map +1 -0
  80. package/dist/storage/json-store.d.ts +20 -0
  81. package/dist/storage/json-store.d.ts.map +1 -0
  82. package/dist/storage/json-store.js +92 -0
  83. package/dist/storage/json-store.js.map +1 -0
  84. package/dist/types.d.ts +142 -0
  85. package/dist/types.d.ts.map +1 -0
  86. package/dist/types.js +36 -0
  87. package/dist/types.js.map +1 -0
  88. package/package.json +60 -0
@@ -0,0 +1,167 @@
1
+ import chalk from 'chalk';
2
+ import { query } from '@anthropic-ai/claude-code';
3
+ const BATCH_ANALYSIS_PROMPT = `Analyze these GitHub issues and determine their dependencies and execution order.
4
+
5
+ ## Issues to Analyze
6
+
7
+ {{issuesList}}
8
+
9
+ ---
10
+
11
+ ## Your Task
12
+
13
+ Analyze each issue and determine:
14
+ 1. **dependencies**: Which issues MUST be completed BEFORE this issue can start
15
+ 2. **affectedPaths**: File paths this issue will likely create or modify
16
+
17
+ Respond with ONLY a JSON array (no markdown, no explanation):
18
+ [
19
+ {
20
+ "issueNumber": 1,
21
+ "dependencies": [],
22
+ "affectedPaths": ["src/path/to/file.ts"]
23
+ },
24
+ {
25
+ "issueNumber": 2,
26
+ "dependencies": [1],
27
+ "affectedPaths": ["src/other/file.ts"]
28
+ }
29
+ ]
30
+
31
+ Rules:
32
+ - Look for explicit dependency mentions: "depends on #X", "after #X", "blocked by #X", "requires #X"
33
+ - Also infer logical dependencies (e.g., if issue B imports from a file that issue A creates)
34
+ - Only include dependencies between issues in this list
35
+ - affectedPaths should be specific file paths mentioned or implied
36
+ - Respond with ONLY valid JSON, nothing else`;
37
+ export class IssueAnalyzer {
38
+ /**
39
+ * Analyze all issues in a single Claude call to determine dependencies.
40
+ */
41
+ async analyzeIssues(issues) {
42
+ if (issues.length === 0)
43
+ return [];
44
+ const allIssueNumbers = issues.map(i => i.number);
45
+ // Build the issues list for the prompt
46
+ const issuesList = issues.map(issue => `### Issue #${issue.number}: ${issue.title}\n${issue.body || '(No description)'}`).join('\n\n');
47
+ const prompt = BATCH_ANALYSIS_PROMPT.replace('{{issuesList}}', issuesList);
48
+ console.log(chalk.gray(` Sending ${issues.length} issues to Claude for analysis...`));
49
+ try {
50
+ const iterator = query({
51
+ prompt,
52
+ options: {
53
+ maxTurns: 1,
54
+ allowedTools: [],
55
+ },
56
+ });
57
+ let responseText = '';
58
+ for await (const message of iterator) {
59
+ const msg = message;
60
+ if (msg.type === 'assistant') {
61
+ const assistantMsg = msg.message;
62
+ if (assistantMsg?.content && Array.isArray(assistantMsg.content)) {
63
+ for (const block of assistantMsg.content) {
64
+ if (typeof block === 'object' && block && 'type' in block && block.type === 'text' && 'text' in block) {
65
+ responseText += String(block.text);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ // Parse JSON array from response
72
+ const jsonMatch = responseText.match(/\[[\s\S]*\]/);
73
+ if (!jsonMatch) {
74
+ throw new Error('No JSON array found in response');
75
+ }
76
+ const parsed = JSON.parse(jsonMatch[0]);
77
+ // Create a map for quick lookup
78
+ const analysisMap = new Map(parsed.map(p => [p.issueNumber, p]));
79
+ // Build analyzed issues
80
+ const results = issues.map(issue => {
81
+ const analysis = analysisMap.get(issue.number);
82
+ // Filter dependencies to only include valid issues
83
+ const validDeps = (analysis?.dependencies || []).filter(d => allIssueNumbers.includes(d) && d !== issue.number);
84
+ const analyzed = {
85
+ ...issue,
86
+ affectedPaths: analysis?.affectedPaths || [],
87
+ dependencies: validDeps,
88
+ analyzedAt: new Date().toISOString(),
89
+ };
90
+ // Log each issue's analysis
91
+ const depsStr = validDeps.length > 0
92
+ ? `depends on ${validDeps.map(d => `#${d}`).join(', ')}`
93
+ : 'no dependencies';
94
+ console.log(chalk.gray(` #${issue.number}: ${depsStr}`));
95
+ return analyzed;
96
+ });
97
+ return results;
98
+ }
99
+ catch (error) {
100
+ console.log(chalk.yellow(` Claude analysis failed, falling back to pattern matching: ${error}`));
101
+ return this.fallbackAnalysis(issues, allIssueNumbers);
102
+ }
103
+ }
104
+ /**
105
+ * Fallback to pattern matching if Claude analysis fails.
106
+ */
107
+ fallbackAnalysis(issues, allIssueNumbers) {
108
+ return issues.map(issue => {
109
+ const deps = this.extractDependencies(issue, allIssueNumbers);
110
+ const paths = this.extractAffectedPaths(issue);
111
+ const depsStr = deps.length > 0
112
+ ? `depends on ${deps.map(d => `#${d}`).join(', ')}`
113
+ : 'no dependencies';
114
+ console.log(chalk.gray(` #${issue.number}: ${depsStr} (pattern match)`));
115
+ return {
116
+ ...issue,
117
+ affectedPaths: paths,
118
+ dependencies: deps,
119
+ analyzedAt: new Date().toISOString(),
120
+ };
121
+ });
122
+ }
123
+ /**
124
+ * Extract dependencies using pattern matching.
125
+ */
126
+ extractDependencies(issue, validNumbers) {
127
+ if (!issue.body)
128
+ return [];
129
+ const dependencies = new Set();
130
+ const body = issue.body;
131
+ const dependencyStatements = [
132
+ /depends?\s+on\s+([^.\n]+)/gi,
133
+ /after\s+([^.\n]+)/gi,
134
+ /blocked\s+by\s+([^.\n]+)/gi,
135
+ /requires?\s+([^.\n]+)/gi,
136
+ ];
137
+ for (const pattern of dependencyStatements) {
138
+ let match;
139
+ while ((match = pattern.exec(body)) !== null) {
140
+ const statement = match[1];
141
+ const issueRefs = statement.matchAll(/#(\d+)/g);
142
+ for (const ref of issueRefs) {
143
+ const num = parseInt(ref[1], 10);
144
+ if (validNumbers.includes(num) && num !== issue.number) {
145
+ dependencies.add(num);
146
+ }
147
+ }
148
+ }
149
+ }
150
+ return Array.from(dependencies);
151
+ }
152
+ /**
153
+ * Extract affected file paths from issue body.
154
+ */
155
+ extractAffectedPaths(issue) {
156
+ if (!issue.body)
157
+ return [];
158
+ const paths = new Set();
159
+ const pathPattern = /`((?:src|lib|app|packages?)\/[^`]+\.[a-z]+)`/gi;
160
+ let match;
161
+ while ((match = pathPattern.exec(issue.body)) !== null) {
162
+ paths.add(match[1]);
163
+ }
164
+ return Array.from(paths);
165
+ }
166
+ }
167
+ //# sourceMappingURL=issue-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-analyzer.js","sourceRoot":"","sources":["../../src/analysis/issue-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AnalyzedIssue } from '../types.js';
2
+ export declare class PlanParser {
3
+ /**
4
+ * Parse a plan into discrete work items with dependencies.
5
+ */
6
+ parse(planContent: string): Promise<AnalyzedIssue[]>;
7
+ }
8
+ //# sourceMappingURL=plan-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-parser.d.ts","sourceRoot":"","sources":["../../src/analysis/plan-parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgDjD,qBAAa,UAAU;IACrB;;OAEG;IACG,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CA6E3D"}
@@ -0,0 +1,112 @@
1
+ import chalk from 'chalk';
2
+ import { query } from '@anthropic-ai/claude-code';
3
+ const PLAN_ANALYSIS_PROMPT = `Analyze this plan and break it into discrete, implementable work items.
4
+
5
+ ## Plan
6
+
7
+ {{plan}}
8
+
9
+ ---
10
+
11
+ ## Your Task
12
+
13
+ Break this plan into discrete work items that can be implemented independently (but may have dependencies on each other).
14
+
15
+ For each work item, provide:
16
+ 1. **id**: Sequential number starting from 1
17
+ 2. **title**: Short descriptive title
18
+ 3. **body**: Full implementation details including:
19
+ - What to create/modify
20
+ - Specific file paths
21
+ - Function signatures or interfaces
22
+ - Testing instructions
23
+ - Acceptance criteria
24
+ 4. **dependencies**: IDs of work items that MUST be completed before this one
25
+
26
+ Respond with ONLY a JSON array (no markdown, no explanation):
27
+ [
28
+ {
29
+ "id": 1,
30
+ "title": "Initialize project",
31
+ "body": "Create the project structure...\\n\\n## Implementation\\n...",
32
+ "dependencies": []
33
+ },
34
+ {
35
+ "id": 2,
36
+ "title": "Create utilities",
37
+ "body": "Create utility functions...\\n\\n**Depends on #1**\\n\\n## Implementation\\n...",
38
+ "dependencies": [1]
39
+ }
40
+ ]
41
+
42
+ Rules:
43
+ - Each work item should be self-contained with all context needed to implement it
44
+ - Include "**Depends on #N**" in the body text for any dependencies
45
+ - Work items should be small enough to implement in one session
46
+ - Include specific file paths, function signatures, and acceptance criteria
47
+ - Respond with ONLY valid JSON, nothing else`;
48
+ export class PlanParser {
49
+ /**
50
+ * Parse a plan into discrete work items with dependencies.
51
+ */
52
+ async parse(planContent) {
53
+ const prompt = PLAN_ANALYSIS_PROMPT.replace('{{plan}}', planContent);
54
+ console.log(chalk.gray(' Sending plan to Claude for analysis...'));
55
+ try {
56
+ const iterator = query({
57
+ prompt,
58
+ options: {
59
+ maxTurns: 1,
60
+ allowedTools: [],
61
+ },
62
+ });
63
+ let responseText = '';
64
+ for await (const message of iterator) {
65
+ const msg = message;
66
+ if (msg.type === 'assistant') {
67
+ const assistantMsg = msg.message;
68
+ if (assistantMsg?.content && Array.isArray(assistantMsg.content)) {
69
+ for (const block of assistantMsg.content) {
70
+ if (typeof block === 'object' && block && 'type' in block && block.type === 'text' && 'text' in block) {
71
+ responseText += String(block.text);
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ // Parse JSON array from response
78
+ const jsonMatch = responseText.match(/\[[\s\S]*\]/);
79
+ if (!jsonMatch) {
80
+ throw new Error('No JSON array found in response');
81
+ }
82
+ const parsed = JSON.parse(jsonMatch[0]);
83
+ const allIds = parsed.map(p => p.id);
84
+ // Convert to AnalyzedIssue format
85
+ const results = parsed.map(item => {
86
+ // Filter dependencies to only include valid IDs
87
+ const validDeps = item.dependencies.filter(d => allIds.includes(d) && d !== item.id);
88
+ const depsStr = validDeps.length > 0
89
+ ? `depends on ${validDeps.map(d => `#${d}`).join(', ')}`
90
+ : 'no dependencies';
91
+ console.log(chalk.gray(` #${item.id}: ${item.title} (${depsStr})`));
92
+ return {
93
+ number: item.id,
94
+ title: item.title,
95
+ body: item.body,
96
+ state: 'open',
97
+ labels: [],
98
+ url: '',
99
+ htmlUrl: '',
100
+ affectedPaths: [],
101
+ dependencies: validDeps,
102
+ analyzedAt: new Date().toISOString(),
103
+ };
104
+ });
105
+ return results;
106
+ }
107
+ catch (error) {
108
+ throw new Error(`Failed to parse plan: ${error instanceof Error ? error.message : error}`);
109
+ }
110
+ }
111
+ }
112
+ //# sourceMappingURL=plan-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-parser.js","sourceRoot":"","sources":["../../src/analysis/plan-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { RunState } from '../types.js';
2
+ export interface LeftoverState {
3
+ hasLeftovers: boolean;
4
+ interruptedRuns: RunState[];
5
+ worktreeDirs: string[];
6
+ millhouseBranches: string[];
7
+ }
8
+ /**
9
+ * Detect leftover state from previous interrupted runs.
10
+ */
11
+ export declare function detectLeftoverState(basePath?: string): Promise<LeftoverState>;
12
+ /**
13
+ * Clean up all millhouse state - worktrees, branches, run files, and labels.
14
+ */
15
+ export declare function cleanupAllState(basePath?: string): Promise<void>;
16
+ /**
17
+ * Display the leftover state to the user.
18
+ */
19
+ export declare function displayLeftoverState(state: LeftoverState): void;
20
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/cli/cleanup.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAO5C,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,aAAa,CAAC,CAgElG;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFrF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CA2B/D"}
@@ -0,0 +1,186 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execSync } from 'node:child_process';
4
+ import chalk from 'chalk';
5
+ import { MILLHOUSE_LABELS } from '../types.js';
6
+ import { GitHubClient } from '../github/client.js';
7
+ const MILLHOUSE_DIR = '.millhouse';
8
+ const ALL_LABELS = Object.values(MILLHOUSE_LABELS);
9
+ /**
10
+ * Detect leftover state from previous interrupted runs.
11
+ */
12
+ export async function detectLeftoverState(basePath = process.cwd()) {
13
+ const result = {
14
+ hasLeftovers: false,
15
+ interruptedRuns: [],
16
+ worktreeDirs: [],
17
+ millhouseBranches: [],
18
+ };
19
+ const millhouseDir = path.join(basePath, MILLHOUSE_DIR);
20
+ // Check for interrupted/running runs
21
+ const runsDir = path.join(millhouseDir, 'runs');
22
+ try {
23
+ const runFiles = await fs.readdir(runsDir);
24
+ for (const file of runFiles) {
25
+ if (file.endsWith('.json')) {
26
+ const content = await fs.readFile(path.join(runsDir, file), 'utf-8');
27
+ const run = JSON.parse(content);
28
+ if (run.status === 'running' || run.status === 'interrupted') {
29
+ result.interruptedRuns.push(run);
30
+ }
31
+ }
32
+ }
33
+ }
34
+ catch {
35
+ // No runs directory
36
+ }
37
+ // Check for worktree directories
38
+ const worktreesDir = path.join(millhouseDir, 'worktrees');
39
+ try {
40
+ const entries = await fs.readdir(worktreesDir);
41
+ for (const entry of entries) {
42
+ const fullPath = path.join(worktreesDir, entry);
43
+ const stat = await fs.stat(fullPath);
44
+ if (stat.isDirectory()) {
45
+ result.worktreeDirs.push(fullPath);
46
+ }
47
+ }
48
+ }
49
+ catch {
50
+ // No worktrees directory
51
+ }
52
+ // Check for millhouse branches
53
+ try {
54
+ const branches = execSync('git branch --list "millhouse/*"', {
55
+ cwd: basePath,
56
+ encoding: 'utf-8',
57
+ }).trim();
58
+ if (branches) {
59
+ result.millhouseBranches = branches
60
+ .split('\n')
61
+ .map(b => b.trim().replace(/^\* /, ''))
62
+ .filter(Boolean);
63
+ }
64
+ }
65
+ catch {
66
+ // Git command failed
67
+ }
68
+ result.hasLeftovers =
69
+ result.interruptedRuns.length > 0 ||
70
+ result.worktreeDirs.length > 0 ||
71
+ result.millhouseBranches.length > 0;
72
+ return result;
73
+ }
74
+ /**
75
+ * Clean up all millhouse state - worktrees, branches, run files, and labels.
76
+ */
77
+ export async function cleanupAllState(basePath = process.cwd()) {
78
+ const millhouseDir = path.join(basePath, MILLHOUSE_DIR);
79
+ // Remove labels from issues in interrupted runs
80
+ try {
81
+ const githubClient = new GitHubClient();
82
+ const runsDir = path.join(millhouseDir, 'runs');
83
+ const runFiles = await fs.readdir(runsDir).catch(() => []);
84
+ const issueNumbers = new Set();
85
+ for (const file of runFiles) {
86
+ if (file.endsWith('.json')) {
87
+ const content = await fs.readFile(path.join(runsDir, file), 'utf-8');
88
+ const run = JSON.parse(content);
89
+ for (const issue of run.issues) {
90
+ issueNumbers.add(issue.number);
91
+ }
92
+ }
93
+ }
94
+ for (const issueNumber of issueNumbers) {
95
+ for (const label of ALL_LABELS) {
96
+ await githubClient.removeLabel(issueNumber, label).catch(() => { });
97
+ }
98
+ }
99
+ }
100
+ catch {
101
+ // GitHub client might fail if not in a repo, continue with local cleanup
102
+ }
103
+ // Remove all worktree directories
104
+ const worktreesDir = path.join(millhouseDir, 'worktrees');
105
+ try {
106
+ await fs.rm(worktreesDir, { recursive: true, force: true });
107
+ }
108
+ catch {
109
+ // Directory might not exist
110
+ }
111
+ // Prune git worktrees
112
+ try {
113
+ execSync('git worktree prune', { cwd: basePath, stdio: 'ignore' });
114
+ }
115
+ catch {
116
+ // Git command failed
117
+ }
118
+ // Delete all millhouse branches
119
+ try {
120
+ const branches = execSync('git branch --list "millhouse/*"', {
121
+ cwd: basePath,
122
+ encoding: 'utf-8',
123
+ }).trim();
124
+ if (branches) {
125
+ const branchList = branches
126
+ .split('\n')
127
+ .map(b => b.trim().replace(/^\* /, ''))
128
+ .filter(Boolean);
129
+ for (const branch of branchList) {
130
+ try {
131
+ execSync(`git branch -D "${branch}"`, { cwd: basePath, stdio: 'ignore' });
132
+ }
133
+ catch {
134
+ // Branch might be checked out or other issue
135
+ }
136
+ }
137
+ }
138
+ }
139
+ catch {
140
+ // Git command failed
141
+ }
142
+ // Clear run state files
143
+ const runsDir = path.join(millhouseDir, 'runs');
144
+ try {
145
+ await fs.rm(runsDir, { recursive: true, force: true });
146
+ }
147
+ catch {
148
+ // Directory might not exist
149
+ }
150
+ // Clear worktrees.json
151
+ const worktreesFile = path.join(millhouseDir, 'worktrees.json');
152
+ try {
153
+ await fs.unlink(worktreesFile);
154
+ }
155
+ catch {
156
+ // File might not exist
157
+ }
158
+ }
159
+ /**
160
+ * Display the leftover state to the user.
161
+ */
162
+ export function displayLeftoverState(state) {
163
+ console.log(chalk.yellow('\n⚠️ Found leftover state from a previous run:\n'));
164
+ if (state.interruptedRuns.length > 0) {
165
+ console.log(chalk.gray(' Interrupted runs:'));
166
+ for (const run of state.interruptedRuns) {
167
+ const issueCount = run.issues.length;
168
+ const completed = run.completedIssues.length;
169
+ console.log(` - ${run.id} (${completed}/${issueCount} issues completed)`);
170
+ }
171
+ }
172
+ if (state.worktreeDirs.length > 0) {
173
+ console.log(chalk.gray(' Worktree directories:'));
174
+ for (const dir of state.worktreeDirs) {
175
+ console.log(` - ${path.basename(dir)}`);
176
+ }
177
+ }
178
+ if (state.millhouseBranches.length > 0) {
179
+ console.log(chalk.gray(' Git branches:'));
180
+ for (const branch of state.millhouseBranches) {
181
+ console.log(` - ${branch}`);
182
+ }
183
+ }
184
+ console.log('');
185
+ }
186
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/cli/cleanup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function cleanCommand(): Promise<void>;
2
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/clean.ts"],"names":[],"mappings":"AAOA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBlD"}
@@ -0,0 +1,16 @@
1
+ import ora from 'ora';
2
+ import { detectLeftoverState, cleanupAllState, displayLeftoverState, } from '../cleanup.js';
3
+ export async function cleanCommand() {
4
+ const spinner = ora('Checking for leftover state...').start();
5
+ const leftoverState = await detectLeftoverState();
6
+ if (!leftoverState.hasLeftovers) {
7
+ spinner.succeed('Nothing to clean up');
8
+ return;
9
+ }
10
+ spinner.stop();
11
+ displayLeftoverState(leftoverState);
12
+ const cleanSpinner = ora('Cleaning up...').start();
13
+ await cleanupAllState();
14
+ cleanSpinner.succeed('Cleaned up all millhouse state');
15
+ }
16
+ //# sourceMappingURL=clean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.js","sourceRoot":"","sources":["../../../src/cli/commands/clean.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,OAAO,GAAG,GAAG,CAAC,gCAAgC,CAAC,CAAC,KAAK,EAAE,CAAC;IAE9D,MAAM,aAAa,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAElD,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;QAChC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,IAAI,EAAE,CAAC;IACf,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAEpC,MAAM,YAAY,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,CAAC;IACnD,MAAM,eAAe,EAAE,CAAC;IACxB,YAAY,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function resumeCommand(runId: string): Promise<void>;
2
+ //# sourceMappingURL=resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/resume.ts"],"names":[],"mappings":"AAcA,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4EhE"}
@@ -0,0 +1,82 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { Orchestrator } from '../../core/orchestrator.js';
4
+ import { loadConfig } from '../../storage/config.js';
5
+ import { JsonStore } from '../../storage/json-store.js';
6
+ import { GitHubClient } from '../../github/client.js';
7
+ import { LabelManager } from '../../github/label-manager.js';
8
+ import { IssueDiscoverer } from '../../github/issue-discoverer.js';
9
+ import { IssueAnalyzer } from '../../analysis/issue-analyzer.js';
10
+ import { GraphBuilder } from '../../analysis/graph-builder.js';
11
+ import { WorktreeManager } from '../../execution/worktree-manager.js';
12
+ import { ClaudeRunner } from '../../execution/claude-runner.js';
13
+ import { Scheduler } from '../../core/scheduler.js';
14
+ export async function resumeCommand(runId) {
15
+ const spinner = ora('Loading run state...').start();
16
+ try {
17
+ const store = new JsonStore();
18
+ const runState = await store.getRun(runId);
19
+ if (!runState) {
20
+ spinner.fail(`Run not found: ${runId}`);
21
+ process.exit(1);
22
+ }
23
+ if (runState.status === 'completed') {
24
+ spinner.fail('Run already completed');
25
+ process.exit(1);
26
+ }
27
+ spinner.text = 'Loading configuration...';
28
+ const config = await loadConfig();
29
+ // Initialize components
30
+ spinner.text = 'Initializing components...';
31
+ const githubClient = new GitHubClient();
32
+ const labelManager = new LabelManager(githubClient);
33
+ const issueDiscoverer = new IssueDiscoverer(githubClient);
34
+ const issueAnalyzer = new IssueAnalyzer();
35
+ const graphBuilder = new GraphBuilder();
36
+ const worktreeManager = new WorktreeManager();
37
+ const claudeRunner = new ClaudeRunner(config);
38
+ // Create scheduler with previous concurrency
39
+ const scheduler = new Scheduler({
40
+ concurrency: config.execution.concurrency,
41
+ continueOnError: config.execution.continueOnError,
42
+ });
43
+ // Create orchestrator
44
+ const orchestrator = new Orchestrator({
45
+ config,
46
+ store,
47
+ githubClient,
48
+ labelManager,
49
+ issueDiscoverer,
50
+ issueAnalyzer,
51
+ graphBuilder,
52
+ worktreeManager,
53
+ claudeRunner,
54
+ scheduler,
55
+ });
56
+ spinner.succeed('Loaded');
57
+ // Show current state
58
+ console.log(chalk.blue(`\n📦 Resuming run: ${runId}`));
59
+ console.log(` Completed: ${runState.completedIssues.length}`);
60
+ console.log(` Failed: ${runState.failedIssues.length}`);
61
+ console.log(` Remaining: ${runState.issues.length - runState.completedIssues.length - runState.failedIssues.length}`);
62
+ // Resume execution
63
+ console.log(chalk.blue('\n🚀 Resuming execution...'));
64
+ const result = await orchestrator.resume(runState);
65
+ if (result.status === 'completed') {
66
+ console.log(chalk.green('\n✅ All issues completed successfully!'));
67
+ if (result.pullRequestUrl) {
68
+ console.log(chalk.blue(` Pull request: ${result.pullRequestUrl}`));
69
+ }
70
+ }
71
+ else if (result.status === 'failed') {
72
+ console.log(chalk.red(`\n❌ Run failed: ${result.error}`));
73
+ process.exit(1);
74
+ }
75
+ }
76
+ catch (error) {
77
+ spinner.fail('Error');
78
+ console.error(chalk.red(`\n${error instanceof Error ? error.message : error}`));
79
+ process.exit(1);
80
+ }
81
+ }
82
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../src/cli/commands/resume.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,IAAI,GAAG,0BAA0B,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAElC,wBAAwB;QACxB,OAAO,CAAC,IAAI,GAAG,4BAA4B,CAAC;QAC5C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QACxC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QAE9C,6CAA6C;QAC7C,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW;YACzC,eAAe,EAAE,MAAM,CAAC,SAAS,CAAC,eAAe;SAClD,CAAC,CAAC;QAEH,sBAAsB;QACtB,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC;YACpC,MAAM;YACN,KAAK;YACL,YAAY;YACZ,YAAY;YACZ,eAAe;YACf,aAAa;YACb,YAAY;YACZ,eAAe;YACf,YAAY;YACZ,SAAS;SACV,CAAC,CAAC;QAEH,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAE1B,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAExH,mBAAmB;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnD,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;YACnE,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}