@g-abhishek/gitx 0.1.4 โ†’ 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +82 -13
  2. package/dist/ai/claudeAi.d.ts.map +1 -1
  3. package/dist/ai/claudeAi.js +4 -30
  4. package/dist/ai/claudeAi.js.map +1 -1
  5. package/dist/ai/claudeCliAi.d.ts.map +1 -1
  6. package/dist/ai/claudeCliAi.js +4 -21
  7. package/dist/ai/claudeCliAi.js.map +1 -1
  8. package/dist/ai/openAiAi.d.ts.map +1 -1
  9. package/dist/ai/openAiAi.js +4 -30
  10. package/dist/ai/openAiAi.js.map +1 -1
  11. package/dist/ai/reviewHelpers.d.ts +24 -0
  12. package/dist/ai/reviewHelpers.d.ts.map +1 -1
  13. package/dist/ai/reviewHelpers.js +123 -39
  14. package/dist/ai/reviewHelpers.js.map +1 -1
  15. package/dist/cli/commands/pr/cherryPick.d.ts +25 -0
  16. package/dist/cli/commands/pr/cherryPick.d.ts.map +1 -0
  17. package/dist/cli/commands/pr/cherryPick.js +317 -0
  18. package/dist/cli/commands/pr/cherryPick.js.map +1 -0
  19. package/dist/cli/commands/pr/fixComments.d.ts +5 -2
  20. package/dist/cli/commands/pr/fixComments.d.ts.map +1 -1
  21. package/dist/cli/commands/pr/fixComments.js +5 -82
  22. package/dist/cli/commands/pr/fixComments.js.map +1 -1
  23. package/dist/cli/commands/pr/index.d.ts.map +1 -1
  24. package/dist/cli/commands/pr/index.js +6 -2
  25. package/dist/cli/commands/pr/index.js.map +1 -1
  26. package/dist/cli/commands/pr/port.d.ts +34 -0
  27. package/dist/cli/commands/pr/port.d.ts.map +1 -0
  28. package/dist/cli/commands/pr/port.js +453 -0
  29. package/dist/cli/commands/pr/port.js.map +1 -0
  30. package/dist/cli/commands/pr/resolve.d.ts +3 -0
  31. package/dist/cli/commands/pr/resolve.d.ts.map +1 -0
  32. package/dist/cli/commands/pr/resolve.js +92 -0
  33. package/dist/cli/commands/pr/resolve.js.map +1 -0
  34. package/dist/cli/commands/pr/review.js +1 -1
  35. package/dist/cli/commands/pr/review.js.map +1 -1
  36. package/dist/cli/commands/sync.d.ts +12 -11
  37. package/dist/cli/commands/sync.d.ts.map +1 -1
  38. package/dist/cli/commands/sync.js +13 -101
  39. package/dist/cli/commands/sync.js.map +1 -1
  40. package/dist/utils/gitOps.d.ts +11 -4
  41. package/dist/utils/gitOps.d.ts.map +1 -1
  42. package/dist/utils/gitOps.js +53 -37
  43. package/dist/utils/gitOps.js.map +1 -1
  44. package/dist/workflows/pr.d.ts +1 -1
  45. package/dist/workflows/pr.d.ts.map +1 -1
  46. package/dist/workflows/pr.js +82 -19
  47. package/dist/workflows/pr.js.map +1 -1
  48. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport inquirer from \"inquirer\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runFixCommentsWorkflow } from \"../../../workflows/pr.js\";\nimport { pushBranch, getCurrentBranch, isWorkingTreeDirty } from \"../../../utils/gitOps.js\";\n\nexport function registerPrResolveCommand(pr: Command): void {\n pr.command(\"resolve\")\n .description(\"๐Ÿ”ง AI-resolve review comments: applies code fixes, commits, and pushes\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--dry-run\", \"Preview fixes without applying or committing\", false)\n .option(\"--no-commit\", \"Apply fixes to working tree only โ€” skip commit and push\", false)\n .option(\"--no-push\", \"Apply & commit locally but skip push\", false)\n .action(async (id: string, options: { dryRun: boolean; commit: boolean; push: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n // Commander sets options.commit = false when --no-commit is passed\n const noCommit = options.commit === false;\n\n const gitx = await Gitx.fromCwd();\n const ctx = await gitx.getRepoContext();\n logger.info(`๐Ÿ”ง Resolving review comments on PR #${prNumber} (${ctx.repoSlug})โ€ฆ\\n`);\n\n // โ”€โ”€ AI availability check โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โš ๏ธ No AI provider configured โ€” cannot generate fixes.\\n\" +\n \" Run `gitx config` to set up an AI provider (Claude, OpenAI, or claude-cli).\"\n );\n return;\n }\n\n // โ”€โ”€ Confirmation prompt โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!options.dryRun) {\n const modeDesc = noCommit\n ? \"apply fixes to your working tree only (no commit or push)\"\n : options.push === false\n ? \"apply fixes and commit locally (no push)\"\n : \"apply fixes, commit, and push\";\n\n const { proceed } = await inquirer.prompt<{ proceed: boolean }>([\n {\n type: \"confirm\",\n name: \"proceed\",\n message: `This will ${modeDesc}. Continue?`,\n default: false,\n },\n ]);\n if (!proceed) {\n logger.warn(\"Cancelled.\");\n return;\n }\n }\n\n // โ”€โ”€ Guard: warn about uncommitted changes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!options.dryRun) {\n const dirty = await isWorkingTreeDirty(gitx.cwd);\n if (dirty) {\n logger.warn(\"โš ๏ธ You have uncommitted changes. They may conflict with applied fixes.\");\n const { cont } = await inquirer.prompt<{ cont: boolean }>([\n { type: \"confirm\", name: \"cont\", message: \"Continue anyway?\", default: false },\n ]);\n if (!cont) { logger.warn(\"Cancelled.\"); return; }\n }\n }\n\n const result = await runFixCommentsWorkflow(gitx, prNumber, options.dryRun, noCommit);\n\n logger.info(`\\n๐Ÿ“‹ PR: ${result.pr.title}`);\n\n if (result.appliedFixes.length === 0 && result.skippedFixes.length === 0) {\n logger.info(\"No actionable review comments found.\");\n return;\n }\n\n if (result.appliedFixes.length > 0) {\n logger.success(`\\nโœ… Applied ${result.appliedFixes.length} fix(es):`);\n result.appliedFixes.forEach((f) => logger.info(` โ€ข ${f.path} โ€” ${f.rationale}`));\n }\n\n if (result.skippedFixes.length > 0) {\n logger.warn(`\\nโš ๏ธ Skipped ${result.skippedFixes.length} fix(es):`);\n result.skippedFixes.forEach((f) => logger.warn(` โ€ข ${f.path}: ${f.reason}`));\n }\n\n // โ”€โ”€ Push if applicable โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!options.dryRun && !noCommit && options.push !== false && result.appliedFixes.length > 0) {\n const branch = await getCurrentBranch(gitx.cwd);\n logger.info(`\\n๐Ÿš€ Pushing ${branch}โ€ฆ`);\n try {\n await pushBranch(branch, gitx.cwd);\n logger.success(\"Branch pushed.\");\n } catch (err) {\n logger.warn(`Push failed: ${String((err as Error).message ?? err)}`);\n }\n }\n });\n}\n"]}
@@ -123,7 +123,7 @@ export function registerPrReviewCommand(pr) {
123
123
  logger.warn("โš ๏ธ Review could not be posted to the PR (see error above).\n" +
124
124
  " The full review is shown above โ€” you can copy it manually.");
125
125
  }
126
- // To address the review comments, run: gitx pr fix-comments <PR_number>
126
+ // To resolve the review comments, run: gitx pr resolve <PR_number>
127
127
  });
128
128
  }
