@iloom/cli 0.1.17 → 0.1.19
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/README.md +51 -6
- package/dist/ClaudeContextManager-JKR4WGNU.js +13 -0
- package/dist/ClaudeService-55DQGB7T.js +12 -0
- package/dist/{GitHubService-F7Z3XJOS.js → GitHubService-LWP4GKGH.js} +3 -3
- package/dist/{LoomLauncher-MODG2SEM.js → LoomLauncher-UMMLPIZO.js} +7 -7
- package/dist/{PromptTemplateManager-7FINLRDE.js → PromptTemplateManager-WII75TKH.js} +2 -2
- package/dist/README.md +755 -0
- package/dist/{SettingsManager-VAZF26S2.js → SettingsManager-SKLUVE3K.js} +6 -2
- package/dist/{add-issue-22JBNOML.js → add-issue-X56V3XPB.js} +23 -8
- package/dist/add-issue-X56V3XPB.js.map +1 -0
- package/dist/{chunk-Y7SAGNUT.js → chunk-DEPYQRRB.js} +2 -2
- package/dist/{chunk-WKEWRSDB.js → chunk-ELFT36PV.js} +3 -3
- package/dist/chunk-FXV24OYZ.js +83 -0
- package/dist/chunk-FXV24OYZ.js.map +1 -0
- package/dist/{chunk-HPJJSYNS.js → chunk-H5LDRGVK.js} +6 -8
- package/dist/{chunk-HPJJSYNS.js.map → chunk-H5LDRGVK.js.map} +1 -1
- package/dist/{chunk-QEPVTTHD.js → chunk-IO4WFTL2.js} +17 -11
- package/dist/chunk-IO4WFTL2.js.map +1 -0
- package/dist/{chunk-KQDEK2ZW.js → chunk-JXQXSC45.js} +41 -9
- package/dist/chunk-JXQXSC45.js.map +1 -0
- package/dist/{chunk-JQ7VOSTC.js → chunk-KOCQAD2E.js} +3 -3
- package/dist/{chunk-YYSKGAZT.js → chunk-LAPY6NAE.js} +17 -8
- package/dist/chunk-LAPY6NAE.js.map +1 -0
- package/dist/{chunk-O2QWO64Z.js → chunk-PV3GAXQO.js} +56 -3
- package/dist/chunk-PV3GAXQO.js.map +1 -0
- package/dist/chunk-PVAVNJKS.js +188 -0
- package/dist/chunk-PVAVNJKS.js.map +1 -0
- package/dist/{chunk-CP2NU2JC.js → chunk-Q2KYPAH2.js} +7 -7
- package/dist/{chunk-CP2NU2JC.js.map → chunk-Q2KYPAH2.js.map} +1 -1
- package/dist/{chunk-W3DQTW63.js → chunk-USVVV3FP.js} +4 -4
- package/dist/{chunk-SSR5AVRJ.js → chunk-VCMMAFXQ.js} +21 -8
- package/dist/chunk-VCMMAFXQ.js.map +1 -0
- package/dist/chunk-VVH3ANF2.js +307 -0
- package/dist/chunk-VVH3ANF2.js.map +1 -0
- package/dist/{chunk-JBH2ZYYZ.js → chunk-VYQLLHZ7.js} +22 -3
- package/dist/chunk-VYQLLHZ7.js.map +1 -0
- package/dist/{chunk-SJUQ2NDR.js → chunk-ZMNQBJUI.js} +24 -19
- package/dist/chunk-ZMNQBJUI.js.map +1 -0
- package/dist/{chunk-T7QPXANZ.js → chunk-ZWXJBSUW.js} +17 -17
- package/dist/chunk-ZWXJBSUW.js.map +1 -0
- package/dist/{cleanup-3LUWPSM7.js → cleanup-ZHROIBSQ.js} +12 -16
- package/dist/cleanup-ZHROIBSQ.js.map +1 -0
- package/dist/cli.js +107 -49
- package/dist/cli.js.map +1 -1
- package/dist/contribute-3MQJ3XAQ.js +256 -0
- package/dist/contribute-3MQJ3XAQ.js.map +1 -0
- package/dist/{enhance-XJIQHVPD.js → enhance-VGWUX474.js} +18 -8
- package/dist/enhance-VGWUX474.js.map +1 -0
- package/dist/{feedback-23CLXKFT.js → feedback-ZOUCCHN4.js} +8 -8
- package/dist/{finish-3CQZIULO.js → finish-QJSK6Z7J.js} +36 -313
- package/dist/finish-QJSK6Z7J.js.map +1 -0
- package/dist/{git-LVRZ57GJ.js → git-OUYMVYJX.js} +2 -2
- package/dist/{ignite-WXEF2ID5.js → ignite-HICLZEYU.js} +124 -9
- package/dist/ignite-HICLZEYU.js.map +1 -0
- package/dist/index.d.ts +794 -712
- package/dist/index.js +169 -36
- package/dist/index.js.map +1 -1
- package/dist/init-UMKNHNV5.js +339 -0
- package/dist/init-UMKNHNV5.js.map +1 -0
- package/dist/mcp/github-comment-server.js +12 -9
- package/dist/mcp/github-comment-server.js.map +1 -1
- package/dist/neon-helpers-ZVIRPKCI.js +10 -0
- package/dist/{open-X6BTENPV.js → open-ETZUFSE4.js} +15 -17
- package/dist/{open-X6BTENPV.js.map → open-ETZUFSE4.js.map} +1 -1
- package/dist/prompts/init-prompt.txt +748 -0
- package/dist/prompts/issue-prompt.txt +141 -9
- package/dist/rebase-KBWFDZCN.js +95 -0
- package/dist/rebase-KBWFDZCN.js.map +1 -0
- package/dist/remote-GJEZWRCC.js +14 -0
- package/dist/{run-2JCPQAX3.js → run-4SVQ3WEU.js} +15 -17
- package/dist/{run-2JCPQAX3.js.map → run-4SVQ3WEU.js.map} +1 -1
- package/dist/schema/settings.schema.json +51 -1
- package/dist/{start-LWVRBJ6S.js → start-CT2ZEFP2.js} +54 -53
- package/dist/{start-LWVRBJ6S.js.map → start-CT2ZEFP2.js.map} +1 -1
- package/dist/{test-git-XPF4SZXJ.js → test-git-MKZATGZN.js} +3 -3
- package/dist/{test-prefix-XGFXFAYN.js → test-prefix-ZNLWDI3K.js} +3 -3
- package/dist/{update-DN3FSNKY.js → update-4TDDUR5K.js} +10 -4
- package/dist/{update-DN3FSNKY.js.map → update-4TDDUR5K.js.map} +1 -1
- package/package.json +3 -2
- package/dist/ClaudeContextManager-XOSXQ67R.js +0 -13
- package/dist/ClaudeService-YSZ6EXWP.js +0 -12
- package/dist/NeonProvider-PAGPUH7F.js +0 -12
- package/dist/add-issue-22JBNOML.js.map +0 -1
- package/dist/chunk-37DYYFVK.js +0 -29
- package/dist/chunk-37DYYFVK.js.map +0 -1
- package/dist/chunk-F3XBU2R7.js +0 -110
- package/dist/chunk-F3XBU2R7.js.map +0 -1
- package/dist/chunk-JBH2ZYYZ.js.map +0 -1
- package/dist/chunk-KQDEK2ZW.js.map +0 -1
- package/dist/chunk-O2QWO64Z.js.map +0 -1
- package/dist/chunk-QEPVTTHD.js.map +0 -1
- package/dist/chunk-SJUQ2NDR.js.map +0 -1
- package/dist/chunk-SSR5AVRJ.js.map +0 -1
- package/dist/chunk-T7QPXANZ.js.map +0 -1
- package/dist/chunk-YYSKGAZT.js.map +0 -1
- package/dist/cleanup-3LUWPSM7.js.map +0 -1
- package/dist/enhance-XJIQHVPD.js.map +0 -1
- package/dist/env-MDFL4ZXL.js +0 -23
- package/dist/finish-3CQZIULO.js.map +0 -1
- package/dist/ignite-WXEF2ID5.js.map +0 -1
- package/dist/init-RHACUR4E.js +0 -123
- package/dist/init-RHACUR4E.js.map +0 -1
- /package/dist/{ClaudeContextManager-XOSXQ67R.js.map → ClaudeContextManager-JKR4WGNU.js.map} +0 -0
- /package/dist/{ClaudeService-YSZ6EXWP.js.map → ClaudeService-55DQGB7T.js.map} +0 -0
- /package/dist/{GitHubService-F7Z3XJOS.js.map → GitHubService-LWP4GKGH.js.map} +0 -0
- /package/dist/{LoomLauncher-MODG2SEM.js.map → LoomLauncher-UMMLPIZO.js.map} +0 -0
- /package/dist/{NeonProvider-PAGPUH7F.js.map → PromptTemplateManager-WII75TKH.js.map} +0 -0
- /package/dist/{PromptTemplateManager-7FINLRDE.js.map → SettingsManager-SKLUVE3K.js.map} +0 -0
- /package/dist/{chunk-Y7SAGNUT.js.map → chunk-DEPYQRRB.js.map} +0 -0
- /package/dist/{chunk-WKEWRSDB.js.map → chunk-ELFT36PV.js.map} +0 -0
- /package/dist/{chunk-JQ7VOSTC.js.map → chunk-KOCQAD2E.js.map} +0 -0
- /package/dist/{chunk-W3DQTW63.js.map → chunk-USVVV3FP.js.map} +0 -0
- /package/dist/{feedback-23CLXKFT.js.map → feedback-ZOUCCHN4.js.map} +0 -0
- /package/dist/{SettingsManager-VAZF26S2.js.map → git-OUYMVYJX.js.map} +0 -0
- /package/dist/{env-MDFL4ZXL.js.map → neon-helpers-ZVIRPKCI.js.map} +0 -0
- /package/dist/{git-LVRZ57GJ.js.map → remote-GJEZWRCC.js.map} +0 -0
- /package/dist/{test-git-XPF4SZXJ.js.map → test-git-MKZATGZN.js.map} +0 -0
- /package/dist/{test-prefix-XGFXFAYN.js.map → test-prefix-ZNLWDI3K.js.map} +0 -0
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MergeManager
|
|
4
|
+
} from "./chunk-VVH3ANF2.js";
|
|
2
5
|
import {
|
|
3
6
|
ResourceCleanup
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-Q2KYPAH2.js";
|
|
5
8
|
import {
|
|
6
9
|
IdentifierParser
|
|
7
10
|
} from "./chunk-H4E4THUZ.js";
|
|
@@ -12,16 +15,18 @@ import {
|
|
|
12
15
|
CLIIsolationManager,
|
|
13
16
|
DatabaseManager,
|
|
14
17
|
EnvironmentManager
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import
|
|
18
|
+
} from "./chunk-H5LDRGVK.js";
|
|
19
|
+
import {
|
|
20
|
+
loadEnvIntoProcess
|
|
21
|
+
} from "./chunk-ZMNQBJUI.js";
|
|
17
22
|
import {
|
|
18
23
|
detectPackageManager,
|
|
19
24
|
installDependencies,
|
|
20
25
|
runScript
|
|
21
26
|
} from "./chunk-BLCTGFZN.js";
|
|
22
27
|
import {
|
|
23
|
-
|
|
24
|
-
} from "./chunk-
|
|
28
|
+
createNeonProviderFromSettings
|
|
29
|
+
} from "./chunk-LAPY6NAE.js";
|
|
25
30
|
import {
|
|
26
31
|
ProjectCapabilityDetector
|
|
27
32
|
} from "./chunk-CWR2SANQ.js";
|
|
@@ -30,26 +35,27 @@ import {
|
|
|
30
35
|
readPackageJson
|
|
31
36
|
} from "./chunk-2ZPFJQ3B.js";
|
|
32
37
|
import {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
getConfiguredRepoFromSettings,
|
|
39
|
+
hasMultipleRemotes
|
|
40
|
+
} from "./chunk-FXV24OYZ.js";
|
|
36
41
|
import {
|
|
37
|
-
|
|
38
|
-
} from "./chunk-
|
|
42
|
+
GitHubService
|
|
43
|
+
} from "./chunk-ZWXJBSUW.js";
|
|
44
|
+
import "./chunk-JXQXSC45.js";
|
|
39
45
|
import {
|
|
40
46
|
detectClaudeCli,
|
|
41
47
|
launchClaude
|
|
42
48
|
} from "./chunk-PXZBAC2M.js";
|
|
43
49
|
import {
|
|
44
50
|
GitWorktreeManager
|
|
45
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-IO4WFTL2.js";
|
|
46
52
|
import {
|
|
47
53
|
SettingsManager
|
|
48
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-VYQLLHZ7.js";
|
|
49
55
|
import {
|
|
50
56
|
executeGitCommand,
|
|
51
57
|
findMainWorktreePathWithSettings
|
|
52
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-KOCQAD2E.js";
|
|
53
59
|
import "./chunk-JNKJ7NJV.js";
|
|
54
60
|
import {
|
|
55
61
|
logger
|
|
@@ -377,11 +383,11 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
377
383
|
getClaudePrompt(validationType, validationCommand) {
|
|
378
384
|
switch (validationType) {
|
|
379
385
|
case "typecheck":
|
|
380
|
-
return `There are TypeScript errors in this codebase. Please analyze the typecheck output, identify all type errors, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues.When you are done, tell the user to quit to continue the validation process.`;
|
|
386
|
+
return `There are TypeScript errors in this codebase. Please analyze the typecheck output, identify all type errors, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues. When you are done, tell the user to quit using /exit to continue the validation process.`;
|
|
381
387
|
case "lint":
|
|
382
|
-
return `There are ESLint errors in this codebase. Please analyze the linting output, identify all linting issues, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. Focus on code quality, consistency, and following the project's linting rules.When you are done, tell the user to quit to continue the validation process.`;
|
|
388
|
+
return `There are ESLint errors in this codebase. Please analyze the linting output, identify all linting issues, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. Focus on code quality, consistency, and following the project's linting rules. When you are done, tell the user to quit using /exit to continue the validation process.`;
|
|
383
389
|
case "test":
|
|
384
|
-
return `There are unit test failures in this codebase. Please analyze the test output to understand what's failing, then fix the issues. This might involve updating test code, fixing bugs in the source code, or updating tests to match new behavior. Run '${validationCommand}' to see the detailed test failures, then make the necessary changes to get all tests passing.When you are done, tell the user to quit to continue the validation process.`;
|
|
390
|
+
return `There are unit test failures in this codebase. Please analyze the test output to understand what's failing, then fix the issues. This might involve updating test code, fixing bugs in the source code, or updating tests to match new behavior. Run '${validationCommand}' to see the detailed test failures, then make the necessary changes to get all tests passing. When you are done, tell the user to quit using /exit to continue the validation process.`;
|
|
385
391
|
}
|
|
386
392
|
}
|
|
387
393
|
};
|
|
@@ -697,293 +703,6 @@ Start your response immediately with the commit message text.
|
|
|
697
703
|
}
|
|
698
704
|
};
|
|
699
705
|
|
|
700
|
-
// src/lib/MergeManager.ts
|
|
701
|
-
var MergeManager = class {
|
|
702
|
-
constructor(settingsManager) {
|
|
703
|
-
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* Get the main branch name from settings (defaults to 'main')
|
|
707
|
-
* @private
|
|
708
|
-
*/
|
|
709
|
-
async getMainBranch() {
|
|
710
|
-
const settings = await this.settingsManager.loadSettings();
|
|
711
|
-
return settings.mainBranch ?? "main";
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* Rebase current branch on main with fail-fast on conflicts
|
|
715
|
-
* Ports bash/merge-and-clean.sh lines 781-913
|
|
716
|
-
*
|
|
717
|
-
* @param worktreePath - Path to the worktree
|
|
718
|
-
* @param options - Merge options (dryRun, force)
|
|
719
|
-
* @throws Error if main branch doesn't exist, uncommitted changes exist, or conflicts occur
|
|
720
|
-
*/
|
|
721
|
-
async rebaseOnMain(worktreePath, options = {}) {
|
|
722
|
-
const { dryRun = false, force = false } = options;
|
|
723
|
-
const mainBranch = await this.getMainBranch();
|
|
724
|
-
logger.info(`Starting rebase on ${mainBranch} branch...`);
|
|
725
|
-
try {
|
|
726
|
-
await executeGitCommand(["show-ref", "--verify", "--quiet", `refs/heads/${mainBranch}`], {
|
|
727
|
-
cwd: worktreePath
|
|
728
|
-
});
|
|
729
|
-
} catch {
|
|
730
|
-
throw new Error(
|
|
731
|
-
`Main branch "${mainBranch}" does not exist. Cannot rebase.
|
|
732
|
-
Ensure the repository has a "${mainBranch}" branch or create it first.`
|
|
733
|
-
);
|
|
734
|
-
}
|
|
735
|
-
const statusOutput = await executeGitCommand(["status", "--porcelain"], {
|
|
736
|
-
cwd: worktreePath
|
|
737
|
-
});
|
|
738
|
-
if (statusOutput.trim()) {
|
|
739
|
-
throw new Error(
|
|
740
|
-
"Uncommitted changes detected. Please commit or stash changes before rebasing.\nRun: git status to see uncommitted changes\nOr: il finish will automatically commit them for you"
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
const mergeBase = await executeGitCommand(["merge-base", mainBranch, "HEAD"], {
|
|
744
|
-
cwd: worktreePath
|
|
745
|
-
});
|
|
746
|
-
const mainHead = await executeGitCommand(["rev-parse", mainBranch], {
|
|
747
|
-
cwd: worktreePath
|
|
748
|
-
});
|
|
749
|
-
const mergeBaseTrimmed = mergeBase.trim();
|
|
750
|
-
const mainHeadTrimmed = mainHead.trim();
|
|
751
|
-
if (mergeBaseTrimmed === mainHeadTrimmed) {
|
|
752
|
-
logger.success(`Branch is already up to date with ${mainBranch}. No rebase needed.`);
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
const commitsOutput = await executeGitCommand(["log", "--oneline", `${mainBranch}..HEAD`], {
|
|
756
|
-
cwd: worktreePath
|
|
757
|
-
});
|
|
758
|
-
const commits = commitsOutput.trim();
|
|
759
|
-
const commitLines = commits ? commits.split("\n") : [];
|
|
760
|
-
if (commits) {
|
|
761
|
-
logger.info(`Found ${commitLines.length} commit(s) to rebase:`);
|
|
762
|
-
commitLines.forEach((commit) => logger.info(` ${commit}`));
|
|
763
|
-
} else {
|
|
764
|
-
logger.info(`${mainBranch} branch has moved forward. Rebasing to update branch...`);
|
|
765
|
-
}
|
|
766
|
-
if (!force && !dryRun) {
|
|
767
|
-
logger.info("Proceeding with rebase... (use --force to skip confirmations)");
|
|
768
|
-
}
|
|
769
|
-
if (dryRun) {
|
|
770
|
-
logger.info(`[DRY RUN] Would execute: git rebase ${mainBranch}`);
|
|
771
|
-
if (commitLines.length > 0) {
|
|
772
|
-
logger.info(`[DRY RUN] This would rebase ${commitLines.length} commit(s)`);
|
|
773
|
-
}
|
|
774
|
-
return;
|
|
775
|
-
}
|
|
776
|
-
try {
|
|
777
|
-
await executeGitCommand(["rebase", mainBranch], { cwd: worktreePath });
|
|
778
|
-
logger.success("Rebase completed successfully!");
|
|
779
|
-
} catch (error) {
|
|
780
|
-
const conflictedFiles = await this.detectConflictedFiles(worktreePath);
|
|
781
|
-
if (conflictedFiles.length > 0) {
|
|
782
|
-
logger.info("Merge conflicts detected, attempting Claude-assisted resolution...");
|
|
783
|
-
const resolved = await this.attemptClaudeConflictResolution(
|
|
784
|
-
worktreePath,
|
|
785
|
-
conflictedFiles
|
|
786
|
-
);
|
|
787
|
-
if (resolved) {
|
|
788
|
-
logger.success("Conflicts resolved with Claude assistance, rebase completed");
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
const conflictError = this.formatConflictError(conflictedFiles);
|
|
792
|
-
throw new Error(conflictError);
|
|
793
|
-
}
|
|
794
|
-
throw new Error(
|
|
795
|
-
`Rebase failed: ${error instanceof Error ? error.message : String(error)}
|
|
796
|
-
Run: git status for more details
|
|
797
|
-
Or: git rebase --abort to cancel the rebase`
|
|
798
|
-
);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* Validate that fast-forward merge is possible
|
|
803
|
-
* Ports bash/merge-and-clean.sh lines 957-968
|
|
804
|
-
*
|
|
805
|
-
* @param branchName - Name of the branch to merge
|
|
806
|
-
* @param mainWorktreePath - Path where main branch is checked out
|
|
807
|
-
* @throws Error if fast-forward is not possible
|
|
808
|
-
*/
|
|
809
|
-
async validateFastForwardPossible(branchName, mainWorktreePath) {
|
|
810
|
-
const mainBranch = await this.getMainBranch();
|
|
811
|
-
const mergeBase = await executeGitCommand(["merge-base", mainBranch, branchName], {
|
|
812
|
-
cwd: mainWorktreePath
|
|
813
|
-
});
|
|
814
|
-
const mainHead = await executeGitCommand(["rev-parse", mainBranch], {
|
|
815
|
-
cwd: mainWorktreePath
|
|
816
|
-
});
|
|
817
|
-
const mergeBaseTrimmed = mergeBase.trim();
|
|
818
|
-
const mainHeadTrimmed = mainHead.trim();
|
|
819
|
-
if (mergeBaseTrimmed !== mainHeadTrimmed) {
|
|
820
|
-
throw new Error(
|
|
821
|
-
`Cannot perform fast-forward merge.
|
|
822
|
-
The ${mainBranch} branch has moved forward since this branch was created.
|
|
823
|
-
Merge base: ${mergeBaseTrimmed}
|
|
824
|
-
Main HEAD: ${mainHeadTrimmed}
|
|
825
|
-
|
|
826
|
-
To fix this:
|
|
827
|
-
1. Rebase the branch on ${mainBranch}: git rebase ${mainBranch}
|
|
828
|
-
2. Or use: il finish to automatically rebase and merge
|
|
829
|
-
`
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
/**
|
|
834
|
-
* Perform fast-forward only merge
|
|
835
|
-
* Ports bash/merge-and-clean.sh lines 938-994
|
|
836
|
-
*
|
|
837
|
-
* @param branchName - Name of the branch to merge
|
|
838
|
-
* @param worktreePath - Path to the worktree
|
|
839
|
-
* @param options - Merge options (dryRun, force)
|
|
840
|
-
* @throws Error if checkout, validation, or merge fails
|
|
841
|
-
*/
|
|
842
|
-
async performFastForwardMerge(branchName, worktreePath, options = {}) {
|
|
843
|
-
const { dryRun = false, force = false } = options;
|
|
844
|
-
const mainBranch = await this.getMainBranch();
|
|
845
|
-
logger.info("Starting fast-forward merge...");
|
|
846
|
-
const mainWorktreePath = options.repoRoot ?? await findMainWorktreePathWithSettings(worktreePath, this.settingsManager);
|
|
847
|
-
logger.debug(`Using ${mainBranch} branch location: ${mainWorktreePath}`);
|
|
848
|
-
const currentBranch = await executeGitCommand(["branch", "--show-current"], {
|
|
849
|
-
cwd: mainWorktreePath
|
|
850
|
-
});
|
|
851
|
-
if (currentBranch.trim() !== mainBranch) {
|
|
852
|
-
throw new Error(
|
|
853
|
-
`Expected ${mainBranch} branch but found: ${currentBranch.trim()}
|
|
854
|
-
At location: ${mainWorktreePath}
|
|
855
|
-
This indicates the main worktree detection failed.`
|
|
856
|
-
);
|
|
857
|
-
}
|
|
858
|
-
await this.validateFastForwardPossible(branchName, mainWorktreePath);
|
|
859
|
-
const commitsOutput = await executeGitCommand(["log", "--oneline", `${mainBranch}..${branchName}`], {
|
|
860
|
-
cwd: mainWorktreePath
|
|
861
|
-
});
|
|
862
|
-
const commits = commitsOutput.trim();
|
|
863
|
-
if (!commits) {
|
|
864
|
-
logger.success(`Branch is already merged into ${mainBranch}. No merge needed.`);
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
const commitLines = commits.split("\n");
|
|
868
|
-
logger.info(`Found ${commitLines.length} commit(s) to merge:`);
|
|
869
|
-
commitLines.forEach((commit) => logger.info(` ${commit}`));
|
|
870
|
-
if (!force && !dryRun) {
|
|
871
|
-
logger.info("Proceeding with fast-forward merge... (use --force to skip confirmations)");
|
|
872
|
-
}
|
|
873
|
-
if (dryRun) {
|
|
874
|
-
logger.info(`[DRY RUN] Would execute: git merge --ff-only ${branchName}`);
|
|
875
|
-
logger.info(`[DRY RUN] This would merge ${commitLines.length} commit(s)`);
|
|
876
|
-
return;
|
|
877
|
-
}
|
|
878
|
-
try {
|
|
879
|
-
await executeGitCommand(["merge", "--ff-only", branchName], { cwd: mainWorktreePath });
|
|
880
|
-
logger.success(`Fast-forward merge completed! Merged ${commitLines.length} commit(s).`);
|
|
881
|
-
} catch (error) {
|
|
882
|
-
throw new Error(
|
|
883
|
-
`Fast-forward merge failed: ${error instanceof Error ? error.message : String(error)}
|
|
884
|
-
|
|
885
|
-
To recover:
|
|
886
|
-
1. Check merge status: git status
|
|
887
|
-
2. Abort merge if needed: git merge --abort
|
|
888
|
-
3. Verify branch is rebased: git rebase main
|
|
889
|
-
4. Try merge again: il finish`
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
/**
|
|
894
|
-
* Helper: Detect conflicted files after failed rebase
|
|
895
|
-
* @private
|
|
896
|
-
*/
|
|
897
|
-
async detectConflictedFiles(worktreePath) {
|
|
898
|
-
try {
|
|
899
|
-
const output = await executeGitCommand(["diff", "--name-only", "--diff-filter=U"], {
|
|
900
|
-
cwd: worktreePath
|
|
901
|
-
});
|
|
902
|
-
return output.trim().split("\n").filter((file) => file.length > 0);
|
|
903
|
-
} catch {
|
|
904
|
-
return [];
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
/**
|
|
908
|
-
* Helper: Format conflict error message with manual resolution steps
|
|
909
|
-
* @private
|
|
910
|
-
*/
|
|
911
|
-
formatConflictError(conflictedFiles) {
|
|
912
|
-
const fileList = conflictedFiles.map((file) => ` \u2022 ${file}`).join("\n");
|
|
913
|
-
return "Rebase failed - merge conflicts detected in:\n" + fileList + "\n\nTo resolve manually:\n 1. Fix conflicts in the files above\n 2. Stage resolved files: git add <files>\n 3. Continue rebase: git rebase --continue\n 4. Or abort rebase: git rebase --abort\n 5. Then re-run: il finish <issue-number>";
|
|
914
|
-
}
|
|
915
|
-
/**
|
|
916
|
-
* Attempt to resolve conflicts using Claude
|
|
917
|
-
* Ports bash/merge-and-clean.sh lines 839-894
|
|
918
|
-
*
|
|
919
|
-
* @param worktreePath - Path to the worktree
|
|
920
|
-
* @param conflictedFiles - List of files with conflicts
|
|
921
|
-
* @returns true if conflicts resolved, false otherwise
|
|
922
|
-
* @private
|
|
923
|
-
*/
|
|
924
|
-
async attemptClaudeConflictResolution(worktreePath, conflictedFiles) {
|
|
925
|
-
const isClaudeAvailable = await detectClaudeCli();
|
|
926
|
-
if (!isClaudeAvailable) {
|
|
927
|
-
logger.debug("Claude CLI not available, skipping conflict resolution");
|
|
928
|
-
return false;
|
|
929
|
-
}
|
|
930
|
-
logger.info(`Launching Claude to resolve conflicts in ${conflictedFiles.length} file(s)...`);
|
|
931
|
-
const prompt = `Please help resolve the git rebase conflicts in this repository. Analyze the conflicted files, understand the changes from both branches, fix the conflicts, then run 'git add .' to stage the resolved files, and finally run 'git rebase --continue' to continue the rebase process. Handle the entire workflow for me.`;
|
|
932
|
-
try {
|
|
933
|
-
await launchClaude(prompt, {
|
|
934
|
-
addDir: worktreePath,
|
|
935
|
-
headless: false
|
|
936
|
-
// Interactive - runs in current terminal with stdio: inherit
|
|
937
|
-
});
|
|
938
|
-
const remainingConflicts = await this.detectConflictedFiles(worktreePath);
|
|
939
|
-
if (remainingConflicts.length > 0) {
|
|
940
|
-
logger.warn(
|
|
941
|
-
`Conflicts still exist in ${remainingConflicts.length} file(s) after Claude assistance`
|
|
942
|
-
);
|
|
943
|
-
return false;
|
|
944
|
-
}
|
|
945
|
-
const rebaseInProgress = await this.isRebaseInProgress(worktreePath);
|
|
946
|
-
if (rebaseInProgress) {
|
|
947
|
-
logger.warn("Rebase still in progress after Claude assistance");
|
|
948
|
-
return false;
|
|
949
|
-
}
|
|
950
|
-
logger.success("Claude successfully resolved conflicts and completed rebase");
|
|
951
|
-
return true;
|
|
952
|
-
} catch (error) {
|
|
953
|
-
logger.warn("Claude conflict resolution failed", {
|
|
954
|
-
error: error instanceof Error ? error.message : String(error)
|
|
955
|
-
});
|
|
956
|
-
return false;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
/**
|
|
960
|
-
* Check if a git rebase is currently in progress
|
|
961
|
-
* Checks for .git/rebase-merge or .git/rebase-apply directories
|
|
962
|
-
* Ports bash script logic from lines 853-856
|
|
963
|
-
*
|
|
964
|
-
* @param worktreePath - Path to the worktree
|
|
965
|
-
* @returns true if rebase in progress, false otherwise
|
|
966
|
-
* @private
|
|
967
|
-
*/
|
|
968
|
-
async isRebaseInProgress(worktreePath) {
|
|
969
|
-
const fs = await import("fs/promises");
|
|
970
|
-
const path2 = await import("path");
|
|
971
|
-
const rebaseMergePath = path2.join(worktreePath, ".git", "rebase-merge");
|
|
972
|
-
const rebaseApplyPath = path2.join(worktreePath, ".git", "rebase-apply");
|
|
973
|
-
try {
|
|
974
|
-
await fs.access(rebaseMergePath);
|
|
975
|
-
return true;
|
|
976
|
-
} catch {
|
|
977
|
-
}
|
|
978
|
-
try {
|
|
979
|
-
await fs.access(rebaseApplyPath);
|
|
980
|
-
return true;
|
|
981
|
-
} catch {
|
|
982
|
-
}
|
|
983
|
-
return false;
|
|
984
|
-
}
|
|
985
|
-
};
|
|
986
|
-
|
|
987
706
|
// src/lib/BuildRunner.ts
|
|
988
707
|
var BuildRunner = class {
|
|
989
708
|
constructor(capabilityDetector) {
|
|
@@ -1096,10 +815,7 @@ var FinishCommand = class {
|
|
|
1096
815
|
const settings = await this.settingsManager.loadSettings();
|
|
1097
816
|
const databaseUrlEnvVarName = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
|
|
1098
817
|
const environmentManager = new EnvironmentManager();
|
|
1099
|
-
const neonProvider =
|
|
1100
|
-
projectId: process.env.NEON_PROJECT_ID ?? "",
|
|
1101
|
-
parentBranch: process.env.NEON_PARENT_BRANCH ?? ""
|
|
1102
|
-
});
|
|
818
|
+
const neonProvider = createNeonProviderFromSettings(settings);
|
|
1103
819
|
const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
|
|
1104
820
|
const cliIsolationManager = new CLIIsolationManager();
|
|
1105
821
|
this.resourceCleanup = new ResourceCleanup(
|
|
@@ -1114,8 +830,15 @@ var FinishCommand = class {
|
|
|
1114
830
|
*/
|
|
1115
831
|
async execute(input) {
|
|
1116
832
|
try {
|
|
833
|
+
const settings = await this.settingsManager.loadSettings();
|
|
834
|
+
let repo;
|
|
835
|
+
const multipleRemotes = await hasMultipleRemotes();
|
|
836
|
+
if (multipleRemotes) {
|
|
837
|
+
repo = await getConfiguredRepoFromSettings(settings);
|
|
838
|
+
logger.info(`Using GitHub repository: ${repo}`);
|
|
839
|
+
}
|
|
1117
840
|
const parsed = await this.parseInput(input.identifier, input.options);
|
|
1118
|
-
const worktrees = await this.validateInput(parsed, input.options);
|
|
841
|
+
const worktrees = await this.validateInput(parsed, input.options, repo);
|
|
1119
842
|
logger.info(`Validated input: ${this.formatParsedInput(parsed)}`);
|
|
1120
843
|
const worktree = worktrees[0];
|
|
1121
844
|
if (!worktree) {
|
|
@@ -1125,7 +848,7 @@ var FinishCommand = class {
|
|
|
1125
848
|
if (!parsed.number) {
|
|
1126
849
|
throw new Error("Invalid PR number");
|
|
1127
850
|
}
|
|
1128
|
-
const pr = await this.gitHubService.fetchPR(parsed.number);
|
|
851
|
+
const pr = await this.gitHubService.fetchPR(parsed.number, repo);
|
|
1129
852
|
await this.executePRWorkflow(parsed, input.options, worktree, pr);
|
|
1130
853
|
} else {
|
|
1131
854
|
await this.executeIssueWorkflow(parsed, input.options, worktree);
|
|
@@ -1251,7 +974,7 @@ var FinishCommand = class {
|
|
|
1251
974
|
/**
|
|
1252
975
|
* Validate the parsed input based on its type
|
|
1253
976
|
*/
|
|
1254
|
-
async validateInput(parsed, options) {
|
|
977
|
+
async validateInput(parsed, options, repo) {
|
|
1255
978
|
switch (parsed.type) {
|
|
1256
979
|
case "pr": {
|
|
1257
980
|
if (!parsed.number) {
|
|
@@ -1265,7 +988,7 @@ var FinishCommand = class {
|
|
|
1265
988
|
if (!parsed.number) {
|
|
1266
989
|
throw new Error("Invalid issue number");
|
|
1267
990
|
}
|
|
1268
|
-
const issue = await this.gitHubService.fetchIssue(parsed.number);
|
|
991
|
+
const issue = await this.gitHubService.fetchIssue(parsed.number, repo);
|
|
1269
992
|
if (issue.state === "closed" && !options.force) {
|
|
1270
993
|
throw new Error(
|
|
1271
994
|
`Issue #${parsed.number} is closed. Use --force to finish anyway.`
|
|
@@ -1466,7 +1189,7 @@ var FinishCommand = class {
|
|
|
1466
1189
|
logger.info(`[DRY RUN] Would push changes to origin/${pr.branch}`);
|
|
1467
1190
|
} else {
|
|
1468
1191
|
logger.info("Pushing changes to remote...");
|
|
1469
|
-
const { pushBranchToRemote } = await import("./git-
|
|
1192
|
+
const { pushBranchToRemote } = await import("./git-OUYMVYJX.js");
|
|
1470
1193
|
await pushBranchToRemote(pr.branch, worktree.path, {
|
|
1471
1194
|
dryRun: false
|
|
1472
1195
|
});
|
|
@@ -1629,4 +1352,4 @@ var FinishCommand = class {
|
|
|
1629
1352
|
export {
|
|
1630
1353
|
FinishCommand
|
|
1631
1354
|
};
|
|
1632
|
-
//# sourceMappingURL=finish-
|
|
1355
|
+
//# sourceMappingURL=finish-QJSK6Z7J.js.map
|