@link-assistant/hive-mind 0.48.3 → 0.49.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 0.49.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add --claude-file and --gitkeep-file CLI options for choosing between CLAUDE.md and .gitkeep files
8
+
9
+ This feature allows users to choose which file type to use for PR creation:
10
+ - `--claude-file` (default: true): Use CLAUDE.md file for task details
11
+ - `--gitkeep-file` (default: false, experimental): Use .gitkeep file instead
12
+
13
+ The flags are mutually exclusive:
14
+ - Using `--gitkeep-file` automatically disables `--claude-file`
15
+ - Using `--no-claude-file` automatically enables `--gitkeep-file`
16
+ - Both flags cannot be disabled simultaneously
17
+
18
+ This is a step toward making .gitkeep the default behavior in future releases.
19
+
20
+ ## 0.48.4
21
+
22
+ ### Patch Changes
23
+
24
+ - b010ce6: Increase minimum disk space requirement from 512 MB to 2 GB to provide more room for commands to gracefully finish before running out of disk space and prevent potential OS issues
25
+
3
26
  ## 0.48.3
4
27
 
5
28
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "0.48.3",
3
+ "version": "0.49.0",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -64,7 +64,7 @@ export const githubLimits = {
64
64
 
65
65
  // Memory and disk configurations
66
66
  export const systemLimits = {
67
- minDiskSpaceMb: parseIntWithDefault('HIVE_MIND_MIN_DISK_SPACE_MB', 500),
67
+ minDiskSpaceMb: parseIntWithDefault('HIVE_MIND_MIN_DISK_SPACE_MB', 2048),
68
68
  defaultPageSizeKb: parseIntWithDefault('HIVE_MIND_DEFAULT_PAGE_SIZE_KB', 16),
69
69
  };
70
70
 
@@ -128,8 +128,8 @@ export const createYargsConfig = yargsInstance => {
128
128
  })
129
129
  .option('min-disk-space', {
130
130
  type: 'number',
131
- description: 'Minimum required disk space in MB (default: 500)',
132
- default: 500,
131
+ description: 'Minimum required disk space in MB (default: 2048)',
132
+ default: 2048,
133
133
  })