129
129
  //# sourceMappingURL=review.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/review.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runReviewWorkflow } from \"../../../workflows/pr.js\";\n\nexport function registerPrReviewCommand(pr: Command): void {\n pr.command(\"review\")\n .description(\"๐Ÿง Senior-dev AI review: inline comments, checklist, verdict\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--no-comment\", \"Show review locally only โ€” do not post to PR\")\n .option(\"--no-inline\", \"Post overall review but skip inline file comments\")\n .action(async (id: string, options: { comment: boolean; inline: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n const gitx = await Gitx.fromCwd();\n\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โš ๏ธ No AI provider configured โ€” review will not be meaningful.\\n\" +\n \" Run: gitx config set anthropic (or openai / claude-cli)\"\n );\n return;\n }\n\n const postComment = options.comment !== false;\n\n logger.info(`\\n๐Ÿง Senior-dev AI review โ€” PR #${prNumber}\\n`);\n\n let result: Awaited<ReturnType<typeof runReviewWorkflow>>;\n try {\n result = await runReviewWorkflow(gitx, prNumber, postComment);\n } catch (err) {\n logger.error(`Review failed: ${String((err as Error).message ?? err)}`);\n process.exitCode = 1;\n return;\n }\n\n const { pr: pullReq, review, comments } = result;\n\n // โ”€โ”€ PR header โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`\\n๐Ÿ“‹ ${pullReq.title}`);\n logger.info(` ${pullReq.head} โ†’ ${pullReq.base} ยท by ${pullReq.author} ยท ${pullReq.state}`);\n logger.info(` ${pullReq.url}\\n`);\n\n if (!review) {\n logger.info(`๐Ÿค– Review:\\n${result.aiSummary}`);\n return;\n }\n\n // โ”€โ”€ Verdict โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const verdictIcon =\n review.verdict === \"approve\"\n ? \"โœ… APPROVE\"\n : review.verdict === \"request_changes\"\n ? \"๐Ÿ”ด REQUEST CHANGES\"\n : \"๐Ÿ’ฌ COMMENT\";\n\n logger.info(`๐Ÿค– Verdict: ${verdictIcon}\\n`);\n\n // โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`๐Ÿ“ Summary:\\n ${review.summary.replace(/\\n/g, \"\\n \")}\\n`);\n\n // โ”€โ”€ Checklist โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.checklist.length > 0) {\n logger.info(\"โœ… Review Checklist:\");\n for (const item of review.checklist) {\n const icon = item.status === \"pass\" ? \"โœ…\" : item.status === \"warn\" ? \"โš ๏ธ \" : \"โŒ\";\n logger.info(` ${icon} ${item.area.padEnd(20)} ${item.note}`);\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Issues โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const criticals = review.issues.filter((i) => i.severity === \"critical\");\n const warnings = review.issues.filter((i) => i.severity === \"warning\");\n const suggestions = review.issues.filter((i) => i.severity === \"suggestion\");\n\n if (review.issues.length > 0) {\n logger.info(`๐Ÿ”Ž Issues (${review.issues.length}):`);\n for (const issue of [...criticals, ...warnings, ...suggestions]) {\n const icon = issue.severity === \"critical\" ? \"๐Ÿ”ด\" : issue.severity === \"warning\" ? \"๐ŸŸก\" : \"๐Ÿ’ก\";\n const loc = issue.file ? ` [${issue.file}${issue.line ? `:${issue.line}` : \"\"}]` : \"\";\n logger.info(` ${icon} ${issue.description}${loc}`);\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Inline comments โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.inlineComments.length > 0) {\n logger.info(`๐Ÿ’ฌ Inline Comments (${review.inlineComments.length}):`);\n for (const c of review.inlineComments) {\n const icon = c.severity === \"critical\" ? \"๐Ÿ”ด\" : c.severity === \"warning\" ? \"๐ŸŸก\" : \"๐Ÿ’ก\";\n logger.info(`\\n ${icon} ${c.path}:${c.line}`);\n logger.info(` ${c.body.replace(/\\n/g, \"\\n \")}`);\n if (c.suggestion) {\n logger.info(` ๐Ÿ“Œ Suggestion: ${c.suggestion.split(\"\\n\")[0]}โ€ฆ`);\n }\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Positives โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.positives.length > 0) {\n logger.info(\"๐Ÿ‘ Positives:\");\n for (const p of review.positives) logger.info(` โœ” ${p}`);\n logger.info(\"\");\n }\n\n // โ”€โ”€ Testing notes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.testingNotes) {\n logger.info(`๐Ÿงช How to test:\\n ${review.testingNotes.replace(/\\n/g, \"\\n \")}\\n`);\n }\n\n // โ”€โ”€ Existing PR comments โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (comments.length > 0) {\n logger.info(`๐Ÿ’ฌ Existing comments on PR (${comments.length}):`);\n for (const c of comments.slice(0, 4)) {\n const loc = c.path ? ` @ ${c.path}${c.line ? `:${c.line}` : \"\"}` : \"\";\n logger.info(\n ` [${c.author}${loc}]: ${c.body.slice(0, 120)}${c.body.length > 120 ? \"โ€ฆ\" : \"\"}`\n );\n }\n if (comments.length > 4) logger.info(` โ€ฆ and ${comments.length - 4} more.`);\n logger.info(\"\");\n }\n\n // โ”€โ”€ Status โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!postComment) {\n logger.info(\"โ„น๏ธ Review shown locally only (--no-comment).\");\n } else if (result.reviewPosted) {\n const inlineCount = review.inlineComments.length;\n if (inlineCount > 0) {\n logger.success(\n `โœ… Review posted to PR. ${inlineCount} inline comment(s) โ€” check the PR to see delivery method.`\n );\n logger.info(\n ` (If lines were outside the diff, comments were posted as plain PR comments instead.)`\n );\n } else {\n logger.success(\"โœ… Review posted to PR.\");\n }\n } else {\n logger.warn(\n \"โš ๏ธ Review could not be posted to the PR (see error above).\\n\" +\n \" The full review is shown above โ€” you can copy it manually.\"\n );\n }\n\n // To address the review comments, run: gitx pr fix-comments <PR_number>\n });\n}\n\n"]}
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../../src/cli/commands/pr/review.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { logger } from \"../../../logger/logger.js\";\nimport { Gitx } from \"../../../core/gitx.js\";\nimport { runReviewWorkflow } from \"../../../workflows/pr.js\";\n\nexport function registerPrReviewCommand(pr: Command): void {\n pr.command(\"review\")\n .description(\"๐Ÿง Senior-dev AI review: inline comments, checklist, verdict\")\n .argument(\"<id>\", \"Pull request number\")\n .option(\"--no-comment\", \"Show review locally only โ€” do not post to PR\")\n .option(\"--no-inline\", \"Post overall review but skip inline file comments\")\n .action(async (id: string, options: { comment: boolean; inline: boolean }) => {\n const prNumber = parseInt(id, 10);\n if (isNaN(prNumber) || prNumber <= 0) {\n logger.error(`Invalid PR number: ${id}`);\n process.exit(1);\n }\n\n const gitx = await Gitx.fromCwd();\n\n if (!await Gitx.isAiAvailable(gitx.config)) {\n logger.warn(\n \"โš ๏ธ No AI provider configured โ€” review will not be meaningful.\\n\" +\n \" Run: gitx config set anthropic (or openai / claude-cli)\"\n );\n return;\n }\n\n const postComment = options.comment !== false;\n\n logger.info(`\\n๐Ÿง Senior-dev AI review โ€” PR #${prNumber}\\n`);\n\n let result: Awaited<ReturnType<typeof runReviewWorkflow>>;\n try {\n result = await runReviewWorkflow(gitx, prNumber, postComment);\n } catch (err) {\n logger.error(`Review failed: ${String((err as Error).message ?? err)}`);\n process.exitCode = 1;\n return;\n }\n\n const { pr: pullReq, review, comments } = result;\n\n // โ”€โ”€ PR header โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`\\n๐Ÿ“‹ ${pullReq.title}`);\n logger.info(` ${pullReq.head} โ†’ ${pullReq.base} ยท by ${pullReq.author} ยท ${pullReq.state}`);\n logger.info(` ${pullReq.url}\\n`);\n\n if (!review) {\n logger.info(`๐Ÿค– Review:\\n${result.aiSummary}`);\n return;\n }\n\n // โ”€โ”€ Verdict โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const verdictIcon =\n review.verdict === \"approve\"\n ? \"โœ… APPROVE\"\n : review.verdict === \"request_changes\"\n ? \"๐Ÿ”ด REQUEST CHANGES\"\n : \"๐Ÿ’ฌ COMMENT\";\n\n logger.info(`๐Ÿค– Verdict: ${verdictIcon}\\n`);\n\n // โ”€โ”€ Summary โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`๐Ÿ“ Summary:\\n ${review.summary.replace(/\\n/g, \"\\n \")}\\n`);\n\n // โ”€โ”€ Checklist โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.checklist.length > 0) {\n logger.info(\"โœ… Review Checklist:\");\n for (const item of review.checklist) {\n const icon = item.status === \"pass\" ? \"โœ…\" : item.status === \"warn\" ? \"โš ๏ธ \" : \"โŒ\";\n logger.info(` ${icon} ${item.area.padEnd(20)} ${item.note}`);\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Issues โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const criticals = review.issues.filter((i) => i.severity === \"critical\");\n const warnings = review.issues.filter((i) => i.severity === \"warning\");\n const suggestions = review.issues.filter((i) => i.severity === \"suggestion\");\n\n if (review.issues.length > 0) {\n logger.info(`๐Ÿ”Ž Issues (${review.issues.length}):`);\n for (const issue of [...criticals, ...warnings, ...suggestions]) {\n const icon = issue.severity === \"critical\" ? \"๐Ÿ”ด\" : issue.severity === \"warning\" ? \"๐ŸŸก\" : \"๐Ÿ’ก\";\n const loc = issue.file ? ` [${issue.file}${issue.line ? `:${issue.line}` : \"\"}]` : \"\";\n logger.info(` ${icon} ${issue.description}${loc}`);\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Inline comments โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.inlineComments.length > 0) {\n logger.info(`๐Ÿ’ฌ Inline Comments (${review.inlineComments.length}):`);\n for (const c of review.inlineComments) {\n const icon = c.severity === \"critical\" ? \"๐Ÿ”ด\" : c.severity === \"warning\" ? \"๐ŸŸก\" : \"๐Ÿ’ก\";\n logger.info(`\\n ${icon} ${c.path}:${c.line}`);\n logger.info(` ${c.body.replace(/\\n/g, \"\\n \")}`);\n if (c.suggestion) {\n logger.info(` ๐Ÿ“Œ Suggestion: ${c.suggestion.split(\"\\n\")[0]}โ€ฆ`);\n }\n }\n logger.info(\"\");\n }\n\n // โ”€โ”€ Positives โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.positives.length > 0) {\n logger.info(\"๐Ÿ‘ Positives:\");\n for (const p of review.positives) logger.info(` โœ” ${p}`);\n logger.info(\"\");\n }\n\n // โ”€โ”€ Testing notes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (review.testingNotes) {\n logger.info(`๐Ÿงช How to test:\\n ${review.testingNotes.replace(/\\n/g, \"\\n \")}\\n`);\n }\n\n // โ”€โ”€ Existing PR comments โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (comments.length > 0) {\n logger.info(`๐Ÿ’ฌ Existing comments on PR (${comments.length}):`);\n for (const c of comments.slice(0, 4)) {\n const loc = c.path ? ` @ ${c.path}${c.line ? `:${c.line}` : \"\"}` : \"\";\n logger.info(\n ` [${c.author}${loc}]: ${c.body.slice(0, 120)}${c.body.length > 120 ? \"โ€ฆ\" : \"\"}`\n );\n }\n if (comments.length > 4) logger.info(` โ€ฆ and ${comments.length - 4} more.`);\n logger.info(\"\");\n }\n\n // โ”€โ”€ Status โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (!postComment) {\n logger.info(\"โ„น๏ธ Review shown locally only (--no-comment).\");\n } else if (result.reviewPosted) {\n const inlineCount = review.inlineComments.length;\n if (inlineCount > 0) {\n logger.success(\n `โœ… Review posted to PR. ${inlineCount} inline comment(s) โ€” check the PR to see delivery method.`\n );\n logger.info(\n ` (If lines were outside the diff, comments were posted as plain PR comments instead.)`\n );\n } else {\n logger.success(\"โœ… Review posted to PR.\");\n }\n } else {\n logger.warn(\n \"โš ๏ธ Review could not be posted to the PR (see error above).\\n\" +\n \" The full review is shown above โ€” you can copy it manually.\"\n );\n }\n\n // To resolve the review comments, run: gitx pr resolve <PR_number>\n });\n}\n\n"]}
@@ -2,22 +2,23 @@
2
2
  * gitx sync
