xab 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +42 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ var init_config = __esm(() => {
|
|
|
43
43
|
promptHints: [],
|
|
44
44
|
pathRemaps: [],
|
|
45
45
|
reviewStrictness: "normal",
|
|
46
|
-
maxAttempts:
|
|
46
|
+
maxAttempts: undefined,
|
|
47
47
|
commitPrefix: "backmerge:"
|
|
48
48
|
};
|
|
49
49
|
});
|
|
@@ -543,7 +543,9 @@ After making all file changes, you MUST run these two commands as your FINAL act
|
|
|
543
543
|
If you do not run both commands, your work will be discarded. This is not optional.
|
|
544
544
|
The validation system checks for exactly one new git commit. Zero commits = failure.
|
|
545
545
|
|
|
546
|
-
Report what you did
|
|
546
|
+
Report what you did.
|
|
547
|
+
|
|
548
|
+
MAKE SURE TO ACTUALLY GIT COMMIT, NOT JUST MODIFY FILES.`;
|
|
547
549
|
const firstPrompt = `${MERGE_PREAMBLE}
|
|
548
550
|
${opts.repoContext ? `## Repository context
|
|
549
551
|
${opts.repoContext}
|
|
@@ -622,7 +624,9 @@ After making all fixes, you MUST run these two commands as your FINAL action:
|
|
|
622
624
|
|
|
623
625
|
If you do not run both commands, your fixes will be discarded. This is not optional.
|
|
624
626
|
|
|
625
|
-
Report what you fixed
|
|
627
|
+
Report what you fixed.
|
|
628
|
+
|
|
629
|
+
MAKE SURE TO ACTUALLY GIT COMMIT, NOT JUST MODIFY FILES.`;
|
|
626
630
|
const turn = await thread.run(prompt, { outputSchema: applyResultSchema });
|
|
627
631
|
return parseJson(turn.finalResponse, {
|
|
628
632
|
applied: false,
|
|
@@ -783,7 +787,7 @@ If you have ANY objections, be specific about what's wrong and how to fix it. Yo
|
|
|
783
787
|
options: {
|
|
784
788
|
cwd: worktreePath,
|
|
785
789
|
model: "claude-opus-4-6",
|
|
786
|
-
maxTurns:
|
|
790
|
+
maxTurns: undefined,
|
|
787
791
|
permissionMode: "default",
|
|
788
792
|
outputFormat: reviewSchema,
|
|
789
793
|
tools: ["Read", "Glob", "Grep", "Bash"],
|
|
@@ -1173,12 +1177,12 @@ async function validateApply(worktreeGit, beforeHash) {
|
|
|
1173
1177
|
errors.push(`Failed to check commits: ${e.message}`);
|
|
1174
1178
|
}
|
|
1175
1179
|
const status = await worktreeGit.status();
|
|
1176
|
-
const
|
|
1177
|
-
const modified = status.modified.filter((f) => !
|
|
1178
|
-
const created = status.created.filter((f) => !
|
|
1179
|
-
const deleted = status.deleted.filter((f) => !
|
|
1180
|
-
const notAdded = status.not_added.filter((f) => !
|
|
1181
|
-
const conflicted = status.conflicted.filter((f) => !
|
|
1180
|
+
const isInfra = (f) => f.startsWith(".backmerge/") || f.startsWith(".backmerge\\") || f.startsWith(".git-local/") || f.startsWith(".git-local\\");
|
|
1181
|
+
const modified = status.modified.filter((f) => !isInfra(f));
|
|
1182
|
+
const created = status.created.filter((f) => !isInfra(f));
|
|
1183
|
+
const deleted = status.deleted.filter((f) => !isInfra(f));
|
|
1184
|
+
const notAdded = status.not_added.filter((f) => !isInfra(f));
|
|
1185
|
+
const conflicted = status.conflicted.filter((f) => !isInfra(f));
|
|
1182
1186
|
const worktreeClean = modified.length === 0 && created.length === 0 && deleted.length === 0 && conflicted.length === 0 && notAdded.length === 0;
|
|
1183
1187
|
const dirtyFiles = [];
|
|
1184
1188
|
if (!worktreeClean) {
|
|
@@ -1228,7 +1232,7 @@ async function getAppliedDiffStat(worktreeGit, beforeHash) {
|
|
|
1228
1232
|
}
|
|
1229
1233
|
async function resetHard(git, ref) {
|
|
1230
1234
|
await git.raw(["reset", "--hard", ref]);
|
|
1231
|
-
await git.raw(["clean", "-fd", "--exclude=.backmerge"]);
|
|
1235
|
+
await git.raw(["clean", "-fd", "--exclude=.backmerge", "--exclude=.git-local"]);
|
|
1232
1236
|
}
|
|
1233
1237
|
async function fetchOrigin(git) {
|
|
1234
1238
|
await git.fetch(["--all", "--prune"]);
|
|
@@ -1268,7 +1272,7 @@ async function runEngine(opts, cb) {
|
|
|
1268
1272
|
autoSkip = true
|
|
1269
1273
|
} = opts;
|
|
1270
1274
|
const config = loadConfig(repoPath, opts.configPath);
|
|
1271
|
-
const effectiveMaxAttempts = opts.maxAttempts ?? config.maxAttempts ??
|
|
1275
|
+
const effectiveMaxAttempts = opts.maxAttempts ?? config.maxAttempts ?? Infinity;
|
|
1272
1276
|
const effectiveWorkBranch = opts.workBranch ?? config.workBranch;
|
|
1273
1277
|
const commitPrefix = config.commitPrefix ?? "backmerge:";
|
|
1274
1278
|
if (!checkCodexInstalled())
|
|
@@ -1548,7 +1552,7 @@ async function processOneCommit(o) {
|
|
|
1548
1552
|
}
|
|
1549
1553
|
for (let attempt = 1;attempt <= o.maxAttempts; attempt++) {
|
|
1550
1554
|
const headBefore = await getHead(o.wtGit);
|
|
1551
|
-
cb.onStatus(`Applying ${commit.hash.slice(0, 8)} (attempt ${attempt}
|
|
1555
|
+
cb.onStatus(`Applying ${commit.hash.slice(0, 8)} (attempt ${attempt})...`);
|
|
1552
1556
|
let applyResult;
|
|
1553
1557
|
try {
|
|
1554
1558
|
applyResult = await applyCommit({
|
|
@@ -1571,7 +1575,26 @@ async function processOneCommit(o) {
|
|
|
1571
1575
|
continue;
|
|
1572
1576
|
}
|
|
1573
1577
|
cb.onStatus(`Validating ${commit.hash.slice(0, 8)}...`);
|
|
1574
|
-
|
|
1578
|
+
let validation = await validateApply(o.wtGit, headBefore);
|
|
1579
|
+
if (!validation.valid && validation.newCommitCount === 0 && !validation.worktreeClean && validation.dirtyFiles.length > 0) {
|
|
1580
|
+
const realChanges = validation.dirtyFiles.filter((f) => !f.includes(".git-local/"));
|
|
1581
|
+
if (realChanges.length > 0) {
|
|
1582
|
+
cb.onLog(`Codex left ${realChanges.length} changed files without committing \u2014 creating rescue commit`, "yellow");
|
|
1583
|
+
for (const f of realChanges)
|
|
1584
|
+
cb.onLog(` ${f}`, "yellow");
|
|
1585
|
+
const commitMsg = `${o.commitPrefix} ${commit.message} (from ${commit.hash.slice(0, 8)})`;
|
|
1586
|
+
try {
|
|
1587
|
+
await o.wtGit.raw(["add", "-A", "--", ".", ":!.git-local"]);
|
|
1588
|
+
await o.wtGit.raw(["commit", "-m", commitMsg]);
|
|
1589
|
+
validation = await validateApply(o.wtGit, headBefore);
|
|
1590
|
+
if (validation.valid) {
|
|
1591
|
+
cb.onLog(`Rescue commit succeeded`, "green");
|
|
1592
|
+
}
|
|
1593
|
+
} catch (e) {
|
|
1594
|
+
cb.onLog(`Rescue commit failed: ${e.message}`, "red");
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1575
1598
|
if (!validation.valid) {
|
|
1576
1599
|
cb.onLog(`Validation failed: ${validation.errors.join("; ")}`, "red");
|
|
1577
1600
|
if (validation.dirtyFiles.length > 0) {
|
|
@@ -1625,10 +1648,10 @@ async function processOneCommit(o) {
|
|
|
1625
1648
|
}
|
|
1626
1649
|
if (!reviewResult.approved) {
|
|
1627
1650
|
cb.onLog(`Review rejected: ${reviewResult.issues.join("; ")}`, "red");
|
|
1628
|
-
const maxFixRounds =
|
|
1651
|
+
const maxFixRounds = Infinity;
|
|
1629
1652
|
let fixed = false;
|
|
1630
1653
|
for (let fixRound = 1;fixRound <= maxFixRounds; fixRound++) {
|
|
1631
|
-
cb.onStatus(`Codex fixing review issues (round ${fixRound}
|
|
1654
|
+
cb.onStatus(`Codex fixing review issues (round ${fixRound})...`);
|
|
1632
1655
|
try {
|
|
1633
1656
|
await fixFromReview({
|
|
1634
1657
|
worktreePath: o.wtPath,
|
|
@@ -1690,7 +1713,7 @@ async function processOneCommit(o) {
|
|
|
1690
1713
|
kind: "failed",
|
|
1691
1714
|
commitHash: commit.hash,
|
|
1692
1715
|
commitMessage: commit.message,
|
|
1693
|
-
reason: `Review rejected after
|
|
1716
|
+
reason: `Review rejected after fix attempts: ${reviewResult.issues.join("; ")}`,
|
|
1694
1717
|
failedPhase: "review",
|
|
1695
1718
|
reviewApproved: false,
|
|
1696
1719
|
reviewIssues: reviewResult.issues,
|
|
@@ -1704,7 +1727,7 @@ async function processOneCommit(o) {
|
|
|
1704
1727
|
kind: "failed",
|
|
1705
1728
|
commitHash: commit.hash,
|
|
1706
1729
|
commitMessage: commit.message,
|
|
1707
|
-
reason: `Review rejected after
|
|
1730
|
+
reason: `Review rejected after fix attempts: ${reviewResult.issues.join("; ")}`,
|
|
1708
1731
|
failedPhase: "review",
|
|
1709
1732
|
reviewApproved: false,
|
|
1710
1733
|
reviewIssues: reviewResult.issues,
|
|
@@ -2883,7 +2906,7 @@ Behavior:
|
|
|
2883
2906
|
--no-fetch Skip fetch (default)
|
|
2884
2907
|
--no-review Skip Claude review pass
|
|
2885
2908
|
--no-auto-skip Don't auto-skip commits AI identifies as present
|
|
2886
|
-
--max-attempts <n> Max retries per commit (default:
|
|
2909
|
+
--max-attempts <n> Max retries per commit (default: unlimited)
|
|
2887
2910
|
--no-resume Don't resume from interrupted runs (default: auto-resume)
|
|
2888
2911
|
--config <path> Path to config file (default: auto-discover)
|
|
2889
2912
|
--help, -h Show this help
|