134
134
  .option('auto-cleanup', {
135
135
  type: 'boolean',
package/src/hive.mjs CHANGED
@@ -1450,7 +1450,7 @@ if (isDirectExecution) {
1450
1450
  } else {
1451
1451
  const systemCheck = await checkSystem(
1452
1452
  {
1453
- minDiskSpaceMB: argv.minDiskSpace || 500,
1453
+ minDiskSpaceMB: argv.minDiskSpace || 2048,
1454
1454
  minMemoryMB: 256,
1455
1455
  exitOnFailure: true,
1456
1456
  },
@@ -27,7 +27,7 @@ const lib = await import('./lib.mjs');
27
27
  const { log: libLog, setLogFile } = lib;
28
28
 
29
29
  // Function to check available disk space
30
- export const checkDiskSpace = async (minSpaceMB = 500, options = {}) => {
30
+ export const checkDiskSpace = async (minSpaceMB = 2048, options = {}) => {
31
31
  const log = options.log || libLog;
32
32
 
33
33
  try {
@@ -290,7 +290,7 @@ export const getResourceSnapshot = async () => {
290
290
 
291
291
  // Combined system check function
292
292
  export const checkSystem = async (requirements = {}, options = {}) => {
293
- const { minMemoryMB = 256, minDiskSpaceMB = 500, exitOnFailure = false } = requirements;
293
+ const { minMemoryMB = 256, minDiskSpaceMB = 2048, exitOnFailure = false } = requirements;
294
294
 
295
295
  // Note: log is passed through options to checkDiskSpace and checkRAM
296
296
  const results = {
@@ -336,7 +336,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
336
336
  alias: 'd',
337
337
  type: 'number',
338
338
  description: 'Minimum required disk space in MB',
339
- default: 500,
339
+ default: 2048,
340
340
  })
341
341
  .option('exit-on-failure', {
342
342
  alias: 'e',
@@ -181,18 +181,20 @@ export const checkExistingPRsForAutoContinue = async (argv, isIssueUrl, owner, r
181
181
  continue;
182
182
  }
183
183
 
184
- // Check if CLAUDE.md exists in this PR branch
184
+ // Check if CLAUDE.md or .gitkeep exists in this PR branch
185
+ // If neither exists, it means work was completed and files were removed
185
186
  const claudeMdExists = await checkFileInBranch(owner, repo, 'CLAUDE.md', pr.headRefName);
187
+ const gitkeepExists = await checkFileInBranch(owner, repo, '.gitkeep', pr.headRefName);
186
188
 
187
- if (!claudeMdExists) {
188
- await log(`✅ Auto-continue: Using PR #${pr.number} (CLAUDE.md missing - work completed, branch: ${pr.headRefName})`);
189
+ if (!claudeMdExists && !gitkeepExists) {
190
+ await log(`✅ Auto-continue: Using PR #${pr.number} (CLAUDE.md/.gitkeep missing - work completed, branch: ${pr.headRefName})`);
189
191
 
190
- // Switch to continue mode immediately (don't wait 24 hours if CLAUDE.md is missing)
192
+ // Switch to continue mode immediately (don't wait 24 hours if both files are missing)
191
193
  isContinueMode = true;
192
194
  prNumber = pr.number;
193
195
  prBranch = pr.headRefName;
194
196
  if (argv.verbose) {
195
- await log(' Continue mode activated: Auto-continue (CLAUDE.md missing)', { verbose: true });
197
+ await log(' Continue mode activated: Auto-continue (initial commit files missing)', { verbose: true });
196
198
  await log(` PR Number: ${prNumber}`, { verbose: true });
197
199
  await log(` PR Branch: ${prBranch}`, { verbose: true });
198
200
  }
@@ -454,15 +456,16 @@ export const processAutoContinueForIssue = async (argv, isIssueUrl, urlNumber, o
454
456
  continue;
455
457
  }
456
458
 
457
- // Check if CLAUDE.md exists in this PR branch
459
+ // Check if CLAUDE.md or .gitkeep exists in this PR branch
458
460
  const claudeMdExists = await checkFileInBranch(owner, repo, 'CLAUDE.md', pr.headRefName);
461
+ const gitkeepExists = await checkFileInBranch(owner, repo, '.gitkeep', pr.headRefName);
459
462
 
460
- if (!claudeMdExists) {
461
- await log(`✅ Auto-continue: Using PR #${pr.number} (CLAUDE.md missing - work completed, branch: ${pr.headRefName})`);
463
+ if (!claudeMdExists && !gitkeepExists) {
464
+ await log(`✅ Auto-continue: Using PR #${pr.number} (CLAUDE.md/.gitkeep missing - work completed, branch: ${pr.headRefName})`);
462
465
 
463
- // Switch to continue mode immediately (don't wait 24 hours if CLAUDE.md is missing)
466
+ // Switch to continue mode immediately (don't wait 24 hours if CLAUDE.md/.gitkeep is missing)
464
467
  if (argv.verbose) {
465
- await log(' Continue mode activated: Auto-continue (CLAUDE.md missing)', { verbose: true });
468
+ await log(' Continue mode activated: Auto-continue (CLAUDE.md/.gitkeep missing)', { verbose: true });
466
469
  await log(` PR Number: ${pr.number}`, { verbose: true });
467
470
  await log(` PR Branch: ${pr.headRefName}`, { verbose: true });
468
471
  }
@@ -490,12 +493,12 @@ export const processAutoContinueForIssue = async (argv, isIssueUrl, urlNumber, o
490
493
  issueNumber,
491
494
  };
492
495
  } else {
493
- await log(` PR #${pr.number}: CLAUDE.md exists, age ${ageHours}h < 24h - skipping`);
496
+ await log(` PR #${pr.number}: CLAUDE.md/.gitkeep exists, age ${ageHours}h < 24h - skipping`);
494
497
  }
495
498
  }
496
499
  }
497
500
 
498
- await log('⏭️ No suitable PRs found (missing CLAUDE.md or older than 24h) - creating new PR as usual');
501
+ await log('⏭️ No suitable PRs found (missing CLAUDE.md/.gitkeep or older than 24h) - creating new PR as usual');
499
502
  } else {
500
503
  await log(`📝 No existing PRs found for issue #${issueNumber} - creating new PR`);
501
504
  }
@@ -30,20 +30,54 @@ export async function handleAutoPrCreation({ argv, tempDir, branchName, issueNum
30
30
  const issueUrl = argv['issue-url'] || argv._[0];
31
31
 
32
32
  try {
33
- // Create CLAUDE.md file with the task details
34
- await log(formatAligned('📝', 'Creating:', 'CLAUDE.md with task details'));
33
+ // Determine which file to create based on CLI flags
34
+ const useClaudeFile = argv.claudeFile !== false; // Default to true
35
+ const useGitkeepFile = argv.gitkeepFile === true; // Default to false
35
36
 
36
- // Check if CLAUDE.md already exists and read its content
37
- const claudeMdPath = path.join(tempDir, 'CLAUDE.md');
37
+ // Log which mode we're using
38
+ if (argv.verbose) {
39
+ await log(` Using ${useClaudeFile ? 'CLAUDE.md' : '.gitkeep'} mode (--claude-file=${useClaudeFile}, --gitkeep-file=${useGitkeepFile})`, { verbose: true });
40
+ }
41
+
42
+ let filePath;
43
+ let fileName;
38
44
  let existingContent = null;
39
45
  let fileExisted = false;
40
- try {
41
- existingContent = await fs.readFile(claudeMdPath, 'utf8');
42
- fileExisted = true;
43
- } catch (err) {
44
- // File doesn't exist, which is fine
45
- if (err.code !== 'ENOENT') {
46
- throw err;
46
+
47
+ if (useClaudeFile) {
48
+ // Create CLAUDE.md file with the task details
49
+ await log(formatAligned('📝', 'Creating:', 'CLAUDE.md with task details'));
50
+
51
+ filePath = path.join(tempDir, 'CLAUDE.md');
52
+ fileName = 'CLAUDE.md';
53
+
54
+ // Check if CLAUDE.md already exists and read its content
55
+ try {
56
+ existingContent = await fs.readFile(filePath, 'utf8');
57
+ fileExisted = true;
58
+ } catch (err) {
59
+ // File doesn't exist, which is fine
60
+ if (err.code !== 'ENOENT') {
61
+ throw err;
62
+ }
63
+ }
64
+ } else {
65
+ // Create .gitkeep file directly (experimental mode)
66
+ await log(formatAligned('📝', 'Creating:', '.gitkeep (experimental mode)'));
67
+
68
+ filePath = path.join(tempDir, '.gitkeep');
69
+ fileName = '.gitkeep';
70
+
71
+ // .gitkeep files are typically small, no need to check for existing content
72
+ // But we'll check if it exists for proper handling
73
+ try {
74
+ existingContent = await fs.readFile(filePath, 'utf8');
75
+ fileExisted = true;
76
+ } catch (err) {
77
+ // File doesn't exist, which is fine
78
+ if (err.code !== 'ENOENT') {
79
+ throw err;
80
+ }
47
81
  }
48
82
  }
49
83
 
@@ -61,44 +95,65 @@ export async function handleAutoPrCreation({ argv, tempDir, branchName, issueNum
61
95
  // Without this, appending the same task info produces no git changes,
62
96
  // leading to "No commits between branches" error during PR creation
63
97
  const timestamp = new Date().toISOString();
64
- const taskInfo = `Issue to solve: ${issueUrl}
98
+
99
+ let finalContent;
100
+
101
+ if (useClaudeFile) {
102
+ // CLAUDE.md: Use detailed task info
103
+ const taskInfo = `Issue to solve: ${issueUrl}
65
104
  Your prepared branch: ${branchName}
66
105
  Your prepared working directory: ${tempDir}${
67
- argv.fork && forkedRepo
68
- ? `
106
+ argv.fork && forkedRepo
107
+ ? `
69
108
  Your forked repository: ${forkedRepo}
70
109
  Original repository (upstream): ${owner}/${repo}`
71
- : ''
72
- }
110
+ : ''
111
+ }
73
112
 
74
113
  Proceed.`;
75
114
 
76
- // If CLAUDE.md already exists, append the task info with separator and timestamp
77
- // Otherwise, create new file with just the task info (no timestamp needed for new files)
78
- let finalContent;
79
- if (fileExisted && existingContent) {
80
- await log(' CLAUDE.md already exists, appending task info...', { verbose: true });
81
- // Remove any trailing whitespace and add separator
82
- const trimmedExisting = existingContent.trimEnd();
83
- // Add timestamp to ensure uniqueness when appending
84
- finalContent = `${trimmedExisting}\n\n---\n\n${taskInfo}\n\nRun timestamp: ${timestamp}`;
115
+ // If file already exists, append the task info with separator and timestamp
116
+ // Otherwise, create new file with just the task info (no timestamp needed for new files)
117
+ if (fileExisted && existingContent) {
118
+ await log(` ${fileName} already exists, appending task info...`, { verbose: true });
119
+ // Remove any trailing whitespace and add separator
120
+ const trimmedExisting = existingContent.trimEnd();
121
+ // Add timestamp to ensure uniqueness when appending
122
+ finalContent = `${trimmedExisting}\n\n---\n\n${taskInfo}\n\nRun timestamp: ${timestamp}`;
123
+ } else {
124
+ finalContent = taskInfo;
125
+ }
85
126
  } else {
86
- finalContent = taskInfo;
127
+ // .gitkeep: Use minimal metadata format
128
+ const gitkeepContent = `# Auto-generated file for PR creation
129
+ # Issue: ${issueUrl}
130
+ # Branch: ${branchName}
131
+ # Timestamp: ${timestamp}
132
+ # This file was created with --gitkeep-file flag (experimental)
133
+ # It will be removed when the task is complete`;
134
+
135
+ if (fileExisted && existingContent) {
136
+ await log(` ${fileName} already exists, appending timestamp...`, { verbose: true });
137
+ // For .gitkeep, just append a new timestamp to ensure uniqueness
138
+ finalContent = `${existingContent.trimEnd()}\n# Updated: ${timestamp}`;
139
+ } else {
140
+ finalContent = gitkeepContent;
141
+ }
87
142
  }
88
143
 
89
- await fs.writeFile(claudeMdPath, finalContent);
90
- await log(formatAligned('✅', 'File created:', 'CLAUDE.md'));
144
+ await fs.writeFile(filePath, finalContent);
145
+ await log(formatAligned('✅', 'File created:', fileName));
91
146
 
92
147
  // Add and commit the file
93
148
  await log(formatAligned('📦', 'Adding file:', 'To git staging'));
94
149
 
95
150
  // Use explicit cwd option for better reliability
96
- const addResult = await $({ cwd: tempDir })`git add CLAUDE.md`;
151
+ const addResult = await $({ cwd: tempDir })`git add ${fileName}`;
97
152
 
98
153
  if (addResult.code !== 0) {
99
- await log('❌ Failed to add CLAUDE.md', { level: 'error' });
154
+ await log(`❌ Failed to add ${fileName}`, { level: 'error' });
100
155
  await log(` Error: ${addResult.stderr ? addResult.stderr.toString() : 'Unknown error'}`, { level: 'error' });
101
- throw new Error('Failed to add CLAUDE.md');
156
+ throw new Error(`Failed to add ${fileName}`);
102
157
  }
103
158
 
104
159
  // Verify the file was actually staged
@@ -110,112 +165,133 @@ Proceed.`;
110
165
  }
111
166
 
112
167
  // Track which file we're using for the commit
113
- let commitFileName = 'CLAUDE.md';
168
+ let commitFileName = fileName;
114
169
 
115
170
  // Check if anything was actually staged
116
171
  if (!gitStatus || gitStatus.length === 0) {
117
172
  await log('');
118
- await log(formatAligned('⚠️', 'CLAUDE.md not staged:', 'Checking if file is ignored'), { level: 'warning' });
173
+ await log(formatAligned('⚠️', `${fileName} not staged:`, 'Checking if file is ignored'), { level: 'warning' });
119
174
 
120
- // Check if CLAUDE.md is in .gitignore
121
- const checkIgnoreResult = await $({ cwd: tempDir })`git check-ignore CLAUDE.md`;
122
- const isIgnored = checkIgnoreResult.code === 0;
175
+ // Only apply fallback logic when using CLAUDE.md mode (not in --gitkeep-file mode)
176
+ if (useClaudeFile) {
177
+ // Check if CLAUDE.md is in .gitignore
178
+ const checkIgnoreResult = await $({ cwd: tempDir })`git check-ignore CLAUDE.md`;
179
+ const isIgnored = checkIgnoreResult.code === 0;
123
180
 
124
- if (isIgnored) {
125
- await log(formatAligned('ℹ️', 'CLAUDE.md is ignored:', 'Using .gitkeep fallback'));
126
- await log('');
127
- await log(' 📝 Fallback strategy:');
128
- await log(' CLAUDE.md is in .gitignore, using .gitkeep instead.');
129
- await log(' This allows auto-PR creation to proceed without modifying .gitignore.');
130
- await log('');
181
+ if (isIgnored) {
182
+ await log(formatAligned('ℹ️', 'CLAUDE.md is ignored:', 'Using .gitkeep fallback'));
183
+ await log('');
184
+ await log(' 📝 Fallback strategy:');
185
+ await log(' CLAUDE.md is in .gitignore, using .gitkeep instead.');
186
+ await log(' This allows auto-PR creation to proceed without modifying .gitignore.');
187
+ await log('');
131
188
 
132
- // Create a .gitkeep file as fallback
133
- const gitkeepPath = path.join(tempDir, '.gitkeep');
134
- const gitkeepContent = `# Auto-generated file for PR creation
189
+ // Create a .gitkeep file as fallback
190
+ const gitkeepPath = path.join(tempDir, '.gitkeep');
191
+ const gitkeepContent = `# Auto-generated file for PR creation
135
192
  # Issue: ${issueUrl}
136
193
  # Branch: ${branchName}
137
194
  # This file was created because CLAUDE.md is in .gitignore
138
195
  # It will be removed when the task is complete`;
139
196
 
140
- await fs.writeFile(gitkeepPath, gitkeepContent);
141
- await log(formatAligned('✅', 'Created:', '.gitkeep file'));
197
+ await fs.writeFile(gitkeepPath, gitkeepContent);
198
+ await log(formatAligned('✅', 'Created:', '.gitkeep file'));
142
199
 
143
- // Try to add .gitkeep
144
- const gitkeepAddResult = await $({ cwd: tempDir })`git add .gitkeep`;
200
+ // Try to add .gitkeep
201
+ const gitkeepAddResult = await $({ cwd: tempDir })`git add .gitkeep`;
145
202
 
146
- if (gitkeepAddResult.code !== 0) {
147
- await log('❌ Failed to add .gitkeep', { level: 'error' });
148
- await log(` Error: ${gitkeepAddResult.stderr ? gitkeepAddResult.stderr.toString() : 'Unknown error'}`, {
149
- level: 'error',
150
- });
151
- throw new Error('Failed to add .gitkeep');
152
- }
203
+ if (gitkeepAddResult.code !== 0) {
204
+ await log('❌ Failed to add .gitkeep', { level: 'error' });
205
+ await log(` Error: ${gitkeepAddResult.stderr ? gitkeepAddResult.stderr.toString() : 'Unknown error'}`, {
206
+ level: 'error',
207
+ });
208
+ throw new Error('Failed to add .gitkeep');
209
+ }
210
+
211
+ // Verify .gitkeep was staged
212
+ statusResult = await $({ cwd: tempDir })`git status --short`;
213
+ gitStatus = statusResult.stdout ? statusResult.stdout.toString().trim() : '';
153
214
 
154
- // Verify .gitkeep was staged
155
- statusResult = await $({ cwd: tempDir })`git status --short`;
156
- gitStatus = statusResult.stdout ? statusResult.stdout.toString().trim() : '';
215
+ if (!gitStatus || gitStatus.length === 0) {
216
+ await log('');
217
+ await log(formatAligned('❌', 'GIT ADD FAILED:', 'Neither CLAUDE.md nor .gitkeep could be staged'), {
218
+ level: 'error',
219
+ });
220
+ await log('');
221
+ await log(' 🔍 What happened:');
222
+ await log(' Both CLAUDE.md and .gitkeep failed to stage.');
223
+ await log('');
224
+ await log(' 🔧 Troubleshooting steps:');
225
+ await log(` 1. Check git status: cd "${tempDir}" && git status`);
226
+ await log(` 2. Check .gitignore: cat "${tempDir}/.gitignore"`);
227
+ await log(` 3. Try force add: cd "${tempDir}" && git add -f .gitkeep`);
228
+ await log('');
229
+ throw new Error('Git add staged nothing - both files failed');
230
+ }
157
231
 
158
- if (!gitStatus || gitStatus.length === 0) {
232
+ commitFileName = '.gitkeep';
233
+ await log(formatAligned('✅', 'File staged:', '.gitkeep'));
234
+ } else {
159
235
  await log('');
160
- await log(formatAligned('❌', 'GIT ADD FAILED:', 'Neither CLAUDE.md nor .gitkeep could be staged'), {
161
- level: 'error',
162
- });
236
+ await log(formatAligned('❌', 'GIT ADD FAILED:', 'Nothing was staged'), { level: 'error' });
163
237
  await log('');
164
238
  await log(' 🔍 What happened:');
165
- await log(' Both CLAUDE.md and .gitkeep failed to stage.');
239
+ await log(' CLAUDE.md was created but git did not stage any changes.');
240
+ await log('');
241
+ await log(' 💡 Possible causes:');
242
+ await log(' • CLAUDE.md already exists with identical content');
243
+ await log(' • File system sync issue');
166
244
  await log('');
167
245
  await log(' 🔧 Troubleshooting steps:');
168
- await log(` 1. Check git status: cd "${tempDir}" && git status`);
169
- await log(` 2. Check .gitignore: cat "${tempDir}/.gitignore"`);
170
- await log(` 3. Try force add: cd "${tempDir}" && git add -f .gitkeep`);
246
+ await log(` 1. Check file exists: ls -la "${tempDir}/CLAUDE.md"`);
247
+ await log(` 2. Check git status: cd "${tempDir}" && git status`);
248
+ await log(` 3. Force add: cd "${tempDir}" && git add -f CLAUDE.md`);
171
249
  await log('');
172
- throw new Error('Git add staged nothing - both files failed');
250
+ await log(' 📂 Debug information:');
251
+ await log(` Working directory: ${tempDir}`);
252
+ await log(` Branch: ${branchName}`);
253
+ if (existingContent) {
254
+ await log(' Note: CLAUDE.md already existed (attempted to update with timestamp)');
255
+ }
256
+ await log('');
257
+ throw new Error('Git add staged nothing - CLAUDE.md may be unchanged');
173
258
  }
174
-
175
- commitFileName = '.gitkeep';
176
- await log(formatAligned('✅', 'File staged:', '.gitkeep'));
177
259
  } else {
260
+ // In --gitkeep-file mode, if .gitkeep couldn't be staged, this is an error
178
261
  await log('');
179
262
  await log(formatAligned('❌', 'GIT ADD FAILED:', 'Nothing was staged'), { level: 'error' });
180
263
  await log('');
181
264
  await log(' 🔍 What happened:');
182
- await log(' CLAUDE.md was created but git did not stage any changes.');
265
+ await log(` ${fileName} was created but git did not stage any changes.`);
183
266
  await log('');
184
267
  await log(' 💡 Possible causes:');
185
- await log('CLAUDE.md already exists with identical content');
268
+ await log(`${fileName} already exists with identical content`);
186
269
  await log(' • File system sync issue');
270
+ await log(` • ${fileName} is in .gitignore`);
187
271
  await log('');
188
272
  await log(' 🔧 Troubleshooting steps:');
189
- await log(` 1. Check file exists: ls -la "${tempDir}/CLAUDE.md"`);
273
+ await log(` 1. Check file exists: ls -la "${tempDir}/${fileName}"`);
190
274
  await log(` 2. Check git status: cd "${tempDir}" && git status`);
191
- await log(` 3. Force add: cd "${tempDir}" && git add -f CLAUDE.md`);
275
+ await log(` 3. Check if ignored: cd "${tempDir}" && git check-ignore ${fileName}`);
276
+ await log(` 4. Force add: cd "${tempDir}" && git add -f ${fileName}`);
192
277
  await log('');
193
278
  await log(' 📂 Debug information:');
194
279
  await log(` Working directory: ${tempDir}`);
195
280
  await log(` Branch: ${branchName}`);
281
+ await log(` Mode: ${useClaudeFile ? 'CLAUDE.md' : '.gitkeep'}`);
196
282
  if (existingContent) {
197
- await log(' Note: CLAUDE.md already existed (attempted to update with timestamp)');
283
+ await log(` Note: ${fileName} already existed (attempted to update with timestamp)`);
198
284
  }
199
285
  await log('');
200
- throw new Error('Git add staged nothing - CLAUDE.md may be unchanged');
286
+ throw new Error(`Git add staged nothing - ${fileName} may be unchanged or ignored`);
201
287
  }
202
288
  }
203
289
 
204
290
  await log(formatAligned('📝', 'Creating commit:', `With ${commitFileName} file`));
205
- const commitMessage =
206
- commitFileName === 'CLAUDE.md'
207
- ? `Initial commit with task details
208
-
209
- Adding CLAUDE.md with task information for AI processing.
210
- This file will be removed when the task is complete.
211
-
212
- Issue: ${issueUrl}`
213
- : `Initial commit with task details
214
-
215
- Adding .gitkeep for PR creation (CLAUDE.md is in .gitignore).
216
- This file will be removed when the task is complete.
217
291
 
218
- Issue: ${issueUrl}`;
292
+ // Determine commit message based on which file is being committed
293
+ const fileDesc = commitFileName === 'CLAUDE.md' ? 'CLAUDE.md with task information for AI processing' : `.gitkeep for PR creation (${useGitkeepFile ? 'created with --gitkeep-file flag (experimental)' : 'CLAUDE.md is in .gitignore'})`;
294
+ const commitMessage = `Initial commit with task details\n\nAdding ${fileDesc}.\nThis file will be removed when the task is complete.\n\nIssue: ${issueUrl}`;
219
295
 
220
296
  // Use explicit cwd option for better reliability
221
297
  const commitResult = await $({ cwd: tempDir })`git commit -m ${commitMessage}`;
@@ -228,7 +304,7 @@ Issue: ${issueUrl}`;
228
304
  await log(formatAligned('❌', 'COMMIT FAILED:', 'Could not create initial commit'), { level: 'error' });
229
305
  await log('');
230
306
  await log(' 🔍 What happened:');
231
- await log(' Git commit command failed after staging CLAUDE.md.');
307
+ await log(` Git commit command failed after staging ${commitFileName}.`);
232
308
  await log('');
233
309
 
234
310
  // Check for specific error patterns
@@ -118,6 +118,16 @@ export const createYargsConfig = yargsInstance => {
118
118
  description: 'Automatically fork public repositories without write access (fails for private repos)',
119
119
  default: true,
120
120
  })
121
+ .option('claude-file', {
122
+ type: 'boolean',
123
+ description: 'Create CLAUDE.md file for task details (default, mutually exclusive with --gitkeep-file)',
124
+ default: true,
125
+ })
126
+ .option('gitkeep-file', {
127
+ type: 'boolean',
128
+ description: 'Create .gitkeep file instead of CLAUDE.md (experimental, mutually exclusive with --claude-file)',
129
+ default: false,
130
+ })
121
131
  .option('attach-logs', {
122
132
  type: 'boolean',
123
133
  description: 'Upload the solution draft log file to the Pull Request on completion (⚠️ WARNING: May expose sensitive data)',
@@ -181,8 +191,8 @@ export const createYargsConfig = yargsInstance => {
181
191
  })
182
192
  .option('min-disk-space', {
183
193
  type: 'number',
184
- description: 'Minimum required disk space in MB (default: 500)',
185
- default: 500,
194
+ description: 'Minimum required disk space in MB (default: 2048)',
195
+ default: 2048,
186
196
  })
187
197
  .option('log-dir', {
188
198
  type: 'string',
@@ -365,5 +375,44 @@ export const parseArguments = async (yargs, hideBin) => {
365
375
  argv.model = 'grok-code';
366
376
  }
367
377
 
378
+ // Validate mutual exclusivity of --claude-file and --gitkeep-file
379
+ // Check if both are explicitly enabled (user passed both --claude-file and --gitkeep-file)
380
+ if (argv.claudeFile && argv.gitkeepFile) {
381
+ // Check if they were explicitly set via command line
382
+ const claudeFileExplicit = rawArgs.includes('--claude-file');
383
+ const gitkeepFileExplicit = rawArgs.includes('--gitkeep-file');
384
+
385
+ if (claudeFileExplicit && gitkeepFileExplicit) {
386
+ throw new Error('--claude-file and --gitkeep-file are mutually exclusive. Please use only one.');
387
+ }
388
+
389
+ // If only one is explicit, turn off the other
390
+ if (gitkeepFileExplicit && !claudeFileExplicit) {
391
+ argv.claudeFile = false;
392
+ } else if (claudeFileExplicit && !gitkeepFileExplicit) {
393
+ argv.gitkeepFile = false;
394
+ }
395
+ }
396
+
397
+ // Check for both being disabled (both --no-claude-file and --no-gitkeep-file)
398
+ const noClaudeFile = rawArgs.includes('--no-claude-file');
399
+ const noGitkeepFile = rawArgs.includes('--no-gitkeep-file');
400
+
401
+ if (noClaudeFile && noGitkeepFile) {
402
+ throw new Error('Cannot disable both --claude-file and --gitkeep-file. At least one must be enabled for PR creation.');
403
+ }
404
+
405
+ // If user explicitly set --no-claude-file, enable gitkeep-file
406
+ if (noClaudeFile && !argv.gitkeepFile) {
407
+ argv.gitkeepFile = true;
408
+ argv.claudeFile = false;
409
+ }
410
+
411
+ // If user explicitly set --no-gitkeep-file, enable claude-file (this is the default anyway)
412
+ if (noGitkeepFile && !argv.claudeFile) {
413
+ argv.claudeFile = true;
414
+ argv.gitkeepFile = false;
415
+ }
416
+
368
417
  return argv;
369
418
  };
package/src/solve.mjs CHANGED
@@ -211,7 +211,7 @@ await validateAndExitOnInvalidModel(argv.model, tool, safeExit);
211
211
  // Skip tool CONNECTION validation in dry-run mode or when --skip-tool-connection-check or --no-tool-connection-check is enabled
212
212
  // Note: This does NOT skip model validation which is performed above
213
213
  const skipToolConnectionCheck = argv.dryRun || argv.skipToolConnectionCheck || argv.toolConnectionCheck === false;
214
- if (!(await performSystemChecks(argv.minDiskSpace || 500, skipToolConnectionCheck, argv.model, argv))) {
214
+ if (!(await performSystemChecks(argv.minDiskSpace || 2048, skipToolConnectionCheck, argv.model, argv))) {
215
215
  await safeExit(1, 'System checks failed');
216
216
  }
217
217
  // URL validation debug logging
@@ -1045,8 +1045,8 @@ try {
1045
1045
  const autoRestartEnabled = argv['autoRestartOnUncommittedChanges'] !== false;
1046
1046
  const shouldRestart = await checkForUncommittedChanges(tempDir, owner, repo, branchName, $, log, shouldAutoCommit, autoRestartEnabled);
1047
1047
 
1048
- // Remove CLAUDE.md now that Claude command has finished
1049
- await cleanupClaudeFile(tempDir, branchName, claudeCommitHash);
1048
+ // Remove initial commit file (CLAUDE.md or .gitkeep) now that Claude command has finished
1049
+ await cleanupClaudeFile(tempDir, branchName, claudeCommitHash, argv);
1050
1050
 
1051
1051
  // Show summary of session and log file
1052
1052
  await showSessionSummary(sessionId, limitReached, argv, issueUrl, tempDir, shouldAttachLogs);
@@ -42,13 +42,13 @@ const githubLinking = await import('./github-linking.lib.mjs');
42
42
  const { hasGitHubLinkingKeyword } = githubLinking;
43
43
 
44
44
  /**
45
- * Detect the CLAUDE.md commit hash from branch structure when not available in session
45
+ * Detect the CLAUDE.md or .gitkeep commit hash from branch structure when not available in session
46
46
  * This handles continue mode where the commit hash was lost between sessions
47
47
  *
48
48
  * Safety checks to prevent Issue #617 (wrong commit revert):
49
49
  * 1. Only look at commits on the PR branch (not default branch commits)
50
50
  * 2. Verify the commit message matches our expected pattern
51
- * 3. Verify the commit ONLY adds CLAUDE.md (no other files changed)
51
+ * 3. Verify the commit ONLY adds CLAUDE.md or .gitkeep (no other files changed)
52
52
  * 4. Verify there are additional commits after it (actual work was done)
53
53
  *
54
54
  * @param {string} tempDir - The temporary directory with the git repo
@@ -57,12 +57,16 @@ const { hasGitHubLinkingKeyword } = githubLinking;
57
57
  */
58
58
  const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
59
59
  try {
60
- await log(' Attempting to detect CLAUDE.md commit from branch structure...', { verbose: true });
60
+ await log(' Attempting to detect CLAUDE.md or .gitkeep commit from branch structure...', { verbose: true });
61
61
 
62
- // First check if CLAUDE.md exists in current branch
62
+ // First check if CLAUDE.md or .gitkeep exists in current branch
63
63
  const claudeMdExistsResult = await $({ cwd: tempDir })`git ls-files CLAUDE.md 2>&1`;
64
- if (claudeMdExistsResult.code !== 0 || !claudeMdExistsResult.stdout || !claudeMdExistsResult.stdout.trim()) {
65
- await log(' CLAUDE.md does not exist in current branch', { verbose: true });
64
+ const gitkeepExistsResult = await $({ cwd: tempDir })`git ls-files .gitkeep 2>&1`;
65
+ const claudeMdExists = claudeMdExistsResult.code === 0 && claudeMdExistsResult.stdout && claudeMdExistsResult.stdout.trim();
66
+ const gitkeepExists = gitkeepExistsResult.code === 0 && gitkeepExistsResult.stdout && gitkeepExistsResult.stdout.trim();
67
+
68
+ if (!claudeMdExists && !gitkeepExists) {
69
+ await log(' Neither CLAUDE.md nor .gitkeep exists in current branch', { verbose: true });
66
70
  return null;
67
71
  }
68
72
 
@@ -80,7 +84,7 @@ const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
80
84
  // Find the merge base (fork point) between current branch and default branch
81
85
  const mergeBaseResult = await $({ cwd: tempDir })`git merge-base origin/${defaultBranch} HEAD 2>&1`;
82
86
  if (mergeBaseResult.code !== 0 || !mergeBaseResult.stdout) {
83
- await log(' Could not find merge base, cannot safely detect CLAUDE.md commit', { verbose: true });
87
+ await log(' Could not find merge base, cannot safely detect initial commit', { verbose: true });
84
88
  return null;
85
89
  }
86
90
  const mergeBase = mergeBaseResult.stdout.toString().trim();
@@ -117,19 +121,19 @@ const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
117
121
  verbose: true,
118
122
  });
119
123
 
120
- // Safety check: Verify commit message matches expected pattern
121
- const expectedMessagePatterns = [/^Initial commit with task details/i, /^Add CLAUDE\.md/i, /^CLAUDE\.md/i];
124
+ // Safety check: Verify commit message matches expected pattern (CLAUDE.md or .gitkeep)
125
+ const expectedMessagePatterns = [/^Initial commit with task details/i, /^Add CLAUDE\.md/i, /^CLAUDE\.md/i, /^Add \.gitkeep/i, /\.gitkeep/i];
122
126
 
123
127
  const messageMatches = expectedMessagePatterns.some(pattern => pattern.test(firstCommitMessage));
124
128
  if (!messageMatches) {
125
- await log(' First commit message does not match expected CLAUDE.md pattern', { verbose: true });
126
- await log(' Expected patterns: "Initial commit with task details...", "Add CLAUDE.md", etc.', {
129
+ await log(' First commit message does not match expected pattern', { verbose: true });
130
+ await log(' Expected patterns: "Initial commit with task details...", "Add CLAUDE.md", ".gitkeep", etc.', {
127
131
  verbose: true,
128
132
  });
129
133
  return null;
130
134
  }
131
135
 
132
- // Safety check: Verify the commit ONLY adds CLAUDE.md file (no other files)
136
+ // Safety check: Verify the commit ONLY adds CLAUDE.md or .gitkeep file (no other files)
133
137
  const filesChangedResult = await $({
134
138
  cwd: tempDir,
135
139
  })`git diff-tree --no-commit-id --name-only -r ${firstCommitHash} 2>&1`;
@@ -141,16 +145,20 @@ const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
141
145
  const filesChanged = filesChangedResult.stdout.toString().trim().split('\n').filter(Boolean);
142
146
  await log(` Files changed in first commit: ${filesChanged.join(', ')}`, { verbose: true });
143
147
 
144
- // Check if CLAUDE.md is in the files changed
145
- if (!filesChanged.includes('CLAUDE.md')) {
146
- await log(' First commit does not include CLAUDE.md', { verbose: true });
148
+ // Check if CLAUDE.md or .gitkeep is in the files changed
149
+ const hasClaudeMd = filesChanged.includes('CLAUDE.md');
150
+ const hasGitkeep = filesChanged.includes('.gitkeep');
151
+ if (!hasClaudeMd && !hasGitkeep) {
152
+ await log(' First commit does not include CLAUDE.md or .gitkeep', { verbose: true });
147
153
  return null;
148
154
  }
149
155
 
150
- // CRITICAL SAFETY CHECK: Only allow revert if CLAUDE.md is the ONLY file changed
156
+ const targetFile = hasClaudeMd ? 'CLAUDE.md' : '.gitkeep';
157
+
158
+ // CRITICAL SAFETY CHECK: Only allow revert if the target file is the ONLY file changed
151
159
  // This prevents Issue #617 where reverting a commit deleted .gitignore, LICENSE, README.md
152
160
  if (filesChanged.length > 1) {
153
- await log(` ⚠️ First commit changes more than just CLAUDE.md (${filesChanged.length} files)`, {
161
+ await log(` ⚠️ First commit changes more than just ${targetFile} (${filesChanged.length} files)`, {
154
162
  verbose: true,
155
163
  });
156
164
  await log(` Files: ${filesChanged.join(', ')}`, { verbose: true });
@@ -159,81 +167,86 @@ const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
159
167
  }
160
168
 
161
169
  // All safety checks passed!
162
- await log(` ✅ Detected CLAUDE.md commit: ${firstCommitHash.substring(0, 7)}`, { verbose: true });
163
- await log(' ✅ Commit only contains CLAUDE.md (safe to revert)', { verbose: true });
170
+ await log(` ✅ Detected ${targetFile} commit: ${firstCommitHash.substring(0, 7)}`, { verbose: true });
171
+ await log(` ✅ Commit only contains ${targetFile} (safe to revert)`, { verbose: true });
164
172
  await log(` ✅ Branch has ${branchCommits.length - 1} additional commit(s) (work was done)`, { verbose: true });
165
173
 
166
174
  return firstCommitHash;
167
175
  } catch (error) {
168
176
  reportError(error, {
169
- context: 'detect_claude_md_commit',
177
+ context: 'detect_initial_commit',
170
178
  tempDir,
171
179
  branchName,
172
180
  operation: 'detect_commit_from_branch_structure',
173
181
  });
174
- await log(` Error detecting CLAUDE.md commit: ${error.message}`, { verbose: true });
182
+ await log(` Error detecting initial commit: ${error.message}`, { verbose: true });
175
183
  return null;
176
184
  }
177
185
  };
178
186
 
179
- // Revert the CLAUDE.md commit to restore original state
187
+ // Revert the CLAUDE.md or .gitkeep commit to restore original state
180
188
  export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash = null) => {
181
189
  try {
182
190
  // If no commit hash provided, try to detect it from branch structure
183
191
  // This handles continue mode where the hash was lost between sessions
184
192
  if (!claudeCommitHash) {
185
- await log(' No CLAUDE.md commit hash from session, attempting to detect from branch...', { verbose: true });
193
+ await log(' No initial commit hash from session, attempting to detect from branch...', { verbose: true });
186
194
  claudeCommitHash = await detectClaudeMdCommitFromBranch(tempDir, branchName);
187
195
 
188
196
  if (!claudeCommitHash) {
189
- await log(' Could not safely detect CLAUDE.md commit to revert', { verbose: true });
197
+ await log(' Could not safely detect initial commit to revert', { verbose: true });
190
198
  return;
191
199
  }
192
- await log(` Detected CLAUDE.md commit: ${claudeCommitHash.substring(0, 7)}`, { verbose: true });
200
+ await log(` Detected initial commit: ${claudeCommitHash.substring(0, 7)}`, { verbose: true });
193
201
  }
194
202
 
195
- await log(formatAligned('🔄', 'Cleanup:', 'Reverting CLAUDE.md commit'));
203
+ // Determine which file was used based on the commit message or flags
204
+ // Check the commit message to determine which file was committed
205
+ const commitMsgResult = await $({ cwd: tempDir })`git log -1 --format=%s ${claudeCommitHash} 2>&1`;
206
+ const commitMsg = commitMsgResult.stdout?.trim() || '';
207
+ const isGitkeepFile = commitMsg.includes('.gitkeep');
208
+ const fileName = isGitkeepFile ? '.gitkeep' : 'CLAUDE.md';
209
+
210
+ await log(formatAligned('🔄', 'Cleanup:', `Reverting ${fileName} commit`));
196
211
  await log(` Using saved commit hash: ${claudeCommitHash.substring(0, 7)}...`, { verbose: true });
197
212
 
198
213
  const commitToRevert = claudeCommitHash;
199
214
 
200
215
  // APPROACH 3: Check for modifications before reverting (proactive detection)
201
- // This is the main strategy - detect if CLAUDE.md was modified after initial commit
202
- await log(' Checking if CLAUDE.md was modified since initial commit...', { verbose: true });
203
- const diffResult = await $({ cwd: tempDir })`git diff ${commitToRevert} HEAD -- CLAUDE.md 2>&1`;
216
+ // This is the main strategy - detect if the file was modified after initial commit
217
+ await log(` Checking if ${fileName} was modified since initial commit...`, { verbose: true });
218
+ const diffResult = await $({ cwd: tempDir })`git diff ${commitToRevert} HEAD -- ${fileName} 2>&1`;
204
219
 
205
220
  if (diffResult.stdout && diffResult.stdout.trim()) {
206
- // CLAUDE.md was modified after initial commit - use manual approach to avoid conflicts
207
- await log(' CLAUDE.md was modified after initial commit, using manual cleanup...', { verbose: true });
221
+ // File was modified after initial commit - use manual approach to avoid conflicts
222
+ await log(` ${fileName} was modified after initial commit, using manual cleanup...`, { verbose: true });
208
223
 
209
- // Get the state of CLAUDE.md from before the initial commit (parent of the commit we're reverting)
224
+ // Get the state of the file from before the initial commit (parent of the commit we're reverting)
210
225
  const parentCommit = `${commitToRevert}~1`;
211
- const parentFileExists = await $({ cwd: tempDir })`git cat-file -e ${parentCommit}:CLAUDE.md 2>&1`;
226
+ const parentFileExists = await $({ cwd: tempDir })`git cat-file -e ${parentCommit}:${fileName} 2>&1`;
212
227
 
213
228
  if (parentFileExists.code === 0) {
214
- // CLAUDE.md existed before the initial commit - restore it to that state
215
- await log(' CLAUDE.md existed before session, restoring to previous state...', { verbose: true });
216
- await $({ cwd: tempDir })`git checkout ${parentCommit} -- CLAUDE.md`;
229
+ // File existed before the initial commit - restore it to that state
230
+ await log(` ${fileName} existed before session, restoring to previous state...`, { verbose: true });
231
+ await $({ cwd: tempDir })`git checkout ${parentCommit} -- ${fileName}`;
217
232
  } else {
218
- // CLAUDE.md didn't exist before the initial commit - delete it
219
- await log(' CLAUDE.md was created in session, removing it...', { verbose: true });
220
- await $({ cwd: tempDir })`git rm -f CLAUDE.md 2>&1`;
233
+ // File didn't exist before the initial commit - delete it
234
+ await log(` ${fileName} was created in session, removing it...`, { verbose: true });
235
+ await $({ cwd: tempDir })`git rm -f ${fileName} 2>&1`;
221
236
  }
222
237
 
223
238
  // Create a manual revert commit
224
- const commitResult = await $({
225
- cwd: tempDir,
226
- })`git commit -m "Revert: Remove CLAUDE.md changes from initial commit" 2>&1`;
239
+ const commitResult = await $({ cwd: tempDir })`git commit -m "Revert: Remove ${fileName} changes from initial commit" 2>&1`;
227
240
 
228
241
  if (commitResult.code === 0) {
229
- await log(formatAligned('📦', 'Committed:', 'CLAUDE.md revert (manual)'));
242
+ await log(formatAligned('📦', 'Committed:', `${fileName} revert (manual)`));
230
243
 
231
244
  // Push the revert
232
245
  const pushRevertResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
233
246
  if (pushRevertResult.code === 0) {
234
- await log(formatAligned('📤', 'Pushed:', 'CLAUDE.md revert to GitHub'));
247
+ await log(formatAligned('📤', 'Pushed:', `${fileName} revert to GitHub`));
235
248
  } else {
236
- await log(' Warning: Could not push CLAUDE.md revert', { verbose: true });
249
+ await log(` Warning: Could not push ${fileName} revert`, { verbose: true });
237
250
  }
238
251
  } else {
239
252
  await log(' Warning: Could not create manual revert commit', { verbose: true });
@@ -246,14 +259,14 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
246
259
  // FALLBACK 1: Standard git revert
247
260
  const revertResult = await $({ cwd: tempDir })`git revert ${commitToRevert} --no-edit 2>&1`;
248
261
  if (revertResult.code === 0) {
249
- await log(formatAligned('📦', 'Committed:', 'CLAUDE.md revert'));
262
+ await log(formatAligned('📦', 'Committed:', `${fileName} revert`));
250
263
 
251
264
  // Push the revert
252
265
  const pushRevertResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
253
266
  if (pushRevertResult.code === 0) {
254
- await log(formatAligned('📤', 'Pushed:', 'CLAUDE.md revert to GitHub'));
267
+ await log(formatAligned('📤', 'Pushed:', `${fileName} revert to GitHub`));
255
268
  } else {
256
- await log(' Warning: Could not push CLAUDE.md revert', { verbose: true });
269
+ await log(` Warning: Could not push ${fileName} revert`, { verbose: true });
257
270
  }
258
271
  } else {
259
272
  // FALLBACK 2: Handle unexpected conflicts (three-way merge with automatic resolution)
@@ -267,24 +280,24 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
267
280
  const statusResult = await $({ cwd: tempDir })`git status --short 2>&1`;
268
281
  const statusOutput = statusResult.stdout || '';
269
282
 
270
- // Check if CLAUDE.md is in the conflict
271
- if (statusOutput.includes('CLAUDE.md')) {
272
- await log(' Resolving CLAUDE.md conflict by restoring pre-session state...', { verbose: true });
283
+ // Check if the file is in the conflict
284
+ if (statusOutput.includes(fileName)) {
285
+ await log(` Resolving ${fileName} conflict by restoring pre-session state...`, { verbose: true });
273
286
 
274
- // Get the state of CLAUDE.md from before the initial commit (parent of the commit we're reverting)
287
+ // Get the state of the file from before the initial commit (parent of the commit we're reverting)
275
288
  const parentCommit = `${commitToRevert}~1`;
276
- const parentFileExists = await $({ cwd: tempDir })`git cat-file -e ${parentCommit}:CLAUDE.md 2>&1`;
289
+ const parentFileExists = await $({ cwd: tempDir })`git cat-file -e ${parentCommit}:${fileName} 2>&1`;
277
290
 
278
291
  if (parentFileExists.code === 0) {
279
- // CLAUDE.md existed before the initial commit - restore it to that state
280
- await log(' CLAUDE.md existed before session, restoring to previous state...', { verbose: true });
281
- await $({ cwd: tempDir })`git checkout ${parentCommit} -- CLAUDE.md`;
282
- // Stage the resolved CLAUDE.md
283
- await $({ cwd: tempDir })`git add CLAUDE.md 2>&1`;
292
+ // File existed before the initial commit - restore it to that state
293
+ await log(` ${fileName} existed before session, restoring to previous state...`, { verbose: true });
294
+ await $({ cwd: tempDir })`git checkout ${parentCommit} -- ${fileName}`;
295
+ // Stage the resolved file
296
+ await $({ cwd: tempDir })`git add ${fileName} 2>&1`;
284
297
  } else {
285
- // CLAUDE.md didn't exist before the initial commit - delete it
286
- await log(' CLAUDE.md was created in session, removing it...', { verbose: true });
287
- await $({ cwd: tempDir })`git rm -f CLAUDE.md 2>&1`;
298
+ // File didn't exist before the initial commit - delete it
299
+ await log(` ${fileName} was created in session, removing it...`, { verbose: true });
300
+ await $({ cwd: tempDir })`git rm -f ${fileName} 2>&1`;
288
301
  // No need to git add since git rm stages the deletion
289
302
  }
290
303
 
@@ -292,27 +305,27 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
292
305
  const continueResult = await $({ cwd: tempDir })`git revert --continue --no-edit 2>&1`;
293
306
 
294
307
  if (continueResult.code === 0) {
295
- await log(formatAligned('📦', 'Committed:', 'CLAUDE.md revert (conflict resolved)'));
308
+ await log(formatAligned('📦', 'Committed:', `${fileName} revert (conflict resolved)`));
296
309
 
297
310
  // Push the revert
298
311
  const pushRevertResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
299
312
  if (pushRevertResult.code === 0) {
300
- await log(formatAligned('📤', 'Pushed:', 'CLAUDE.md revert to GitHub'));
313
+ await log(formatAligned('📤', 'Pushed:', `${fileName} revert to GitHub`));
301
314
  } else {
302
- await log(' Warning: Could not push CLAUDE.md revert', { verbose: true });
315
+ await log(` Warning: Could not push ${fileName} revert`, { verbose: true });
303
316
  }
304
317
  } else {
305
318
  await log(' Warning: Could not complete revert after conflict resolution', { verbose: true });
306
319
  await log(` Continue output: ${continueResult.stderr || continueResult.stdout}`, { verbose: true });
307
320
  }
308
321
  } else {
309
- // Conflict in some other file, not CLAUDE.md - this is unexpected
322
+ // Conflict in some other file, not expected file - this is unexpected
310
323
  await log(' Warning: Revert conflict in unexpected file(s), aborting revert', { verbose: true });
311
324
  await $({ cwd: tempDir })`git revert --abort 2>&1`;
312
325
  }
313
326
  } else {
314
327
  // Non-conflict error
315
- await log(' Warning: Could not revert CLAUDE.md commit', { verbose: true });
328
+ await log(` Warning: Could not revert ${fileName} commit`, { verbose: true });
316
329
  await log(` Revert output: ${revertOutput}`, { verbose: true });
317
330
  }
318
331
  }
@@ -321,10 +334,10 @@ export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash =
321
334
  reportError(e, {
322
335
  context: 'cleanup_claude_file',
323
336
  tempDir,
324
- operation: 'revert_claude_md_commit',
337
+ operation: 'revert_initial_commit',
325
338
  });
326
339
  // If revert fails, that's okay - the task is still complete
327
- await log(' CLAUDE.md revert failed or not needed', { verbose: true });
340
+ await log(' Initial commit revert failed or not needed', { verbose: true });
328
341
  }
329
342
  };
330
343
 
@@ -42,7 +42,7 @@ const { reportError } = sentryLib;
42
42
  const { validateClaudeConnection } = claudeLib;
43
43
 
44
44
  // Wrapper function for disk space check using imported module
45
- const checkDiskSpace = async (minSpaceMB = 500) => {
45
+ const checkDiskSpace = async (minSpaceMB = 2048) => {
46
46
  const result = await memoryCheck.checkDiskSpace(minSpaceMB, { log });
47
47
  return result.success;
48
48
  };
@@ -204,7 +204,7 @@ export const validateContinueOnlyOnFeedback = async (argv, isPrUrl, isIssueUrl)
204
204
  // Perform all system checks (disk space, memory, tool connection, GitHub permissions)
205
205
  // Note: skipToolConnection only skips the connection check, not model validation
206
206
  // Model validation should be done separately before calling this function
207
- export const performSystemChecks = async (minDiskSpace = 500, skipToolConnection = false, model = 'sonnet', argv = {}) => {
207
+ export const performSystemChecks = async (minDiskSpace = 2048, skipToolConnection = false, model = 'sonnet', argv = {}) => {
208
208
  // Check disk space before proceeding
209
209
  const hasEnoughSpace = await checkDiskSpace(minDiskSpace);
210
210
  if (!hasEnoughSpace) {