3
3
  *
4
4
  * Bring the current branch up to date with its base branch so a PR can be
5
- * merged cleanly. Uses rebase by default (keeps a linear history).
5
+ * merged cleanly.
6
6
  *
7
7
  * Flow:
8
- * 1. Detect base branch (same logic as `gitx pr create`)
8
+ * 1. Auto-detect base branch (same logic as `gitx pr create`)
9
9
  * 2. git fetch origin
10
- * 3. git rebase origin/<base> (or --merge: git merge origin/<base>)
11
- * 4a. No conflicts โ†’ git push --force-with-lease โ†’ "ready to merge"
12
- * 4b. Conflicts โ†’ list conflicting files, instruct user how to resolve,
13
- * then run `gitx sync --continue` to finish
10
+ * 3. git merge origin/<base> (default) or git rebase origin/<base>
11
+ * 4a. No conflicts โ†’ push โ†’ "ready to merge"
12
+ * 4b. Conflicts โ†’ AI attempts resolution; unresolvable ones pause for manual fix
14
13
  *
15
14
  * Usage:
16
- * gitx sync # rebase onto auto-detected base
17
- * gitx sync --base main # rebase onto a specific base
18
- * gitx sync --strategy merge # merge base into branch instead of rebase
19
- * gitx sync --continue # after manually resolving conflicts
20
- * gitx sync --abort # abort an in-progress rebase/merge
15
+ * gitx sync # auto-detect base, merge (default)
16
+ * gitx sync --base main # target a specific base branch
17
+ * gitx sync --strategy rebase # rebase instead of merge
18
+ * gitx sync --continue # after manually resolving conflicts
19
+ * gitx sync --abort # abort an in-progress rebase/merge
20
+ *
21
+ * To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.
21
22
  */
22
23
  import type { Command } from "commander";
23
24
  export declare function registerSyncCommand(program: Command): void;
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqEzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0S1D"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmEzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoS1D"}
@@ -2,36 +2,35 @@
2
2
  * gitx sync
3
3
  *
4
4
  * Bring the current branch up to date with its base branch so a PR can be
5
- * merged cleanly. Uses rebase by default (keeps a linear history).
5
+ * merged cleanly.
6
6
  *
7
7
  * Flow:
8
- * 1. Detect base branch (same logic as `gitx pr create`)
8
+ * 1. Auto-detect base branch (same logic as `gitx pr create`)
9
9
  * 2. git fetch origin
10
- * 3. git rebase origin/<base> (or --merge: git merge origin/<base>)
11
- * 4a. No conflicts โ†’ git push --force-with-lease โ†’ "ready to merge"
12
- * 4b. Conflicts โ†’ list conflicting files, instruct user how to resolve,
13
- * then run `gitx sync --continue` to finish
10
+ * 3. git merge origin/<base> (default) or git rebase origin/<base>
11
+ * 4a. No conflicts โ†’ push โ†’ "ready to merge"
12
+ * 4b. Conflicts โ†’ AI attempts resolution; unresolvable ones pause for manual fix
14
13
  *
15
14
  * Usage:
16
- * gitx sync # rebase onto auto-detected base
17
- * gitx sync --base main # rebase onto a specific base
18
- * gitx sync --strategy merge # merge base into branch instead of rebase
19
- * gitx sync --continue # after manually resolving conflicts
20
- * gitx sync --abort # abort an in-progress rebase/merge
15
+ * gitx sync # auto-detect base, merge (default)
16
+ * gitx sync --base main # target a specific base branch
17
+ * gitx sync --strategy rebase # rebase instead of merge
18
+ * gitx sync --continue # after manually resolving conflicts
19
+ * gitx sync --abort # abort an in-progress rebase/merge
20
+ *
21
+ * To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.
21
22
  */
22
23
  import ora from "ora";
23
24
  import { execFile } from "node:child_process";
24
25
  import { promisify } from "node:util";
25
26
  import { readFile, writeFile } from "node:fs/promises";
26
27
  import { resolve as resolvePath } from "node:path";
27
- import { confirm, select } from "@inquirer/prompts";
28
+ import { confirm } from "@inquirer/prompts";
28
29
  import { logger } from "../../logger/logger.js";
29
30
  import { getCurrentBranch, detectBaseBranch } from "../../utils/gitOps.js";
30
31
  import { isInsideGitRepo } from "../../utils/git.js";
31
32
  import { GitxError } from "../../utils/errors.js";
32
33
  import { Gitx } from "../../core/gitx.js";
33
- import { createProvider } from "../../providers/factory.js";
34
- import { runAddressWorkflow, filterUnresolvedInlineComments } from "../../workflows/prAddress.js";
35
34
  const execFileAsync = promisify(execFile);
