@link-assistant/hive-mind 0.41.0 → 0.41.3
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 +24 -0
- package/README.md +2 -0
- package/package.json +1 -1
- package/src/claude.prompts.lib.mjs +1 -1
- package/src/opencode.prompts.lib.mjs +1 -1
- package/src/solve.results.lib.mjs +141 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 0.41.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- db8cef7: Fix CLAUDE.md not being deleted in continue mode
|
|
8
|
+
|
|
9
|
+
When a work session completes successfully but the CLAUDE.md commit hash was lost between sessions (e.g., due to session interruption), the system now attempts to detect the CLAUDE.md commit from the branch structure instead of silently skipping cleanup.
|
|
10
|
+
|
|
11
|
+
**Safety Checks (Preventing Issue #617 Recurrence):**
|
|
12
|
+
|
|
13
|
+
1. CLAUDE.md must exist in current branch
|
|
14
|
+
2. Find merge base to isolate PR-only commits
|
|
15
|
+
3. Must have at least 2 commits (CLAUDE.md + actual work)
|
|
16
|
+
4. First commit message must match expected pattern
|
|
17
|
+
5. First commit must ONLY change CLAUDE.md file
|
|
18
|
+
|
|
19
|
+
Fixes #940
|
|
20
|
+
|
|
21
|
+
## 0.41.2
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 43d5e01: Add image format validation warning to system prompts to prevent "Could not process image" errors. AI solvers are now instructed to verify image files with the 'file' command before reading them, avoiding crashes from corrupted downloads or HTML 404 pages. Includes reference to case study documenting the root cause of GitHub image processing failures.
|
|
26
|
+
|
|
3
27
|
## 0.41.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -296,6 +296,8 @@ review --repo owner/repo --pr 456
|
|
|
296
296
|
| `reviewers-hive.mjs` (alpha / experimental) | Review team management | Multi-agent consensus, reviewer assignment |
|
|
297
297
|
| `telegram-bot.mjs` (stable) | Telegram bot interface | Remote command execution, group chat support, diagnostic tools |
|
|
298
298
|
|
|
299
|
+
> **Note**: For a comprehensive analysis of the "Could not process image" error in AI issue solvers, see the [Case Study: Issue #597](docs/case-studies/issue-597/README.md). The case study includes root cause analysis, timeline reconstruction, and evidence of GitHub's time-limited S3 URLs causing image processing failures. Separate tools for downloading GitHub issues and PRs with embedded images are being developed at [gh-download-issue](https://github.com/link-foundation/gh-download-issue) and [gh-download-pull-request](https://github.com/link-foundation/gh-download-pull-request).
|
|
300
|
+
|
|
299
301
|
## 🔧 solve Options
|
|
300
302
|
```bash
|
|
301
303
|
solve <issue-url> [options]
|
package/package.json
CHANGED
|
@@ -134,7 +134,7 @@ Initial research.
|
|
|
134
134
|
- When you start, make sure you create detailed plan for yourself and follow your todo list step by step, make sure that as many points from these guidelines are added to your todo list to keep track of everything that can help you solve the issue with highest possible quality.
|
|
135
135
|
- When user mentions CI failures or asks to investigate logs, consider adding these todos to track the investigation: (1) List recent CI runs with timestamps, (2) Download logs from failed runs to ci-logs/ directory, (3) Analyze error messages and identify root cause, (4) Implement fix, (5) Verify fix resolves the specific errors found in logs.
|
|
136
136
|
- When you read issue, read all details and comments thoroughly.
|
|
137
|
-
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool (or fetch tool) to download the image first, then use Read tool to view and analyze it.
|
|
137
|
+
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool (or fetch tool) to download the image first, then use Read tool to view and analyze it. IMPORTANT: Before reading downloaded images with the Read tool, verify the file is a valid image (not HTML). Use a CLI tool like 'file' command to check the actual file format. Reading corrupted or non-image files (like GitHub's HTML 404 pages saved as .png) can cause "Could not process image" errors and may crash the AI solver process. If the file command shows "HTML" or "text", the download failed and you should retry or skip the image.
|
|
138
138
|
- When you need issue details, use gh issue view https://github.com/${owner}/${repo}/issues/${issueNumber}.
|
|
139
139
|
- When you need related code, use gh search code --owner ${owner} [keywords].
|
|
140
140
|
- When you need repo context, read files in your working directory.${argv && argv.promptExploreSubAgent ? '\n - When you need to learn something about the codebase structure, patterns, or how things work, use the Task tool with subagent_type=Explore to thoroughly explore the codebase.' : ''}
|
|
@@ -119,7 +119,7 @@ General guidelines.
|
|
|
119
119
|
Initial research.
|
|
120
120
|
- When you start, make sure you create detailed plan for yourself and follow your todo list step by step, make sure that as many points from these guidelines are added to your todo list to keep track of everything that can help you solve the issue with highest possible quality.
|
|
121
121
|
- When you read issue, read all details and comments thoroughly.
|
|
122
|
-
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool to download the image first, then use Read tool to view and analyze it.
|
|
122
|
+
- When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, use WebFetch tool to download the image first, then use Read tool to view and analyze it. IMPORTANT: Before reading downloaded images with the Read tool, verify the file is a valid image (not HTML). Use a CLI tool like 'file' command to check the actual file format. Reading corrupted or non-image files (like GitHub's HTML 404 pages saved as .png) can cause "Could not process image" errors and may crash the AI solver process. If the file command shows "HTML" or "text", the download failed and you should retry or skip the image.
|
|
123
123
|
- When you need issue details, use gh issue view https://github.com/${owner}/${repo}/issues/${issueNumber}.
|
|
124
124
|
- When you need related code, use gh search code --owner ${owner} [keywords].
|
|
125
125
|
- When you need repo context, read files in your working directory.
|
|
@@ -50,14 +50,151 @@ const { reportError } = sentryLib;
|
|
|
50
50
|
const githubLinking = await import('./github-linking.lib.mjs');
|
|
51
51
|
const { hasGitHubLinkingKeyword } = githubLinking;
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Detect the CLAUDE.md commit hash from branch structure when not available in session
|
|
55
|
+
* This handles continue mode where the commit hash was lost between sessions
|
|
56
|
+
*
|
|
57
|
+
* Safety checks to prevent Issue #617 (wrong commit revert):
|
|
58
|
+
* 1. Only look at commits on the PR branch (not default branch commits)
|
|
59
|
+
* 2. Verify the commit message matches our expected pattern
|
|
60
|
+
* 3. Verify the commit ONLY adds CLAUDE.md (no other files changed)
|
|
61
|
+
* 4. Verify there are additional commits after it (actual work was done)
|
|
62
|
+
*
|
|
63
|
+
* @param {string} tempDir - The temporary directory with the git repo
|
|
64
|
+
* @param {string} branchName - The PR branch name
|
|
65
|
+
* @returns {string|null} - The detected commit hash or null if not found/safe
|
|
66
|
+
*/
|
|
67
|
+
const detectClaudeMdCommitFromBranch = async (tempDir, branchName) => {
|
|
68
|
+
try {
|
|
69
|
+
await log(' Attempting to detect CLAUDE.md commit from branch structure...', { verbose: true });
|
|
70
|
+
|
|
71
|
+
// First check if CLAUDE.md exists in current branch
|
|
72
|
+
const claudeMdExistsResult = await $({ cwd: tempDir })`git ls-files CLAUDE.md 2>&1`;
|
|
73
|
+
if (claudeMdExistsResult.code !== 0 || !claudeMdExistsResult.stdout || !claudeMdExistsResult.stdout.trim()) {
|
|
74
|
+
await log(' CLAUDE.md does not exist in current branch', { verbose: true });
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Get the default branch to find the fork point
|
|
79
|
+
const defaultBranchResult = await $({ cwd: tempDir })`git symbolic-ref refs/remotes/origin/HEAD 2>&1`;
|
|
80
|
+
let defaultBranch = 'main';
|
|
81
|
+
if (defaultBranchResult.code === 0 && defaultBranchResult.stdout) {
|
|
82
|
+
const match = defaultBranchResult.stdout.toString().match(/refs\/remotes\/origin\/(.+)/);
|
|
83
|
+
if (match) {
|
|
84
|
+
defaultBranch = match[1].trim();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await log(` Using default branch: ${defaultBranch}`, { verbose: true });
|
|
88
|
+
|
|
89
|
+
// Find the merge base (fork point) between current branch and default branch
|
|
90
|
+
const mergeBaseResult = await $({ cwd: tempDir })`git merge-base origin/${defaultBranch} HEAD 2>&1`;
|
|
91
|
+
if (mergeBaseResult.code !== 0 || !mergeBaseResult.stdout) {
|
|
92
|
+
await log(' Could not find merge base, cannot safely detect CLAUDE.md commit', { verbose: true });
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
const mergeBase = mergeBaseResult.stdout.toString().trim();
|
|
96
|
+
await log(` Merge base: ${mergeBase.substring(0, 7)}`, { verbose: true });
|
|
97
|
+
|
|
98
|
+
// Get all commits on the PR branch (commits after the merge base)
|
|
99
|
+
// Format: hash|message|files_changed
|
|
100
|
+
const branchCommitsResult = await $({ cwd: tempDir })`git log ${mergeBase}..HEAD --reverse --format="%H|%s" 2>&1`;
|
|
101
|
+
if (branchCommitsResult.code !== 0 || !branchCommitsResult.stdout) {
|
|
102
|
+
await log(' No commits found on PR branch', { verbose: true });
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const branchCommits = branchCommitsResult.stdout.toString().trim().split('\n').filter(Boolean);
|
|
107
|
+
if (branchCommits.length === 0) {
|
|
108
|
+
await log(' No commits found on PR branch', { verbose: true });
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
await log(` Found ${branchCommits.length} commit(s) on PR branch`, { verbose: true });
|
|
113
|
+
|
|
114
|
+
// Safety check: Must have at least 2 commits (CLAUDE.md commit + actual work)
|
|
115
|
+
if (branchCommits.length < 2) {
|
|
116
|
+
await log(' Only 1 commit on branch - not enough commits to safely revert CLAUDE.md', { verbose: true });
|
|
117
|
+
await log(' (Need at least 2 commits: CLAUDE.md initial + actual work)', { verbose: true });
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Get the first commit on the PR branch
|
|
122
|
+
const firstCommitLine = branchCommits[0];
|
|
123
|
+
const [firstCommitHash, firstCommitMessage] = firstCommitLine.split('|');
|
|
124
|
+
|
|
125
|
+
await log(` First commit on branch: ${firstCommitHash.substring(0, 7)} - "${firstCommitMessage}"`, { verbose: true });
|
|
126
|
+
|
|
127
|
+
// Safety check: Verify commit message matches expected pattern
|
|
128
|
+
const expectedMessagePatterns = [
|
|
129
|
+
/^Initial commit with task details/i,
|
|
130
|
+
/^Add CLAUDE\.md/i,
|
|
131
|
+
/^CLAUDE\.md/i
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const messageMatches = expectedMessagePatterns.some(pattern => pattern.test(firstCommitMessage));
|
|
135
|
+
if (!messageMatches) {
|
|
136
|
+
await log(' First commit message does not match expected CLAUDE.md pattern', { verbose: true });
|
|
137
|
+
await log(' Expected patterns: "Initial commit with task details...", "Add CLAUDE.md", etc.', { verbose: true });
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Safety check: Verify the commit ONLY adds CLAUDE.md file (no other files)
|
|
142
|
+
const filesChangedResult = await $({ cwd: tempDir })`git diff-tree --no-commit-id --name-only -r ${firstCommitHash} 2>&1`;
|
|
143
|
+
if (filesChangedResult.code !== 0 || !filesChangedResult.stdout) {
|
|
144
|
+
await log(' Could not get files changed in first commit', { verbose: true });
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const filesChanged = filesChangedResult.stdout.toString().trim().split('\n').filter(Boolean);
|
|
149
|
+
await log(` Files changed in first commit: ${filesChanged.join(', ')}`, { verbose: true });
|
|
150
|
+
|
|
151
|
+
// Check if CLAUDE.md is in the files changed
|
|
152
|
+
if (!filesChanged.includes('CLAUDE.md')) {
|
|
153
|
+
await log(' First commit does not include CLAUDE.md', { verbose: true });
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// CRITICAL SAFETY CHECK: Only allow revert if CLAUDE.md is the ONLY file changed
|
|
158
|
+
// This prevents Issue #617 where reverting a commit deleted .gitignore, LICENSE, README.md
|
|
159
|
+
if (filesChanged.length > 1) {
|
|
160
|
+
await log(` ⚠️ First commit changes more than just CLAUDE.md (${filesChanged.length} files)`, { verbose: true });
|
|
161
|
+
await log(` Files: ${filesChanged.join(', ')}`, { verbose: true });
|
|
162
|
+
await log(' Refusing to revert to prevent data loss (Issue #617 safety)', { verbose: true });
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// All safety checks passed!
|
|
167
|
+
await log(` ✅ Detected CLAUDE.md commit: ${firstCommitHash.substring(0, 7)}`, { verbose: true });
|
|
168
|
+
await log(' ✅ Commit only contains CLAUDE.md (safe to revert)', { verbose: true });
|
|
169
|
+
await log(` ✅ Branch has ${branchCommits.length - 1} additional commit(s) (work was done)`, { verbose: true });
|
|
170
|
+
|
|
171
|
+
return firstCommitHash;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
reportError(error, {
|
|
174
|
+
context: 'detect_claude_md_commit',
|
|
175
|
+
tempDir,
|
|
176
|
+
branchName,
|
|
177
|
+
operation: 'detect_commit_from_branch_structure'
|
|
178
|
+
});
|
|
179
|
+
await log(` Error detecting CLAUDE.md commit: ${error.message}`, { verbose: true });
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
53
184
|
// Revert the CLAUDE.md commit to restore original state
|
|
54
185
|
export const cleanupClaudeFile = async (tempDir, branchName, claudeCommitHash = null) => {
|
|
55
186
|
try {
|
|
56
|
-
//
|
|
57
|
-
// This
|
|
187
|
+
// If no commit hash provided, try to detect it from branch structure
|
|
188
|
+
// This handles continue mode where the hash was lost between sessions
|
|
58
189
|
if (!claudeCommitHash) {
|
|
59
|
-
await log(' No CLAUDE.md commit
|
|
60
|
-
|
|
190
|
+
await log(' No CLAUDE.md commit hash from session, attempting to detect from branch...', { verbose: true });
|
|
191
|
+
claudeCommitHash = await detectClaudeMdCommitFromBranch(tempDir, branchName);
|
|
192
|
+
|
|
193
|
+
if (!claudeCommitHash) {
|
|
194
|
+
await log(' Could not safely detect CLAUDE.md commit to revert', { verbose: true });
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
await log(` Detected CLAUDE.md commit: ${claudeCommitHash.substring(0, 7)}`, { verbose: true });
|
|
61
198
|
}
|
|
62
199
|
|
|
63
200
|
await log(formatAligned('🔄', 'Cleanup:', 'Reverting CLAUDE.md commit'));
|