@link-assistant/hive-mind 2.12.4 → 2.12.5
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 +6 -0
- package/package.json +1 -1
- package/src/agent.prompts.lib.mjs +12 -0
- package/src/claude.prompts.lib.mjs +9 -0
- package/src/codex.prompts.lib.mjs +9 -0
- package/src/formal-ai-prompt.lib.mjs +29 -0
- package/src/formal-ai.lib.mjs +30 -0
- package/src/gemini.prompts.lib.mjs +9 -0
- package/src/github-url-parser.lib.mjs +8 -0
- package/src/github.lib.mjs +3 -2
- package/src/opencode.prompts.lib.mjs +9 -0
- package/src/qwen.prompts.lib.mjs +9 -0
- package/src/solve.mjs +10 -1
- package/src/solve.restart-shared.lib.mjs +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 2.12.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 77ed9bc: Keep Formal AI repository requests bounded, target the discovered pull request URL, and stop retrying explicit `planned_not_executed` results as successful work.
|
|
8
|
+
|
|
3
9
|
## 2.12.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -9,6 +9,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
9
9
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
10
10
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
11
11
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
12
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
13
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Build the user prompt for Agent
|
|
@@ -16,6 +18,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
16
18
|
* @returns {string} The formatted user prompt
|
|
17
19
|
*/
|
|
18
20
|
export const buildUserPrompt = params => {
|
|
21
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
22
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
23
|
+
|
|
19
24
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv } = params;
|
|
20
25
|
|
|
21
26
|
const promptLines = [];
|
|
@@ -92,6 +97,13 @@ export const buildUserPrompt = params => {
|
|
|
92
97
|
export const buildSystemPrompt = params => {
|
|
93
98
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
94
99
|
|
|
100
|
+
// Issue #2158: Formal AI's deterministic intent router considers the whole
|
|
101
|
+
// provider request, including this caller-owned workflow prompt. Command
|
|
102
|
+
// examples such as `sudo` and `pwd` were consequently executed as if the
|
|
103
|
+
// issue requested them. The compact user prompt remains the repository
|
|
104
|
+
// objective; Formal AI supplies its own execution policy.
|
|
105
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
106
|
+
|
|
95
107
|
// When in fork mode, screenshots are pushed to the fork, not the original repo
|
|
96
108
|
const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
|
|
97
109
|
|
|
@@ -11,6 +11,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
11
11
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
12
12
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
13
13
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
14
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
15
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Build the user prompt for Claude
|
|
@@ -18,6 +20,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
18
20
|
* @returns {string} The formatted user prompt
|
|
19
21
|
*/
|
|
20
22
|
export const buildUserPrompt = params => {
|
|
23
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
24
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
25
|
+
|
|
21
26
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, owner, repo, argv, contributingGuidelines, claudeVersion } = params;
|
|
22
27
|
|
|
23
28
|
if (argv?.minimalRestartContext && argv.resume) {
|
|
@@ -105,6 +110,10 @@ export const buildUserPrompt = params => {
|
|
|
105
110
|
export const buildSystemPrompt = params => {
|
|
106
111
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
107
112
|
|
|
113
|
+
// Issue #2158: keep caller workflow instructions out of Formal AI's task
|
|
114
|
+
// classifier. Formal AI provides its own execution policy.
|
|
115
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
116
|
+
|
|
108
117
|
if (argv?.minimalRestartContext && argv.resume) {
|
|
109
118
|
return '';
|
|
110
119
|
}
|
|
@@ -10,6 +10,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
10
10
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
11
11
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
12
12
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
13
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
14
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* Build the user prompt for Codex
|
|
@@ -17,6 +19,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
17
19
|
* @returns {string} The formatted user prompt
|
|
18
20
|
*/
|
|
19
21
|
export const buildUserPrompt = params => {
|
|
22
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
23
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
24
|
+
|
|
20
25
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv } = params;
|
|
21
26
|
|
|
22
27
|
const promptLines = [];
|
|
@@ -93,6 +98,10 @@ export const buildUserPrompt = params => {
|
|
|
93
98
|
export const buildSystemPrompt = params => {
|
|
94
99
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
95
100
|
|
|
101
|
+
// Issue #2158: keep caller workflow instructions out of Formal AI's task
|
|
102
|
+
// classifier. Formal AI provides its own execution policy.
|
|
103
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
104
|
+
|
|
96
105
|
// When in fork mode, screenshots are pushed to the fork, not the original repo
|
|
97
106
|
const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
|
|
98
107
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the small repository objective sent through native CLIs to Formal AI.
|
|
3
|
+
*
|
|
4
|
+
* Formal AI owns the agent policy for its model. Repeating Hive Mind's native
|
|
5
|
+
* provider policy in the request both wastes context and exposes incidental
|
|
6
|
+
* shell-language cues to Formal AI's deterministic intent router (#2158).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
10
|
+
|
|
11
|
+
export const buildFormalAiRepositoryPrompt = params => {
|
|
12
|
+
if (!isFormalAiModel(params?.argv?.model)) return null;
|
|
13
|
+
|
|
14
|
+
const { issueUrl, issueNumber, prNumber, prUrl, branchName, isContinueMode, feedbackLines, owner, repo } = params;
|
|
15
|
+
const issueReference = isContinueMode && issueNumber && owner && repo ? `https://github.com/${owner}/${repo}/issues/${issueNumber}` : issueUrl || `the issue linked to pull request ${prNumber}`;
|
|
16
|
+
const lines = [`Resolve the GitHub issue at ${issueReference} in this repository.`];
|
|
17
|
+
|
|
18
|
+
if (branchName) lines.push(`Keep the solution on branch ${branchName}.`);
|
|
19
|
+
if (prUrl) lines.push(`Update the pull request at ${prUrl}.`);
|
|
20
|
+
// The review text is caller-controlled and can contain command snippets.
|
|
21
|
+
// Point Formal AI to the canonical PR instead of copying those snippets into
|
|
22
|
+
// the intent-classification request.
|
|
23
|
+
if (feedbackLines?.length && prUrl) lines.push('Review and address all feedback recorded on that pull request.');
|
|
24
|
+
|
|
25
|
+
lines.push('', 'Implement and verify the solution before reporting completion.', isContinueMode ? 'Continue.' : 'Proceed.');
|
|
26
|
+
return `${lines.join('\n')}\n`;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default { buildFormalAiRepositoryPrompt };
|
package/src/formal-ai.lib.mjs
CHANGED
|
@@ -217,6 +217,36 @@ export const createPreparedToolResult = preparedCommand => ({
|
|
|
217
217
|
errorDuringExecution: false,
|
|
218
218
|
});
|
|
219
219
|
|
|
220
|
+
const FORMAL_AI_NON_EXECUTION_PATTERNS = [/^\s*planned,\s*not executed\b/im, /^\s*planned_not_executed\s*$/im, /^\s*terminal_state\s+["']?planned_not_executed\b/im];
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Turn Formal AI's explicit non-execution terminal state into a failed tool
|
|
224
|
+
* result (issue #2158).
|
|
225
|
+
*
|
|
226
|
+
* Formal AI 0.339.1 truthfully reports repository work as
|
|
227
|
+
* `planned_not_executed`, but each native CLI exits zero. Treating that process
|
|
228
|
+
* exit as a successful solve made `--auto-restart-until-mergeable` repeat the
|
|
229
|
+
* same deterministic plan five times. Keep the model's summary for evidence,
|
|
230
|
+
* while giving Hive Mind an actionable terminal failure.
|
|
231
|
+
*/
|
|
232
|
+
export const classifyFormalAiToolResult = ({ model, toolResult } = {}) => {
|
|
233
|
+
if (!toolResult || !isFormalAiModel(model) || toolResult.success === false) return toolResult;
|
|
234
|
+
|
|
235
|
+
const evidence = [toolResult.resultSummary, toolResult.result, toolResult.lastMessage, toolResult.output].filter(value => typeof value === 'string').join('\n');
|
|
236
|
+
if (!FORMAL_AI_NON_EXECUTION_PATTERNS.some(pattern => pattern.test(evidence))) return toolResult;
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
...toolResult,
|
|
240
|
+
success: false,
|
|
241
|
+
errorDuringExecution: true,
|
|
242
|
+
formalAiNonExecution: true,
|
|
243
|
+
errorInfo: {
|
|
244
|
+
code: 'FORMAL_AI_PLANNED_NOT_EXECUTED',
|
|
245
|
+
message: "Formal AI did not execute repository work; it returned the terminal state planned_not_executed. Fix or upgrade Formal AI's repository-work executor before retrying.",
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
|
|
220
250
|
export const logPreparedToolCommand = async ({ argv, fullCommand, log, formatAligned }) => {
|
|
221
251
|
await log(`\n${formatAligned('📝', 'Raw command:', '')}`);
|
|
222
252
|
await log(fullCommand);
|
|
@@ -9,6 +9,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
9
9
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
10
10
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
11
11
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
12
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
13
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Build the user prompt for Gemini
|
|
@@ -16,6 +18,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
16
18
|
* @returns {string} The formatted user prompt
|
|
17
19
|
*/
|
|
18
20
|
export const buildUserPrompt = params => {
|
|
21
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
22
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
23
|
+
|
|
19
24
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv } = params;
|
|
20
25
|
|
|
21
26
|
const promptLines = [];
|
|
@@ -81,6 +86,10 @@ export const buildUserPrompt = params => {
|
|
|
81
86
|
export const buildSystemPrompt = params => {
|
|
82
87
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
83
88
|
|
|
89
|
+
// Issue #2158: keep caller workflow instructions out of Formal AI's task
|
|
90
|
+
// classifier. Formal AI provides its own execution policy.
|
|
91
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
92
|
+
|
|
84
93
|
const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
|
|
85
94
|
|
|
86
95
|
let workspaceInstructions = '';
|
|
@@ -241,6 +241,14 @@ export function normalizeGitHubUrl(url) {
|
|
|
241
241
|
const parsed = parseGitHubUrl(url);
|
|
242
242
|
return parsed.valid ? parsed.normalized : null;
|
|
243
243
|
}
|
|
244
|
+
|
|
245
|
+
/** Build the canonical web URL for a pull request already identified by GitHub. */
|
|
246
|
+
export function buildGitHubPullRequestUrl({ owner, repo, number } = {}) {
|
|
247
|
+
if (!owner || !repo || !Number.isInteger(Number(number)) || Number(number) <= 0) {
|
|
248
|
+
throw new TypeError('A GitHub pull request URL requires owner, repo, and a positive integer number');
|
|
249
|
+
}
|
|
250
|
+
return `https://github.com/${owner}/${repo}/pull/${Number(number)}`;
|
|
251
|
+
}
|
|
244
252
|
/**
|
|
245
253
|
* Check if a URL is a valid GitHub URL of a specific type
|
|
246
254
|
* @param {string} url - The URL to check
|
package/src/github.lib.mjs
CHANGED
|
@@ -20,8 +20,8 @@ export { buildCostInfoString };
|
|
|
20
20
|
// #1756: route gh exec calls through transient + rate-limit retry wrapper
|
|
21
21
|
import { execGhWithRetry } from './github-rate-limit.lib.mjs';
|
|
22
22
|
import { QUIET_PROBE } from './quiet-probe.lib.mjs'; // issues #2130, #2135: keep read-only probe payloads out of the attached log
|
|
23
|
-
import { isGitHubUrlType, normalizeGitHubUrl, parseGitHubUrl } from './github-url-parser.lib.mjs';
|
|
24
|
-
export { isGitHubUrlType, normalizeGitHubUrl, parseGitHubUrl };
|
|
23
|
+
import { buildGitHubPullRequestUrl, isGitHubUrlType, normalizeGitHubUrl, parseGitHubUrl } from './github-url-parser.lib.mjs';
|
|
24
|
+
export { buildGitHubPullRequestUrl, isGitHubUrlType, normalizeGitHubUrl, parseGitHubUrl };
|
|
25
25
|
// Issue #1625: Named marker constants (single source of truth) + in-memory tracking for tool-posted comments. See tool-comments.lib.mjs for design.
|
|
26
26
|
import { SOLUTION_DRAFT_LOG_MARKER, SOLUTION_DRAFT_FAILED_MARKER, SOLUTION_DRAFT_FINISHED_WITH_ERRORS_MARKER, USAGE_LIMIT_REACHED_MARKER, NOW_WORKING_SESSION_IS_ENDED_MARKER, postTrackedComment, postTrackedCommentFromFile } from './tool-comments.lib.mjs';
|
|
27
27
|
export const maskGitHubToken = maskToken; // Alias for backward compatibility
|
|
@@ -1168,6 +1168,7 @@ export default {
|
|
|
1168
1168
|
fetchProjectIssues,
|
|
1169
1169
|
isRateLimitError,
|
|
1170
1170
|
batchCheckPullRequestsForIssues,
|
|
1171
|
+
buildGitHubPullRequestUrl,
|
|
1171
1172
|
parseGitHubUrl,
|
|
1172
1173
|
normalizeGitHubUrl,
|
|
1173
1174
|
isGitHubUrlType,
|
|
@@ -9,6 +9,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
9
9
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
10
10
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
11
11
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
12
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
13
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Build the user prompt for OpenCode
|
|
@@ -16,6 +18,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
16
18
|
* @returns {string} The formatted user prompt
|
|
17
19
|
*/
|
|
18
20
|
export const buildUserPrompt = params => {
|
|
21
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
22
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
23
|
+
|
|
19
24
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv } = params;
|
|
20
25
|
|
|
21
26
|
const promptLines = [];
|
|
@@ -92,6 +97,10 @@ export const buildUserPrompt = params => {
|
|
|
92
97
|
export const buildSystemPrompt = params => {
|
|
93
98
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
94
99
|
|
|
100
|
+
// Issue #2158: keep caller workflow instructions out of Formal AI's task
|
|
101
|
+
// classifier. Formal AI provides its own execution policy.
|
|
102
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
103
|
+
|
|
95
104
|
// When in fork mode, screenshots are pushed to the fork, not the original repo
|
|
96
105
|
const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
|
|
97
106
|
|
package/src/qwen.prompts.lib.mjs
CHANGED
|
@@ -9,6 +9,8 @@ import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
|
9
9
|
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
10
10
|
import { buildRequestedBaseBranchDirective } from './solve-option-contract.prompts.lib.mjs';
|
|
11
11
|
import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
12
|
+
import { buildFormalAiRepositoryPrompt } from './formal-ai-prompt.lib.mjs';
|
|
13
|
+
import { isFormalAiModel } from './formal-ai-model.lib.mjs';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Build the user prompt for Qwen Code
|
|
@@ -16,6 +18,9 @@ import { buildIssueResearchPrompt } from './deep-analysis.lib.mjs';
|
|
|
16
18
|
* @returns {string} The formatted user prompt
|
|
17
19
|
*/
|
|
18
20
|
export const buildUserPrompt = params => {
|
|
21
|
+
const formalAiPrompt = buildFormalAiRepositoryPrompt(params);
|
|
22
|
+
if (formalAiPrompt !== null) return formalAiPrompt;
|
|
23
|
+
|
|
19
24
|
const { issueUrl, issueNumber, prNumber, prUrl, branchName, tempDir, workspaceTmpDir, isContinueMode, forkedRepo, feedbackLines, forkActionsUrl, owner, repo, argv, tool = 'qwen' } = params;
|
|
20
25
|
|
|
21
26
|
const promptLines = [];
|
|
@@ -81,6 +86,10 @@ export const buildUserPrompt = params => {
|
|
|
81
86
|
export const buildSystemPrompt = params => {
|
|
82
87
|
const { owner, repo, issueNumber, prNumber, branchName, workspaceTmpDir, argv, modelSupportsVision, forkedRepo } = params;
|
|
83
88
|
|
|
89
|
+
// Issue #2158: keep caller workflow instructions out of Formal AI's task
|
|
90
|
+
// classifier. Formal AI provides its own execution policy.
|
|
91
|
+
if (isFormalAiModel(argv?.model)) return '';
|
|
92
|
+
|
|
84
93
|
const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
|
|
85
94
|
|
|
86
95
|
let workspaceInstructions = '';
|
package/src/solve.mjs
CHANGED
|
@@ -69,6 +69,7 @@ const { validateAndExitOnInvalidClaudeSubAgentModel, validateAndExitOnInvalidMod
|
|
|
69
69
|
const { autoAcceptInviteForRepo } = await import('./solve.accept-invite.lib.mjs');
|
|
70
70
|
const { handleAutoForkOption, handleMaintainerForkAccess } = await import('./solve.fork-detection.lib.mjs');
|
|
71
71
|
const { resolveUncommittedChangesTool } = await import('./solve.tool-uncommitted.lib.mjs');
|
|
72
|
+
const { classifyFormalAiToolResult } = await import('./formal-ai.lib.mjs');
|
|
72
73
|
const logFile = await initializeLogFile(null);
|
|
73
74
|
const versionInfo = await getVersionInfo();
|
|
74
75
|
const rawCommand = await logSolveStartup(versionInfo);
|
|
@@ -535,7 +536,10 @@ try {
|
|
|
535
536
|
let prUrl = null;
|
|
536
537
|
// In continue mode, we already have the PR details
|
|
537
538
|
if (isContinueMode) {
|
|
538
|
-
|
|
539
|
+
// Issue #2158: auto-continue can discover a PR while the input remains an
|
|
540
|
+
// issue URL. Passing that issue URL as "Your prepared Pull Request" sent
|
|
541
|
+
// the first Formal AI attempt to the wrong GitHub entity.
|
|
542
|
+
prUrl = githubLib.buildGitHubPullRequestUrl({ owner, repo, number: prNumber });
|
|
539
543
|
// prNumber is already set from earlier when we parsed the PR
|
|
540
544
|
}
|
|
541
545
|
// Handle auto PR creation using the new module
|
|
@@ -757,6 +761,11 @@ try {
|
|
|
757
761
|
});
|
|
758
762
|
toolResult = claudeResult;
|
|
759
763
|
}
|
|
764
|
+
toolResult = classifyFormalAiToolResult({ model: argv.model, toolResult });
|
|
765
|
+
if (toolResult?.formalAiNonExecution) {
|
|
766
|
+
await log(`❌ ${toolResult.errorInfo.message}`, { level: 'error' });
|
|
767
|
+
await log(' The deterministic terminal response will not be retried as a mergeability problem.', { level: 'error' });
|
|
768
|
+
}
|
|
760
769
|
try {
|
|
761
770
|
await recordAfterAgentSize({ tempDir, beforeBytes: cleanupContext.diskDiagnostics?.beforeBytes ?? null, log });
|
|
762
771
|
} catch (diskError) {
|
|
@@ -34,6 +34,7 @@ const { log, formatAligned, extractToolErrorCore } = lib;
|
|
|
34
34
|
const { ensurePullRequestBaseBranch } = await import('./solve.pr-base-guard.lib.mjs');
|
|
35
35
|
const { ensureAiToolScratchIgnored, filterAiToolScratchFromStatus } = await import('./ai-tool-scratch.lib.mjs');
|
|
36
36
|
const { RESOURCE_PHASE_RESTART_AFTER, RESOURCE_PHASE_RESTART_BEFORE, recordResourceSnapshot } = await import('./solve.resource-diagnostics.lib.mjs');
|
|
37
|
+
const { classifyFormalAiToolResult } = await import('./formal-ai.lib.mjs');
|
|
37
38
|
// Issue #2123: shared draft/ready transitions for working sessions.
|
|
38
39
|
const { ensurePullRequestIsDraft } = await import('./pr-draft-state.lib.mjs');
|
|
39
40
|
|
|
@@ -492,6 +493,11 @@ export const executeToolIteration = async params => {
|
|
|
492
493
|
});
|
|
493
494
|
}
|
|
494
495
|
|
|
496
|
+
toolResult = classifyFormalAiToolResult({ model: argv.model, toolResult });
|
|
497
|
+
if (toolResult?.formalAiNonExecution) {
|
|
498
|
+
await log(`❌ ${toolResult.errorInfo.message}`, { level: 'error' });
|
|
499
|
+
}
|
|
500
|
+
|
|
495
501
|
await ensurePullRequestBaseBranch({ owner, repo, prNumber, argv, log, formatAligned, $ });
|
|
496
502
|
await recordResourceSnapshot({
|
|
497
503
|
phase: RESOURCE_PHASE_RESTART_AFTER,
|