36
35
  async function git(args, cwd) {
37
36
  try {
@@ -151,11 +150,6 @@ export function registerSyncCommand(program) {
151
150
  logger.info(`โœจ Already on the base branch "${base}" โ€” nothing to sync.`);
152
151
  return;
153
152
  }
154
- // โ”€โ”€ Check for unresolved PR review comments BEFORE syncing โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
155
- // If the current branch has an open PR with unresolved inline comments,
156
- // offer to resolve them now. Fixes are committed onto the branch; the
157
- // sync then rebases/merges and pushes everything together.
158
- await checkAndOfferAddressComments(cwd, head);
159
153
  logger.info(`\n๐Ÿ”„ Syncing ${head} onto origin/${base}\n`);
160
154
  // Fetch latest
161
155
  const fetchSpinner = ora("Fetching latest from originโ€ฆ").start();
@@ -310,88 +304,6 @@ export function registerSyncCommand(program) {
310
304
  await pushAfterSync(cwd, strategy === "rebase");
311
305
  });
312
306
  }
313
- /**
314
- * Before syncing, look up any open PR for the current branch.
315
- * If it has unresolved inline review comments, ask the user:
316
- * - "Resolve comments first, then sync" โ†’ address + commit, sync continues
317
- * - "Sync normally" โ†’ proceed immediately
318
- *
319
- * Fixes are committed using "commit-no-push" mode so the sync rebase/merge
320
- * picks them up and pushes everything together in a single push.
321
- */
322
- async function checkAndOfferAddressComments(cwd, currentBranch) {
323
- let gitx = null;
324
- try {
325
- gitx = await Gitx.fromCwd(cwd);
326
- if (!await Gitx.isAiAvailable(gitx.config))
327
- return;
328
- }
329
- catch {
330
- return; // no gitx config โ€” skip silently
331
- }
332
- let prNumber = null;
333
- let unresolvedCount = 0;
334
- try {
335
- const ctx = await gitx.getRepoContext();
336
- const provider = createProvider(ctx);
337
- // Find the open PR for the current branch
338
- const prs = await provider.listPRs(ctx.repoSlug);
339
- const openPr = prs.find((p) => p.head === currentBranch && p.state === "open");
340
- if (!openPr)
341
- return;
342
- prNumber = openPr.number;
343
- // Use the shared helper: root inline comments with no "โœ… Addressed" reply yet
344
- const allComments = await provider.getPRComments(ctx.repoSlug, prNumber);
345
- unresolvedCount = filterUnresolvedInlineComments(allComments).length;
346
- if (unresolvedCount === 0)
347
- return;
348
- }
349
- catch {
350
- return; // provider error โ€” don't block the sync
351
- }
352
- // โ”€โ”€ Surface the choice โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
353
- logger.info(`\n๐Ÿ’ฌ PR #${prNumber} has ${unresolvedCount} unresolved review comment(s).\n`);
354
- let choice;
355
- try {
356
- choice = await select({
357
- message: "How would you like to proceed?",
358
- choices: [
359
- {
360
- name: `Resolve comments first, then sync (AI generates fixes โ†’ you approve โ†’ commit โ†’ sync)`,
361
- value: "resolve",
362
- },
363
- {
364
- name: `Sync normally (skip comment resolution, proceed with merge)`,
365
- value: "skip",
366
- },
367
- ],
368
- });
369
- }
370
- catch {
371
- return; // Ctrl-C โ†’ skip
372
- }
373
- if (choice === "skip") {
374
- logger.info("โญ๏ธ Skipping comment resolution โ€” proceeding with sync.\n");
375
- return;
376
- }
377
- // โ”€โ”€ Resolve comments (commit but don't push โ€” sync handles the push) โ”€โ”€โ”€โ”€โ”€โ”€โ”€
378
- logger.info(`\n๐Ÿ”ง Resolving ${unresolvedCount} review comment(s) on PR #${prNumber}โ€ฆ\n`);
379
- try {
380
- const result = await runAddressWorkflow(gitx, prNumber, { mode: "commit-no-push" });
381
- const applied = result.addressed.filter((a) => a.applied).length;
382
- const skipped = result.addressed.filter((a) => a.skipped).length;
383
- if (applied > 0) {
384
- logger.success(`โœ… ${applied} fix(es) committed.${skipped > 0 ? ` (${skipped} skipped)` : ""}`);
385
- logger.info(" Sync will rebase these commits and push everything together.\n");
386
- }
387
- else {
388
- logger.info(" No fixes applied โ€” continuing with normal sync.\n");
389
- }
390
- }
391
- catch (err) {
392
- logger.warn(`โš ๏ธ Comment resolution error: ${err.message}\n Continuing with sync.\n`);
393
- }
394
- }
395
307
  async function pushAfterSync(cwd, forceWithLease = false) {
396
308
  // Rebase rewrites history โ†’ requires --force-with-lease.
397
309
  // Merge does not rewrite history โ†’ plain push is fine.
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx sync\n *\n * Bring the current branch up to date with its base branch so a PR can be\n * merged cleanly. Uses rebase by default (keeps a linear history).\n *\n * Flow:\n * 1. Detect base branch (same logic as `gitx pr create`)\n * 2. git fetch origin\n * 3. git rebase origin/<base> (or --merge: git merge origin/<base>)\n * 4a. No conflicts โ†’ git push --force-with-lease โ†’ \"ready to merge\"\n * 4b. Conflicts โ†’ list conflicting files, instruct user how to resolve,\n * then run `gitx sync --continue` to finish\n *\n * Usage:\n * gitx sync # rebase onto auto-detected base\n * gitx sync --base main # rebase onto a specific base\n * gitx sync --strategy merge # merge base into branch instead of rebase\n * gitx sync --continue # after manually resolving conflicts\n * gitx sync --abort # abort an in-progress rebase/merge\n */\n\nimport type { Command } from \"commander\";\nimport ora from \"ora\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { confirm, select } from \"@inquirer/prompts\";\nimport { logger } from \"../../logger/logger.js\";\nimport { getCurrentBranch, detectBaseBranch } from \"../../utils/gitOps.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { GitxError } from \"../../utils/errors.js\";\nimport { Gitx } from \"../../core/gitx.js\";\nimport { createProvider } from \"../../providers/factory.js\";\nimport { runAddressWorkflow, filterUnresolvedInlineComments } from \"../../workflows/prAddress.js\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(\n args: string[],\n cwd: string\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const result = await execFileAsync(\"git\", args, { cwd });\n return { stdout: result.stdout.trim(), stderr: \"\" };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; message?: string };\n return {\n stdout: e.stdout?.trim() ?? \"\",\n stderr: (e.stderr ?? e.message ?? String(err)).trim(),\n };\n }\n}\n\n/** Returns list of files that currently have conflict markers. */\nasync function getConflictingFiles(cwd: string): Promise<string[]> {\n const { stdout } = await git(\n [\"diff\", \"--name-only\", \"--diff-filter=U\"],\n cwd\n );\n return stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n}\n\n/** Check whether a rebase or merge is currently in progress. */\nasync function getInProgressOperation(\n cwd: string\n): Promise<\"rebase\" | \"merge\" | null> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const base = gitDir || \".git\";\n\n const { stdout: rebaseDir } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-merge\"],\n cwd\n );\n const { stdout: rebaseApply } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-apply\"],\n cwd\n );\n const { stdout: mergeHead } = await git(\n [\"rev-parse\", \"--git-path\", \"MERGE_HEAD\"],\n cwd\n );\n\n // Check if the paths actually exist on disk\n const { existsSync } = await import(\"node:fs\");\n if (existsSync(rebaseDir) || existsSync(rebaseApply)) return \"rebase\";\n if (existsSync(mergeHead) || existsSync(`${base}/MERGE_HEAD`)) return \"merge\";\n return null;\n}\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command(\"sync\")\n .description(\"๐Ÿ”„ Sync current branch with its base branch (merge by default, or --strategy rebase)\")\n .option(\"--base <branch>\", \"Base branch to sync with (auto-detected if omitted)\")\n .option(\n \"--strategy <strategy>\",\n \"Sync strategy: merge (default) | rebase\",\n \"merge\"\n )\n .option(\"--continue\", \"Continue after manually resolving conflicts\")\n .option(\"--abort\", \"Abort an in-progress rebase or merge\")\n .action(async (opts: {\n base?: string;\n strategy: string;\n continue?: boolean;\n abort?: boolean;\n }) => {\n const cwd = process.cwd();\n\n if (!(await isInsideGitRepo(cwd))) {\n throw new GitxError(\"Not inside a git repository. cd into your project folder first.\", { exitCode: 2 });\n }\n\n const strategy = opts.strategy === \"rebase\" ? \"rebase\" : \"merge\";\n\n // โ”€โ”€ Handle --abort โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (opts.abort) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress.\");\n return;\n }\n const abortSpinner = ora(`Aborting ${op}โ€ฆ`).start();\n const { stderr } = await git([op, \"--abort\"], cwd);\n if (stderr) {\n abortSpinner.fail(`Abort failed: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n abortSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} aborted. Branch restored to its previous state.`);\n return;\n }\n\n // โ”€โ”€ Handle --continue โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (opts.continue) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress โ€” nothing to continue.\");\n return;\n }\n\n // Check if all conflicts are resolved\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n logger.error(`\\nโŒ There are still unresolved conflicts:\\n`);\n for (const f of conflicts) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Fix the conflicts above, then:\\n`);\n logger.info(` git add <file> # mark each file as resolved`);\n logger.info(` gitx sync --continue # resume\\n`);\n process.exitCode = 1;\n return;\n }\n\n // Stage all resolved files and continue\n await git([\"add\", \"-A\"], cwd);\n const continueSpinner = ora(`Continuing ${op}โ€ฆ`).start();\n\n const env = { ...process.env, GIT_EDITOR: \"true\" }; // skip editor for commit msg\n const { stderr } = await execFileAsync(\n \"git\",\n [op, \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (stderr && !stderr.includes(\"Successfully\")) {\n continueSpinner.fail(`Could not continue ${op}: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n continueSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} completed โœ“`);\n\n // Rebase rewrites history; merge does not\n await pushAfterSync(cwd, op === \"rebase\");\n return;\n }\n\n // โ”€โ”€ Normal sync flow โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const head = await getCurrentBranch(cwd);\n\n // Resolve base\n let base: string;\n if (opts.base) {\n base = opts.base;\n logger.info(`๐Ÿ“Œ Base branch (provided): ${base}`);\n } else {\n const detectSpinner = ora(\"Detecting base branchโ€ฆ\").start();\n base = await detectBaseBranch(cwd);\n detectSpinner.succeed(`Base branch: ${base}`);\n }\n\n if (head === base) {\n logger.info(`โœจ Already on the base branch \"${base}\" โ€” nothing to sync.`);\n return;\n }\n\n // โ”€โ”€ Check for unresolved PR review comments BEFORE syncing โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n // If the current branch has an open PR with unresolved inline comments,\n // offer to resolve them now. Fixes are committed onto the branch; the\n // sync then rebases/merges and pushes everything together.\n await checkAndOfferAddressComments(cwd, head);\n\n logger.info(`\\n๐Ÿ”„ Syncing ${head} onto origin/${base}\\n`);\n\n // Fetch latest\n const fetchSpinner = ora(\"Fetching latest from originโ€ฆ\").start();\n const { stderr: fetchErr } = await git([\"fetch\", \"origin\"], cwd);\n if (fetchErr && !fetchErr.includes(\"->\")) {\n fetchSpinner.fail(`Fetch failed: ${fetchErr}`);\n process.exitCode = 1;\n return;\n }\n fetchSpinner.succeed(\"Fetched latest.\");\n\n // Check if we're already up to date\n const { stdout: behindCount } = await git(\n [\"rev-list\", \"--count\", `HEAD..origin/${base}`],\n cwd\n );\n if (behindCount === \"0\") {\n logger.success(`โœ… \"${head}\" is already up to date with origin/${base}. Ready to merge!`);\n return;\n }\n\n // Run rebase or merge\n const syncSpinner = ora(\n strategy === \"rebase\"\n ? `Rebasing ${head} onto origin/${base}โ€ฆ`\n : `Merging origin/${base} into ${head}โ€ฆ`\n ).start();\n\n const syncArgs =\n strategy === \"rebase\"\n ? [\"rebase\", `origin/${base}`]\n : [\"merge\", `origin/${base}`, \"--no-edit\"];\n\n const { stderr: syncErr } = await git(syncArgs, cwd);\n\n // Detect conflict โ€” try AI resolution first\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n syncSpinner.fail(`Conflicts detected in ${conflicts.length} file(s) โ€” attempting AI resolutionโ€ฆ`);\n\n // Try to load an AI client\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n } catch {\n // No AI available; fall through to manual instructions\n }\n\n if (gitx && await Gitx.isAiAvailable(gitx.config)) {\n const resolved: string[] = [];\n const needsManual: string[] = [];\n\n for (const filePath of conflicts) {\n const absPath = resolvePath(cwd, filePath);\n let content: string;\n try {\n content = await readFile(absPath, \"utf8\");\n } catch {\n needsManual.push(filePath);\n continue;\n }\n\n // Skip binary files (no conflict markers)\n if (!content.includes(\"<<<<<<<\")) {\n needsManual.push(filePath);\n continue;\n }\n\n const resolveSpinner = ora(` ๐Ÿค– AI resolving: ${filePath}`).start();\n try {\n const result = await gitx.ai.resolveConflict(filePath, content);\n\n if (result.confidence === \"high\") {\n await writeFile(absPath, result.resolved, \"utf8\");\n resolveSpinner.succeed(` โœ… Auto-resolved: ${filePath} โ€” ${result.explanation}`);\n resolved.push(filePath);\n } else {\n resolveSpinner.warn(` โš ๏ธ Low confidence: ${filePath} โ€” ${result.explanation}`);\n logger.info(`\\n AI proposed resolution (low confidence). Preview:\\n`);\n // Show first 40 lines of the resolved content as a preview\n const preview = result.resolved.split(\"\\n\").slice(0, 40).join(\"\\n\");\n logger.info(preview);\n if (result.resolved.split(\"\\n\").length > 40) {\n logger.info(` โ€ฆ (${result.resolved.split(\"\\n\").length - 40} more lines)`);\n }\n logger.info(\"\");\n\n let apply = false;\n try {\n apply = await confirm({\n message: `Apply AI resolution for ${filePath}?`,\n default: true,\n });\n } catch {\n apply = false;\n }\n\n if (apply) {\n await writeFile(absPath, result.resolved, \"utf8\");\n logger.success(` โœ… Applied: ${filePath}`);\n resolved.push(filePath);\n } else {\n logger.info(` โญ๏ธ Skipped: ${filePath} โ€” resolve manually`);\n needsManual.push(filePath);\n }\n }\n } catch {\n resolveSpinner.fail(` โŒ AI resolution failed for: ${filePath}`);\n needsManual.push(filePath);\n }\n }\n\n if (needsManual.length > 0) {\n logger.error(`\\nโš ๏ธ ${needsManual.length} file(s) still need manual resolution:\\n`);\n for (const f of needsManual) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Steps to finish:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n\n // All resolved โ€” stage and continue\n if (resolved.length > 0) {\n logger.success(`\\nโœ… AI resolved all ${resolved.length} conflict(s). Staging and continuingโ€ฆ\\n`);\n await git([\"add\", \"-A\"], cwd);\n\n const env = { ...process.env, GIT_EDITOR: \"true\" };\n const { stderr: contErr } = await execFileAsync(\n \"git\",\n [strategy === \"rebase\" ? \"rebase\" : \"merge\", \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (contErr && !contErr.toLowerCase().includes(\"successfully\")) {\n logger.error(`Could not continue ${strategy}: ${contErr}`);\n process.exitCode = 1;\n return;\n }\n }\n } else {\n // No AI โ€” fall back to manual instructions\n logger.error(`\\nโš ๏ธ Merge conflicts in ${conflicts.length} file(s):\\n`);\n for (const f of conflicts) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Steps to resolve:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n }\n\n if (syncErr && !syncErr.toLowerCase().includes(\"successfully\")) {\n syncSpinner.fail(`Sync failed: ${syncErr}`);\n process.exitCode = 1;\n return;\n }\n\n syncSpinner.succeed(\n strategy === \"rebase\"\n ? `Rebased ${head} onto origin/${base} โœ“`\n : `Merged origin/${base} into ${head} โœ“`\n );\n\n // Rebase rewrites history โ†’ force-with-lease; merge โ†’ plain push\n await pushAfterSync(cwd, strategy === \"rebase\");\n });\n}\n\n/**\n * Before syncing, look up any open PR for the current branch.\n * If it has unresolved inline review comments, ask the user:\n * - \"Resolve comments first, then sync\" โ†’ address + commit, sync continues\n * - \"Sync normally\" โ†’ proceed immediately\n *\n * Fixes are committed using \"commit-no-push\" mode so the sync rebase/merge\n * picks them up and pushes everything together in a single push.\n */\nasync function checkAndOfferAddressComments(cwd: string, currentBranch: string): Promise<void> {\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n if (!await Gitx.isAiAvailable(gitx.config)) return;\n } catch {\n return; // no gitx config โ€” skip silently\n }\n\n let prNumber: number | null = null;\n let unresolvedCount = 0;\n\n try {\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n\n // Find the open PR for the current branch\n const prs = await provider.listPRs(ctx.repoSlug);\n const openPr = prs.find((p) => p.head === currentBranch && p.state === \"open\");\n if (!openPr) return;\n\n prNumber = openPr.number;\n\n // Use the shared helper: root inline comments with no \"โœ… Addressed\" reply yet\n const allComments = await provider.getPRComments(ctx.repoSlug, prNumber);\n unresolvedCount = filterUnresolvedInlineComments(allComments).length;\n\n if (unresolvedCount === 0) return;\n } catch {\n return; // provider error โ€” don't block the sync\n }\n\n // โ”€โ”€ Surface the choice โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`\\n๐Ÿ’ฌ PR #${prNumber} has ${unresolvedCount} unresolved review comment(s).\\n`);\n\n let choice: string;\n try {\n choice = await select({\n message: \"How would you like to proceed?\",\n choices: [\n {\n name: `Resolve comments first, then sync (AI generates fixes โ†’ you approve โ†’ commit โ†’ sync)`,\n value: \"resolve\",\n },\n {\n name: `Sync normally (skip comment resolution, proceed with merge)`,\n value: \"skip\",\n },\n ],\n });\n } catch {\n return; // Ctrl-C โ†’ skip\n }\n\n if (choice === \"skip\") {\n logger.info(\"โญ๏ธ Skipping comment resolution โ€” proceeding with sync.\\n\");\n return;\n }\n\n // โ”€โ”€ Resolve comments (commit but don't push โ€” sync handles the push) โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n logger.info(`\\n๐Ÿ”ง Resolving ${unresolvedCount} review comment(s) on PR #${prNumber}โ€ฆ\\n`);\n try {\n const result = await runAddressWorkflow(gitx!, prNumber, { mode: \"commit-no-push\" });\n const applied = result.addressed.filter((a) => a.applied).length;\n const skipped = result.addressed.filter((a) => a.skipped).length;\n\n if (applied > 0) {\n logger.success(`โœ… ${applied} fix(es) committed.${skipped > 0 ? ` (${skipped} skipped)` : \"\"}`);\n logger.info(\" Sync will rebase these commits and push everything together.\\n\");\n } else {\n logger.info(\" No fixes applied โ€” continuing with normal sync.\\n\");\n }\n } catch (err) {\n logger.warn(`โš ๏ธ Comment resolution error: ${(err as Error).message}\\n Continuing with sync.\\n`);\n }\n}\n\nasync function pushAfterSync(cwd: string, forceWithLease = false): Promise<void> {\n // Rebase rewrites history โ†’ requires --force-with-lease.\n // Merge does not rewrite history โ†’ plain push is fine.\n const pushArgs = forceWithLease\n ? [\"push\", \"--force-with-lease\"]\n : [\"push\"];\n\n const label = forceWithLease ? \"Pushing (force-with-lease)โ€ฆ\" : \"Pushingโ€ฆ\";\n const pushSpinner = ora(label).start();\n const { stderr } = await git(pushArgs, cwd);\n if (stderr && stderr.includes(\"error\")) {\n pushSpinner.fail(`Push failed: ${stderr}`);\n const hint = forceWithLease ? \"git push --force-with-lease\" : \"git push\";\n logger.info(` Try: ${hint}`);\n process.exitCode = 1;\n return;\n }\n pushSpinner.succeed(\"Pushed โœ“\");\n logger.success(`\\nโœ… Branch is now up to date. Run \\`gitx pr merge <number>\\` to merge.\\n`);\n}\n"]}
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gitx sync\n *\n * Bring the current branch up to date with its base branch so a PR can be\n * merged cleanly.\n *\n * Flow:\n * 1. Auto-detect base branch (same logic as `gitx pr create`)\n * 2. git fetch origin\n * 3. git merge origin/<base> (default) or git rebase origin/<base>\n * 4a. No conflicts โ†’ push โ†’ \"ready to merge\"\n * 4b. Conflicts โ†’ AI attempts resolution; unresolvable ones pause for manual fix\n *\n * Usage:\n * gitx sync # auto-detect base, merge (default)\n * gitx sync --base main # target a specific base branch\n * gitx sync --strategy rebase # rebase instead of merge\n * gitx sync --continue # after manually resolving conflicts\n * gitx sync --abort # abort an in-progress rebase/merge\n *\n * To resolve PR review comments before syncing, run `gitx pr resolve <number>` first.\n */\n\nimport type { Command } from \"commander\";\nimport ora from \"ora\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve as resolvePath } from \"node:path\";\nimport { confirm } from \"@inquirer/prompts\";\nimport { logger } from \"../../logger/logger.js\";\nimport { getCurrentBranch, detectBaseBranch } from \"../../utils/gitOps.js\";\nimport { isInsideGitRepo } from \"../../utils/git.js\";\nimport { GitxError } from \"../../utils/errors.js\";\nimport { Gitx } from \"../../core/gitx.js\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(\n args: string[],\n cwd: string\n): Promise<{ stdout: string; stderr: string }> {\n try {\n const result = await execFileAsync(\"git\", args, { cwd });\n return { stdout: result.stdout.trim(), stderr: \"\" };\n } catch (err: unknown) {\n const e = err as { stdout?: string; stderr?: string; message?: string };\n return {\n stdout: e.stdout?.trim() ?? \"\",\n stderr: (e.stderr ?? e.message ?? String(err)).trim(),\n };\n }\n}\n\n/** Returns list of files that currently have conflict markers. */\nasync function getConflictingFiles(cwd: string): Promise<string[]> {\n const { stdout } = await git(\n [\"diff\", \"--name-only\", \"--diff-filter=U\"],\n cwd\n );\n return stdout.split(\"\\n\").map((l) => l.trim()).filter(Boolean);\n}\n\n/** Check whether a rebase or merge is currently in progress. */\nasync function getInProgressOperation(\n cwd: string\n): Promise<\"rebase\" | \"merge\" | null> {\n const { stdout: gitDir } = await git([\"rev-parse\", \"--git-dir\"], cwd);\n const base = gitDir || \".git\";\n\n const { stdout: rebaseDir } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-merge\"],\n cwd\n );\n const { stdout: rebaseApply } = await git(\n [\"rev-parse\", \"--git-path\", \"rebase-apply\"],\n cwd\n );\n const { stdout: mergeHead } = await git(\n [\"rev-parse\", \"--git-path\", \"MERGE_HEAD\"],\n cwd\n );\n\n // Check if the paths actually exist on disk\n const { existsSync } = await import(\"node:fs\");\n if (existsSync(rebaseDir) || existsSync(rebaseApply)) return \"rebase\";\n if (existsSync(mergeHead) || existsSync(`${base}/MERGE_HEAD`)) return \"merge\";\n return null;\n}\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command(\"sync\")\n .description(\"๐Ÿ”„ Sync current branch with its base branch (merge by default, or --strategy rebase)\")\n .option(\"--base <branch>\", \"Base branch to sync with (auto-detected if omitted)\")\n .option(\n \"--strategy <strategy>\",\n \"Sync strategy: merge (default) | rebase\",\n \"merge\"\n )\n .option(\"--continue\", \"Continue after manually resolving conflicts\")\n .option(\"--abort\", \"Abort an in-progress rebase or merge\")\n .action(async (opts: {\n base?: string;\n strategy: string;\n continue?: boolean;\n abort?: boolean;\n }) => {\n const cwd = process.cwd();\n\n if (!(await isInsideGitRepo(cwd))) {\n throw new GitxError(\"Not inside a git repository. cd into your project folder first.\", { exitCode: 2 });\n }\n\n const strategy = opts.strategy === \"rebase\" ? \"rebase\" : \"merge\";\n\n // โ”€โ”€ Handle --abort โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (opts.abort) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress.\");\n return;\n }\n const abortSpinner = ora(`Aborting ${op}โ€ฆ`).start();\n const { stderr } = await git([op, \"--abort\"], cwd);\n if (stderr) {\n abortSpinner.fail(`Abort failed: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n abortSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} aborted. Branch restored to its previous state.`);\n return;\n }\n\n // โ”€โ”€ Handle --continue โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n if (opts.continue) {\n const op = await getInProgressOperation(cwd);\n if (!op) {\n logger.info(\"No rebase or merge in progress โ€” nothing to continue.\");\n return;\n }\n\n // Check if all conflicts are resolved\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n logger.error(`\\nโŒ There are still unresolved conflicts:\\n`);\n for (const f of conflicts) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Fix the conflicts above, then:\\n`);\n logger.info(` git add <file> # mark each file as resolved`);\n logger.info(` gitx sync --continue # resume\\n`);\n process.exitCode = 1;\n return;\n }\n\n // Stage all resolved files and continue\n await git([\"add\", \"-A\"], cwd);\n const continueSpinner = ora(`Continuing ${op}โ€ฆ`).start();\n\n const env = { ...process.env, GIT_EDITOR: \"true\" }; // skip editor for commit msg\n const { stderr } = await execFileAsync(\n \"git\",\n [op, \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (stderr && !stderr.includes(\"Successfully\")) {\n continueSpinner.fail(`Could not continue ${op}: ${stderr}`);\n process.exitCode = 1;\n return;\n }\n continueSpinner.succeed(`${op.charAt(0).toUpperCase() + op.slice(1)} completed โœ“`);\n\n // Rebase rewrites history; merge does not\n await pushAfterSync(cwd, op === \"rebase\");\n return;\n }\n\n // โ”€โ”€ Normal sync flow โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n const head = await getCurrentBranch(cwd);\n\n // Resolve base\n let base: string;\n if (opts.base) {\n base = opts.base;\n logger.info(`๐Ÿ“Œ Base branch (provided): ${base}`);\n } else {\n const detectSpinner = ora(\"Detecting base branchโ€ฆ\").start();\n base = await detectBaseBranch(cwd);\n detectSpinner.succeed(`Base branch: ${base}`);\n }\n\n if (head === base) {\n logger.info(`โœจ Already on the base branch \"${base}\" โ€” nothing to sync.`);\n return;\n }\n\n logger.info(`\\n๐Ÿ”„ Syncing ${head} onto origin/${base}\\n`);\n\n // Fetch latest\n const fetchSpinner = ora(\"Fetching latest from originโ€ฆ\").start();\n const { stderr: fetchErr } = await git([\"fetch\", \"origin\"], cwd);\n if (fetchErr && !fetchErr.includes(\"->\")) {\n fetchSpinner.fail(`Fetch failed: ${fetchErr}`);\n process.exitCode = 1;\n return;\n }\n fetchSpinner.succeed(\"Fetched latest.\");\n\n // Check if we're already up to date\n const { stdout: behindCount } = await git(\n [\"rev-list\", \"--count\", `HEAD..origin/${base}`],\n cwd\n );\n if (behindCount === \"0\") {\n logger.success(`โœ… \"${head}\" is already up to date with origin/${base}. Ready to merge!`);\n return;\n }\n\n // Run rebase or merge\n const syncSpinner = ora(\n strategy === \"rebase\"\n ? `Rebasing ${head} onto origin/${base}โ€ฆ`\n : `Merging origin/${base} into ${head}โ€ฆ`\n ).start();\n\n const syncArgs =\n strategy === \"rebase\"\n ? [\"rebase\", `origin/${base}`]\n : [\"merge\", `origin/${base}`, \"--no-edit\"];\n\n const { stderr: syncErr } = await git(syncArgs, cwd);\n\n // Detect conflict โ€” try AI resolution first\n const conflicts = await getConflictingFiles(cwd);\n if (conflicts.length > 0) {\n syncSpinner.fail(`Conflicts detected in ${conflicts.length} file(s) โ€” attempting AI resolutionโ€ฆ`);\n\n // Try to load an AI client\n let gitx: Gitx | null = null;\n try {\n gitx = await Gitx.fromCwd(cwd);\n } catch {\n // No AI available; fall through to manual instructions\n }\n\n if (gitx && await Gitx.isAiAvailable(gitx.config)) {\n const resolved: string[] = [];\n const needsManual: string[] = [];\n\n for (const filePath of conflicts) {\n const absPath = resolvePath(cwd, filePath);\n let content: string;\n try {\n content = await readFile(absPath, \"utf8\");\n } catch {\n needsManual.push(filePath);\n continue;\n }\n\n // Skip binary files (no conflict markers)\n if (!content.includes(\"<<<<<<<\")) {\n needsManual.push(filePath);\n continue;\n }\n\n const resolveSpinner = ora(` ๐Ÿค– AI resolving: ${filePath}`).start();\n try {\n const result = await gitx.ai.resolveConflict(filePath, content);\n\n if (result.confidence === \"high\") {\n await writeFile(absPath, result.resolved, \"utf8\");\n resolveSpinner.succeed(` โœ… Auto-resolved: ${filePath} โ€” ${result.explanation}`);\n resolved.push(filePath);\n } else {\n resolveSpinner.warn(` โš ๏ธ Low confidence: ${filePath} โ€” ${result.explanation}`);\n logger.info(`\\n AI proposed resolution (low confidence). Preview:\\n`);\n // Show first 40 lines of the resolved content as a preview\n const preview = result.resolved.split(\"\\n\").slice(0, 40).join(\"\\n\");\n logger.info(preview);\n if (result.resolved.split(\"\\n\").length > 40) {\n logger.info(` โ€ฆ (${result.resolved.split(\"\\n\").length - 40} more lines)`);\n }\n logger.info(\"\");\n\n let apply = false;\n try {\n apply = await confirm({\n message: `Apply AI resolution for ${filePath}?`,\n default: true,\n });\n } catch {\n apply = false;\n }\n\n if (apply) {\n await writeFile(absPath, result.resolved, \"utf8\");\n logger.success(` โœ… Applied: ${filePath}`);\n resolved.push(filePath);\n } else {\n logger.info(` โญ๏ธ Skipped: ${filePath} โ€” resolve manually`);\n needsManual.push(filePath);\n }\n }\n } catch {\n resolveSpinner.fail(` โŒ AI resolution failed for: ${filePath}`);\n needsManual.push(filePath);\n }\n }\n\n if (needsManual.length > 0) {\n logger.error(`\\nโš ๏ธ ${needsManual.length} file(s) still need manual resolution:\\n`);\n for (const f of needsManual) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Steps to finish:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n\n // All resolved โ€” stage and continue\n if (resolved.length > 0) {\n logger.success(`\\nโœ… AI resolved all ${resolved.length} conflict(s). Staging and continuingโ€ฆ\\n`);\n await git([\"add\", \"-A\"], cwd);\n\n const env = { ...process.env, GIT_EDITOR: \"true\" };\n const { stderr: contErr } = await execFileAsync(\n \"git\",\n [strategy === \"rebase\" ? \"rebase\" : \"merge\", \"--continue\"],\n { cwd, env }\n ).then(\n (r) => ({ stdout: r.stdout, stderr: \"\" }),\n (e: { stderr?: string; message?: string }) => ({\n stdout: \"\",\n stderr: (e.stderr ?? e.message ?? \"\").trim(),\n })\n );\n\n if (contErr && !contErr.toLowerCase().includes(\"successfully\")) {\n logger.error(`Could not continue ${strategy}: ${contErr}`);\n process.exitCode = 1;\n return;\n }\n }\n } else {\n // No AI โ€” fall back to manual instructions\n logger.error(`\\nโš ๏ธ Merge conflicts in ${conflicts.length} file(s):\\n`);\n for (const f of conflicts) logger.info(` โ€ข ${f}`);\n logger.info(`\\n Steps to resolve:\\n`);\n logger.info(` 1. Open each file and fix the conflict markers (<<<<, ====, >>>>)`);\n logger.info(` 2. Mark resolved: git add <file>`);\n logger.info(` 3. Finish sync: gitx sync --continue`);\n logger.info(` 4. Retry merge: gitx pr merge <number>\\n`);\n logger.info(` To give up and go back: gitx sync --abort\\n`);\n process.exitCode = 1;\n return;\n }\n }\n\n if (syncErr && !syncErr.toLowerCase().includes(\"successfully\")) {\n syncSpinner.fail(`Sync failed: ${syncErr}`);\n process.exitCode = 1;\n return;\n }\n\n syncSpinner.succeed(\n strategy === \"rebase\"\n ? `Rebased ${head} onto origin/${base} โœ“`\n : `Merged origin/${base} into ${head} โœ“`\n );\n\n // Rebase rewrites history โ†’ force-with-lease; merge โ†’ plain push\n await pushAfterSync(cwd, strategy === \"rebase\");\n });\n}\n\n\nasync function pushAfterSync(cwd: string, forceWithLease = false): Promise<void> {\n // Rebase rewrites history โ†’ requires --force-with-lease.\n // Merge does not rewrite history โ†’ plain push is fine.\n const pushArgs = forceWithLease\n ? [\"push\", \"--force-with-lease\"]\n : [\"push\"];\n\n const label = forceWithLease ? \"Pushing (force-with-lease)โ€ฆ\" : \"Pushingโ€ฆ\";\n const pushSpinner = ora(label).start();\n const { stderr } = await git(pushArgs, cwd);\n if (stderr && stderr.includes(\"error\")) {\n pushSpinner.fail(`Push failed: ${stderr}`);\n const hint = forceWithLease ? \"git push --force-with-lease\" : \"git push\";\n logger.info(` Try: ${hint}`);\n process.exitCode = 1;\n return;\n }\n pushSpinner.succeed(\"Pushed โœ“\");\n logger.success(`\\nโœ… Branch is now up to date. Run \\`gitx pr merge <number>\\` to merge.\\n`);\n}\n"]}
@@ -62,10 +62,17 @@ export declare function getWorkingDiffStat(cwd?: string): Promise<string>;
62
62
  * Auto-detect the most likely base branch for the current feature branch.
63
63
  *
64
64
  * Strategy:
65
- * 1. Check if the current branch has a configured upstream tracking branch.
66
- * 2. Otherwise, try common default branch names (main, master, develop, dev).
67
- * 3. For each candidate, count commits on HEAD that are NOT in that branch.
68
- * The candidate with the fewest such commits is the likely origin.
65
+ * 1. Upstream tracking branch set via `git push -u` โ€” strongest signal.
66
+ * Ignored if it points to the branch's own remote ref (origin/current).
67
+ * 2. Scan ALL remote tracking branches and count how many commits HEAD has
68
+ * that each candidate doesn't (`git rev-list --count <ref>..HEAD`).
69
+ * The branch with the FEWEST such commits is the closest ancestor โ€”
70
+ * i.e. the branch this one was forked from.
71
+ *
72
+ * Example: main โ†’ feature1 (3 commits) โ†’ feature2 (2 commits)
73
+ * - origin/main..HEAD = 5 (feature1's 3 + feature2's 2)
74
+ * - origin/feature1..HEAD = 2 (just feature2's commits)
75
+ * โ†’ feature1 wins โœ“
69
76
  *
70
77
  * Falls back to "main" if nothing can be determined.
71
78
  */
@@ -1 +1 @@
1
- {"version":3,"file":"gitOps.d.ts","sourceRoot":"","sources":["../../src/utils/gitOps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitOps.d.ts","sourceRoot":"","sources":["../../src/utils/gitOps.ts"],"names":[],"mappings":"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"}
@@ -205,20 +205,24 @@ export async function getWorkingDiffStat(cwd = process.cwd()) {
205
205
  * Auto-detect the most likely base branch for the current feature branch.
206
206
  *
207
207
  * Strategy:
208
- * 1. Check if the current branch has a configured upstream tracking branch.
209
- * 2. Otherwise, try common default branch names (main, master, develop, dev).
210
- * 3. For each candidate, count commits on HEAD that are NOT in that branch.
211
- * The candidate with the fewest such commits is the likely origin.
208
+ * 1. Upstream tracking branch set via `git push -u` โ€” strongest signal.
209
+ * Ignored if it points to the branch's own remote ref (origin/current).
210
+ * 2. Scan ALL remote tracking branches and count how many commits HEAD has
211
+ * that each candidate doesn't (`git rev-list --count <ref>..HEAD`).
212
+ * The branch with the FEWEST such commits is the closest ancestor โ€”
213
+ * i.e. the branch this one was forked from.
214
+ *
215
+ * Example: main โ†’ feature1 (3 commits) โ†’ feature2 (2 commits)
216
+ * - origin/main..HEAD = 5 (feature1's 3 + feature2's 2)
217
+ * - origin/feature1..HEAD = 2 (just feature2's commits)
218
+ * โ†’ feature1 wins โœ“
212
219
  *
213
220
  * Falls back to "main" if nothing can be determined.
214
221
  */
215
222
  export async function detectBaseBranch(cwd = process.cwd()) {
216
- // Get current branch name upfront โ€” used for all checks below
217
223
  const current = await git(["rev-parse", "--abbrev-ref", "HEAD"], cwd).catch(() => "");
218
- // 1. Try upstream tracking branch โ€” only useful if it points to a DIFFERENT
219
- // branch (e.g. origin/main), not the branch's own remote tracking ref.
220
- // e.g. "origin/gitx/test" โ†’ "gitx/test" == current โ†’ skip
221
- // "origin/main" โ†’ "main" != current โ†’ use it
224
+ // 1. Explicit upstream tracking branch โ€” only trust it if it differs from
225
+ // the current branch (guards against "origin/feature2" โ†’ "feature2").
222
226
  try {
223
227
  const upstream = await git(["rev-parse", "--abbrev-ref", "@{upstream}"], cwd);
224
228
  const branch = upstream.replace(/^[^/]+\//, "").trim();
@@ -226,39 +230,51 @@ export async function detectBaseBranch(cwd = process.cwd()) {
226
230
  return branch;
227
231
  }
228
232
  catch {
229
- // No upstream configured โ€” fall through
233
+ // No upstream set โ€” fall through
230
234
  }
231
- // 2. Check remote HEAD (origin's default branch)
235
+ // 2. Scan all remote tracking branches (origin/*), compute how many commits
236
+ // HEAD has that each remote ref doesn't. Closest ancestor wins.
232
237
  try {
233
- const remoteHead = await git(["rev-parse", "--abbrev-ref", "origin/HEAD"], cwd);
234
- const branch = remoteHead.replace(/^origin\//, "").trim();
235
- if (branch && branch !== current)
236
- return branch;
238
+ const remoteOut = await git(["branch", "-r", "--format=%(refname:short)"], cwd);
239
+ const remoteRefs = remoteOut
240
+ .split("\n")
241
+ .map((b) => b.trim())
242
+ .filter((b) => b && !b.endsWith("/HEAD")); // skip "origin/HEAD" pointer
243
+ if (remoteRefs.length === 0)
244
+ return "main";
245
+ // Count commits ahead of every remote ref in parallel for speed
246
+ const results = await Promise.all(remoteRefs.map(async (ref) => {
247
+ const name = ref.replace(/^[^/]+\//, ""); // "origin/feature1" โ†’ "feature1"
248
+ if (name === current)
249
+ return null; // skip own remote tracking ref
250
+ try {
251
+ const out = await git(["rev-list", "--count", `${ref}..HEAD`], cwd);
252
+ return { branch: name, ahead: parseInt(out.trim(), 10) || 0 };
253
+ }
254
+ catch {
255
+ return null;
256
+ }
257
+ }));
258
+ const counts = results.filter((r) => r !== null);
259
+ if (counts.length === 0)
260
+ return "main";
261
+ // Sort by fewest commits ahead โ€” that's the closest ancestor.
262
+ // Tiebreak: prefer default branch names so "main" beats an equally-close
263
+ // unrelated branch that happens to have 0 commits.
264
+ const defaults = new Set(["main", "master", "develop", "dev", "staging"]);
265
+ counts.sort((a, b) => {
266
+ if (a.ahead !== b.ahead)
267
+ return a.ahead - b.ahead;
268
+ // Same distance โ€” prefer default branches
269
+ const aDefault = defaults.has(a.branch) ? 0 : 1;
270
+ const bDefault = defaults.has(b.branch) ? 0 : 1;
271
+ return aDefault - bDefault;
272
+ });
273
+ return counts[0].branch;
237
274
  }
238
275
  catch {
239
- // Not available โ€” fall through
240
- }
241
- // 3. Count commits ahead of each common default branch name
242
- const candidates = ["main", "master", "develop", "dev", "staging"];
243
- const counts = [];
244
- for (const candidate of candidates) {
245
- if (candidate === current)
246
- continue;
247
- try {
248
- // Count commits on HEAD not in candidate
249
- const out = await git(["rev-list", "--count", `${candidate}..HEAD`], cwd);
250
- counts.push({ branch: candidate, ahead: parseInt(out.trim(), 10) || 0 });
251
- }
252
- catch {
253
- // Branch doesn't exist locally โ€” skip
254
- }
255
- }
256
- if (counts.length > 0) {
257
- // Pick the branch with the fewest commits ahead (closest ancestor)
258
- counts.sort((a, b) => a.ahead - b.ahead);
259
- return counts[0].branch;
276
+ return "main";
260
277
  }
261
- return "main";
262
278
  }
263
279
  /**
264
280
  * Get the one-line commit log for commits on HEAD that are not in baseBranch.