xab 3.0.0 → 5.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 +283 -34
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -531,11 +531,18 @@ ${opts.applicationStrategy}
|
|
|
531
531
|
- If the target already has a different version of the same logic, merge both intents
|
|
532
532
|
- Preserve the target's existing improvements \u2014 do not regress
|
|
533
533
|
- Create or modify files as needed; delete files if the source commit deleted them
|
|
534
|
-
- After applying, run exactly: git add -A && git commit -m "${commitMsg.replace(/"/g, "\\\"")}"
|
|
535
|
-
- You MUST create exactly ONE commit. Not zero, not two.
|
|
536
534
|
- No conflict markers, dead code, or TODO placeholders
|
|
537
535
|
- If impossible to apply cleanly, explain why in notes
|
|
538
536
|
|
|
537
|
+
## CRITICAL \u2014 you MUST commit your changes
|
|
538
|
+
After making all file changes, you MUST run these two commands as your FINAL action:
|
|
539
|
+
|
|
540
|
+
git add -A
|
|
541
|
+
git commit -m "${commitMsg.replace(/"/g, "\\\"")}"
|
|
542
|
+
|
|
543
|
+
If you do not run both commands, your work will be discarded. This is not optional.
|
|
544
|
+
The validation system checks for exactly one new git commit. Zero commits = failure.
|
|
545
|
+
|
|
539
546
|
Report what you did.`;
|
|
540
547
|
const firstPrompt = `${MERGE_PREAMBLE}
|
|
541
548
|
${opts.repoContext ? `## Repository context
|
|
@@ -605,9 +612,16 @@ ${opts.reviewIssues.map((issue, i) => `${i + 1}. ${issue}`).join(`
|
|
|
605
612
|
- Read the affected files to understand the current state
|
|
606
613
|
- Fix every issue the reviewer raised
|
|
607
614
|
- Do NOT introduce new problems while fixing
|
|
608
|
-
- After fixing, amend the commit: git add -A && git commit --amend -m "${commitMsg.replace(/"/g, "\\\"")}"
|
|
609
615
|
- The result must be a single clean commit with no issues
|
|
610
616
|
|
|
617
|
+
## CRITICAL \u2014 you MUST amend the commit after fixing
|
|
618
|
+
After making all fixes, you MUST run these two commands as your FINAL action:
|
|
619
|
+
|
|
620
|
+
git add -A
|
|
621
|
+
git commit --amend -m "${commitMsg.replace(/"/g, "\\\"")}"
|
|
622
|
+
|
|
623
|
+
If you do not run both commands, your fixes will be discarded. This is not optional.
|
|
624
|
+
|
|
611
625
|
Report what you fixed.`;
|
|
612
626
|
const turn = await thread.run(prompt, { outputSchema: applyResultSchema });
|
|
613
627
|
return parseJson(turn.finalResponse, {
|
|
@@ -784,7 +798,15 @@ You can:
|
|
|
784
798
|
|
|
785
799
|
You MUST NOT modify the worktree in any way. No file writes, no git commits, no destructive commands.
|
|
786
800
|
|
|
787
|
-
|
|
801
|
+
Testing guidelines:
|
|
802
|
+
- Only run tests that work without API keys, secrets, or external service connections
|
|
803
|
+
- Before running a test, check if it needs env vars by reading the test file or relevant .env.example
|
|
804
|
+
- If a test needs keys, only run it if you can see a .env file with those vars already populated
|
|
805
|
+
- Prefer: type-checks (tsc --noEmit), linters (eslint), unit tests, build checks (forge build, go build)
|
|
806
|
+
- Avoid: integration tests hitting external APIs, tests requiring running databases/services
|
|
807
|
+
- If you can't determine whether a test needs keys, skip it \u2014 don't run and fail
|
|
808
|
+
|
|
809
|
+
Your objections will be sent back to the apply agent for fixing, so be specific and actionable.`
|
|
788
810
|
}
|
|
789
811
|
});
|
|
790
812
|
let resultText = "";
|
|
@@ -1151,17 +1173,36 @@ async function validateApply(worktreeGit, beforeHash) {
|
|
|
1151
1173
|
errors.push(`Failed to check commits: ${e.message}`);
|
|
1152
1174
|
}
|
|
1153
1175
|
const status = await worktreeGit.status();
|
|
1154
|
-
const
|
|
1176
|
+
const isOurs = (f) => f.startsWith(".backmerge/") || f.startsWith(".backmerge\\");
|
|
1177
|
+
const modified = status.modified.filter((f) => !isOurs(f));
|
|
1178
|
+
const created = status.created.filter((f) => !isOurs(f));
|
|
1179
|
+
const deleted = status.deleted.filter((f) => !isOurs(f));
|
|
1180
|
+
const notAdded = status.not_added.filter((f) => !isOurs(f));
|
|
1181
|
+
const conflicted = status.conflicted.filter((f) => !isOurs(f));
|
|
1182
|
+
const worktreeClean = modified.length === 0 && created.length === 0 && deleted.length === 0 && conflicted.length === 0 && notAdded.length === 0;
|
|
1183
|
+
const dirtyFiles = [];
|
|
1155
1184
|
if (!worktreeClean) {
|
|
1156
1185
|
const parts = [];
|
|
1157
|
-
if (
|
|
1158
|
-
parts.push(`${
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1186
|
+
if (modified.length) {
|
|
1187
|
+
parts.push(`${modified.length} modified`);
|
|
1188
|
+
for (const f of modified)
|
|
1189
|
+
dirtyFiles.push(`M ${f}`);
|
|
1190
|
+
}
|
|
1191
|
+
if (notAdded.length) {
|
|
1192
|
+
parts.push(`${notAdded.length} untracked`);
|
|
1193
|
+
for (const f of notAdded)
|
|
1194
|
+
dirtyFiles.push(`? ${f}`);
|
|
1195
|
+
}
|
|
1196
|
+
if (deleted.length) {
|
|
1197
|
+
parts.push(`${deleted.length} deleted`);
|
|
1198
|
+
for (const f of deleted)
|
|
1199
|
+
dirtyFiles.push(`D ${f}`);
|
|
1200
|
+
}
|
|
1201
|
+
if (conflicted.length) {
|
|
1202
|
+
parts.push(`${conflicted.length} conflicted`);
|
|
1203
|
+
for (const f of conflicted)
|
|
1204
|
+
dirtyFiles.push(`C ${f}`);
|
|
1205
|
+
}
|
|
1165
1206
|
errors.push(`Working tree not clean: ${parts.join(", ")}`);
|
|
1166
1207
|
}
|
|
1167
1208
|
const conflictMarkers = [];
|
|
@@ -1182,7 +1223,15 @@ async function validateApply(worktreeGit, beforeHash) {
|
|
|
1182
1223
|
if (conflictMarkers.length > 0) {
|
|
1183
1224
|
errors.push(`Conflict markers in: ${conflictMarkers.join(", ")}`);
|
|
1184
1225
|
}
|
|
1185
|
-
return {
|
|
1226
|
+
return {
|
|
1227
|
+
valid: errors.length === 0,
|
|
1228
|
+
newCommitHash,
|
|
1229
|
+
newCommitCount,
|
|
1230
|
+
worktreeClean,
|
|
1231
|
+
conflictMarkers,
|
|
1232
|
+
dirtyFiles,
|
|
1233
|
+
errors
|
|
1234
|
+
};
|
|
1186
1235
|
}
|
|
1187
1236
|
async function getAppliedDiff(worktreeGit, beforeHash) {
|
|
1188
1237
|
return worktreeGit.raw(["diff", beforeHash, "HEAD"]);
|
|
@@ -1192,7 +1241,7 @@ async function getAppliedDiffStat(worktreeGit, beforeHash) {
|
|
|
1192
1241
|
}
|
|
1193
1242
|
async function resetHard(git, ref) {
|
|
1194
1243
|
await git.raw(["reset", "--hard", ref]);
|
|
1195
|
-
await git.raw(["clean", "-fd"]);
|
|
1244
|
+
await git.raw(["clean", "-fd", "--exclude=.backmerge"]);
|
|
1196
1245
|
}
|
|
1197
1246
|
async function fetchOrigin(git) {
|
|
1198
1247
|
await git.fetch(["--all", "--prune"]);
|
|
@@ -1335,7 +1384,7 @@ async function runEngine(opts, cb) {
|
|
|
1335
1384
|
cb.onLog(`Eval worktree (detached): ${wtPath}`, "green");
|
|
1336
1385
|
const wtGit = createGit(wtPath);
|
|
1337
1386
|
const runId = `run-${ts}`;
|
|
1338
|
-
const audit = new AuditLog(
|
|
1387
|
+
const audit = new AuditLog(repoPath, runId);
|
|
1339
1388
|
const runMeta = {
|
|
1340
1389
|
runId,
|
|
1341
1390
|
startedAt: new Date().toISOString(),
|
|
@@ -1538,6 +1587,11 @@ async function processOneCommit(o) {
|
|
|
1538
1587
|
const validation = await validateApply(o.wtGit, headBefore);
|
|
1539
1588
|
if (!validation.valid) {
|
|
1540
1589
|
cb.onLog(`Validation failed: ${validation.errors.join("; ")}`, "red");
|
|
1590
|
+
if (validation.dirtyFiles.length > 0) {
|
|
1591
|
+
for (const f of validation.dirtyFiles) {
|
|
1592
|
+
cb.onLog(` ${f}`, "red");
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1541
1595
|
await resetHard(o.wtGit, headBefore);
|
|
1542
1596
|
if (attempt === o.maxAttempts)
|
|
1543
1597
|
return mkFailed(commit, "validation", validation.errors.join("; "), start);
|
|
@@ -1736,34 +1790,217 @@ var exports_batch = {};
|
|
|
1736
1790
|
__export(exports_batch, {
|
|
1737
1791
|
runBatch: () => runBatch
|
|
1738
1792
|
});
|
|
1739
|
-
|
|
1793
|
+
import chalk from "chalk";
|
|
1794
|
+
function shortHash2(h) {
|
|
1795
|
+
return h.slice(0, 8);
|
|
1796
|
+
}
|
|
1797
|
+
function ts() {
|
|
1798
|
+
return chalk.dim(new Date().toISOString().slice(11, 19));
|
|
1799
|
+
}
|
|
1800
|
+
function progressBar2(current, total, width = 25) {
|
|
1801
|
+
const ratio = Math.min(current / total, 1);
|
|
1802
|
+
const filled = Math.round(ratio * width);
|
|
1803
|
+
const empty = width - filled;
|
|
1804
|
+
return `${chalk.green("\u2588".repeat(filled))}${chalk.dim("\u2591".repeat(empty))} ${current}/${total}`;
|
|
1805
|
+
}
|
|
1806
|
+
function divider(char = "\u2500", width = 55) {
|
|
1807
|
+
return chalk.dim(char.repeat(width));
|
|
1808
|
+
}
|
|
1809
|
+
function colorize(color, text) {
|
|
1810
|
+
if (!color)
|
|
1811
|
+
return text;
|
|
1812
|
+
return (colorMap[color] ?? chalk.white)(text);
|
|
1813
|
+
}
|
|
1814
|
+
function decisionBadge(kind) {
|
|
1815
|
+
switch (kind) {
|
|
1816
|
+
case "applied":
|
|
1817
|
+
return chalk.bgGreen.black.bold(" APPLIED ");
|
|
1818
|
+
case "would_apply":
|
|
1819
|
+
return chalk.bgCyan.black.bold(" WOULD APPLY ");
|
|
1820
|
+
case "already_applied":
|
|
1821
|
+
return chalk.bgBlue.white.bold(" ALREADY APPLIED ");
|
|
1822
|
+
case "skip":
|
|
1823
|
+
return chalk.bgYellow.black.bold(" SKIP ");
|
|
1824
|
+
case "failed":
|
|
1825
|
+
return chalk.bgRed.white.bold(" FAILED ");
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
function analysisBadge(status) {
|
|
1829
|
+
switch (status) {
|
|
1830
|
+
case "yes":
|
|
1831
|
+
return chalk.green.bold("PRESENT");
|
|
1832
|
+
case "no":
|
|
1833
|
+
return chalk.red.bold("MISSING");
|
|
1834
|
+
case "partial":
|
|
1835
|
+
return chalk.yellow.bold("PARTIAL");
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
function log(msg) {
|
|
1839
|
+
process.stderr.write(msg + `
|
|
1840
|
+
`);
|
|
1841
|
+
}
|
|
1842
|
+
function emitJsonl(obj) {
|
|
1740
1843
|
process.stdout.write(JSON.stringify({ ...obj, ts: new Date().toISOString() }) + `
|
|
1741
1844
|
`);
|
|
1742
1845
|
}
|
|
1743
1846
|
async function runBatch(opts) {
|
|
1847
|
+
const jsonl = opts.jsonl ?? false;
|
|
1848
|
+
const startTime = Date.now();
|
|
1849
|
+
log("");
|
|
1850
|
+
log(` ${chalk.cyan.bold("xab")} ${chalk.dim("\u2014 curated branch reconciliation")}`);
|
|
1851
|
+
log(` ${chalk.magenta(opts.sourceRef)} ${chalk.dim("\u2192")} ${chalk.green(opts.targetRef)}`);
|
|
1852
|
+
if (opts.workBranch)
|
|
1853
|
+
log(` ${chalk.dim("work branch:")} ${chalk.cyan(opts.workBranch)}`);
|
|
1854
|
+
if (opts.dryRun)
|
|
1855
|
+
log(` ${chalk.yellow.bold("DRY RUN")}`);
|
|
1856
|
+
log(` ${divider()}`);
|
|
1857
|
+
log("");
|
|
1744
1858
|
const cb = {
|
|
1745
1859
|
onLog(msg, color) {
|
|
1746
|
-
|
|
1860
|
+
if (jsonl)
|
|
1861
|
+
emitJsonl({ event: "log", msg, color });
|
|
1862
|
+
if (!msg) {
|
|
1863
|
+
log("");
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
log(` ${ts()} ${colorize(color, msg)}`);
|
|
1747
1867
|
},
|
|
1748
1868
|
onStatus(msg) {
|
|
1749
|
-
|
|
1869
|
+
if (jsonl)
|
|
1870
|
+
emitJsonl({ event: "status", msg });
|
|
1871
|
+
log(` ${ts()} ${chalk.dim("\u203A")} ${msg}`);
|
|
1750
1872
|
},
|
|
1751
1873
|
onCommitStart(commit, index, total) {
|
|
1752
|
-
|
|
1874
|
+
if (jsonl)
|
|
1875
|
+
emitJsonl({ event: "commit_start", hash: commit.hash, message: commit.message, index, total });
|
|
1876
|
+
log("");
|
|
1877
|
+
log(` ${divider()}`);
|
|
1878
|
+
log(` ${progressBar2(index + 1, total)} ${chalk.yellow(shortHash2(commit.hash))}`);
|
|
1879
|
+
log(` ${chalk.bold(commit.message)}`);
|
|
1880
|
+
log(` ${chalk.dim(`by ${commit.author} \xB7 ${commit.date}`)}`);
|
|
1881
|
+
log("");
|
|
1753
1882
|
},
|
|
1754
1883
|
onAnalysis(commit, analysis) {
|
|
1755
|
-
|
|
1884
|
+
if (jsonl)
|
|
1885
|
+
emitJsonl({ event: "analysis", hash: commit.hash, result: analysis });
|
|
1886
|
+
log(` ${ts()} ${chalk.dim("analysis:")} ${analysisBadge(analysis.alreadyInTarget)}`);
|
|
1887
|
+
log(` ${chalk.dim(" summary:")} ${analysis.summary}`);
|
|
1888
|
+
if (analysis.reasoning) {
|
|
1889
|
+
log(` ${chalk.dim(" reasoning:")} ${analysis.reasoning}`);
|
|
1890
|
+
}
|
|
1891
|
+
if (analysis.applicationStrategy && analysis.alreadyInTarget !== "yes") {
|
|
1892
|
+
log(` ${chalk.dim(" strategy:")} ${analysis.applicationStrategy}`);
|
|
1893
|
+
}
|
|
1894
|
+
if (analysis.affectedComponents.length > 0) {
|
|
1895
|
+
log(` ${chalk.dim(" components:")} ${analysis.affectedComponents.join(", ")}`);
|
|
1896
|
+
}
|
|
1897
|
+
if (analysis.opsNotes.length > 0) {
|
|
1898
|
+
log(` ${chalk.yellow(" ops:")} ${analysis.opsNotes.join("; ")}`);
|
|
1899
|
+
}
|
|
1756
1900
|
},
|
|
1757
1901
|
onDecision(commit, decision) {
|
|
1758
|
-
|
|
1902
|
+
if (jsonl)
|
|
1903
|
+
emitJsonl({
|
|
1904
|
+
event: "decision",
|
|
1905
|
+
hash: commit.hash,
|
|
1906
|
+
kind: decision.kind,
|
|
1907
|
+
reason: decision.reason,
|
|
1908
|
+
opsNotes: decision.opsNotes
|
|
1909
|
+
});
|
|
1910
|
+
const duration = chalk.dim(`${(decision.durationMs / 1000).toFixed(1)}s`);
|
|
1911
|
+
log(` ${ts()} ${decisionBadge(decision.kind)} ${duration}`);
|
|
1912
|
+
if (decision.newCommitHash) {
|
|
1913
|
+
log(` ${chalk.dim(" commit:")} ${decision.newCommitHash.slice(0, 8)}`);
|
|
1914
|
+
}
|
|
1915
|
+
if (decision.kind === "failed" && decision.error) {
|
|
1916
|
+
log(` ${chalk.red(` error: ${decision.error}`)}`);
|
|
1917
|
+
}
|
|
1918
|
+
if (decision.reason && decision.kind !== "failed") {
|
|
1919
|
+
log(` ${chalk.dim(" reason:")} ${decision.reason}`);
|
|
1920
|
+
}
|
|
1921
|
+
if (decision.filesChanged && decision.filesChanged.length > 0) {
|
|
1922
|
+
for (const f of decision.filesChanged) {
|
|
1923
|
+
log(` ${chalk.dim(` \xB7 ${f}`)}`);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
if (decision.opsNotes && decision.opsNotes.length > 0) {
|
|
1927
|
+
for (const note of decision.opsNotes) {
|
|
1928
|
+
log(` ${chalk.yellow(` ops: ${note}`)}`);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1759
1931
|
},
|
|
1760
1932
|
onReview(commit, review) {
|
|
1761
|
-
|
|
1933
|
+
if (jsonl)
|
|
1934
|
+
emitJsonl({ event: "review", hash: commit.hash, approved: review.approved, issues: review.issues });
|
|
1935
|
+
const badge = review.approved ? chalk.bgGreen.black.bold(" REVIEW OK ") : chalk.bgRed.white.bold(" REVIEW REJECTED ");
|
|
1936
|
+
log(` ${ts()} ${badge} ${chalk.dim(`confidence: ${review.confidence}`)}`);
|
|
1937
|
+
if (!review.approved && review.issues.length > 0) {
|
|
1938
|
+
for (const issue of review.issues.slice(0, 3)) {
|
|
1939
|
+
log(` ${chalk.red(` \xB7 ${issue.slice(0, 120)}`)}`);
|
|
1940
|
+
}
|
|
1941
|
+
if (review.issues.length > 3) {
|
|
1942
|
+
log(` ${chalk.dim(` ...and ${review.issues.length - 3} more issues`)}`);
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1762
1945
|
}
|
|
1763
1946
|
};
|
|
1947
|
+
let result;
|
|
1764
1948
|
try {
|
|
1765
|
-
|
|
1766
|
-
|
|
1949
|
+
result = await runEngine(opts, cb);
|
|
1950
|
+
} catch (e) {
|
|
1951
|
+
if (jsonl)
|
|
1952
|
+
emitJsonl({ event: "fatal", error: e.message });
|
|
1953
|
+
log("");
|
|
1954
|
+
log(` ${chalk.bgRed.white.bold(" FATAL ")} ${e.message}`);
|
|
1955
|
+
log("");
|
|
1956
|
+
return 1;
|
|
1957
|
+
}
|
|
1958
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);
|
|
1959
|
+
const { summary } = result;
|
|
1960
|
+
log("");
|
|
1961
|
+
log(` ${divider("\u2550")}`);
|
|
1962
|
+
log(` ${chalk.bold("Run complete")} ${chalk.dim(`in ${elapsed}s`)}`);
|
|
1963
|
+
log("");
|
|
1964
|
+
const counters = [
|
|
1965
|
+
summary.applied > 0 && `${chalk.green.bold(`${summary.applied}`)} applied`,
|
|
1966
|
+
summary.wouldApply > 0 && `${chalk.cyan.bold(`${summary.wouldApply}`)} would apply`,
|
|
1967
|
+
summary.alreadyApplied > 0 && `${chalk.blue.bold(`${summary.alreadyApplied}`)} already applied`,
|
|
1968
|
+
summary.skipped > 0 && `${chalk.yellow.bold(`${summary.skipped}`)} skipped`,
|
|
1969
|
+
summary.cherrySkipped > 0 && `${chalk.cyan(`${summary.cherrySkipped}`)} cherry-skipped`,
|
|
1970
|
+
summary.failed > 0 && `${chalk.red.bold(`${summary.failed}`)} failed`
|
|
1971
|
+
].filter(Boolean);
|
|
1972
|
+
log(` ${counters.join(chalk.dim(" \xB7 "))}`);
|
|
1973
|
+
if (result.worktreePath)
|
|
1974
|
+
log(` ${chalk.dim("worktree:")} ${result.worktreePath}`);
|
|
1975
|
+
if (result.workBranch)
|
|
1976
|
+
log(` ${chalk.dim("branch:")} ${result.workBranch}`);
|
|
1977
|
+
if (result.auditDir)
|
|
1978
|
+
log(` ${chalk.dim("audit:")} ${result.auditDir}`);
|
|
1979
|
+
if (result.opsNotes.length > 0) {
|
|
1980
|
+
log("");
|
|
1981
|
+
log(` ${chalk.yellow.bold("OPERATOR NOTES")}`);
|
|
1982
|
+
log(` ${chalk.yellow(divider("\u2500", 40))}`);
|
|
1983
|
+
for (const entry of result.opsNotes) {
|
|
1984
|
+
log(` ${chalk.yellow(shortHash2(entry.commitHash))} ${entry.commitMessage}`);
|
|
1985
|
+
for (const note of entry.notes) {
|
|
1986
|
+
log(` ${chalk.yellow("\u2192")} ${note}`);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
const failed = result.decisions.filter((d) => d.kind === "failed");
|
|
1991
|
+
if (failed.length > 0) {
|
|
1992
|
+
log("");
|
|
1993
|
+
log(` ${chalk.red.bold("FAILED COMMITS")}`);
|
|
1994
|
+
log(` ${chalk.red(divider("\u2500", 40))}`);
|
|
1995
|
+
for (const d of failed) {
|
|
1996
|
+
log(` ${chalk.red(shortHash2(d.commitHash))} ${d.commitMessage}`);
|
|
1997
|
+
log(` ${chalk.dim("phase:")} ${d.failedPhase ?? "?"} ${chalk.dim("error:")} ${d.error?.slice(0, 100) ?? "?"}`);
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
log(` ${divider("\u2550")}`);
|
|
2001
|
+
log("");
|
|
2002
|
+
if (jsonl) {
|
|
2003
|
+
emitJsonl({
|
|
1767
2004
|
event: "done",
|
|
1768
2005
|
summary: result.summary,
|
|
1769
2006
|
worktree: result.worktreePath,
|
|
@@ -1771,17 +2008,24 @@ async function runBatch(opts) {
|
|
|
1771
2008
|
auditDir: result.auditDir,
|
|
1772
2009
|
opsNotes: result.opsNotes
|
|
1773
2010
|
});
|
|
1774
|
-
const { summary } = result;
|
|
1775
|
-
if (summary.failed > 0)
|
|
1776
|
-
return 2;
|
|
1777
|
-
return 0;
|
|
1778
|
-
} catch (e) {
|
|
1779
|
-
emit({ event: "fatal", error: e.message });
|
|
1780
|
-
return 1;
|
|
1781
2011
|
}
|
|
2012
|
+
if (summary.failed > 0)
|
|
2013
|
+
return 2;
|
|
2014
|
+
return 0;
|
|
1782
2015
|
}
|
|
2016
|
+
var colorMap;
|
|
1783
2017
|
var init_batch = __esm(() => {
|
|
1784
2018
|
init_engine();
|
|
2019
|
+
colorMap = {
|
|
2020
|
+
red: chalk.red,
|
|
2021
|
+
green: chalk.green,
|
|
2022
|
+
yellow: chalk.yellow,
|
|
2023
|
+
blue: chalk.blue,
|
|
2024
|
+
magenta: chalk.magenta,
|
|
2025
|
+
cyan: chalk.cyan,
|
|
2026
|
+
gray: chalk.gray,
|
|
2027
|
+
white: chalk.white
|
|
2028
|
+
};
|
|
1785
2029
|
});
|
|
1786
2030
|
|
|
1787
2031
|
// index.ts
|
|
@@ -2548,6 +2792,7 @@ var startAfter = "";
|
|
|
2548
2792
|
var limit = 0;
|
|
2549
2793
|
var configPath = "";
|
|
2550
2794
|
var batch = false;
|
|
2795
|
+
var jsonl = false;
|
|
2551
2796
|
var resume = true;
|
|
2552
2797
|
var showHelp = false;
|
|
2553
2798
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -2556,7 +2801,10 @@ for (let i = 0;i < args.length; i++) {
|
|
|
2556
2801
|
showHelp = true;
|
|
2557
2802
|
else if (arg === "--batch" || arg === "-b")
|
|
2558
2803
|
batch = true;
|
|
2559
|
-
else if (arg === "--
|
|
2804
|
+
else if (arg === "--jsonl") {
|
|
2805
|
+
batch = true;
|
|
2806
|
+
jsonl = true;
|
|
2807
|
+
} else if (arg === "--dry-run")
|
|
2560
2808
|
dryRun = true;
|
|
2561
2809
|
else if (arg === "--list-only")
|
|
2562
2810
|
listOnly = true;
|
|
@@ -2694,7 +2942,8 @@ if (batch || listOnly) {
|
|
|
2694
2942
|
repoPath: resolvedPath,
|
|
2695
2943
|
sourceRef,
|
|
2696
2944
|
targetRef,
|
|
2697
|
-
...engineOpts
|
|
2945
|
+
...engineOpts,
|
|
2946
|
+
jsonl
|
|
2698
2947
|
});
|
|
2699
2948
|
process.exit(exitCode);
|
|
2700
2949
|
} else {
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xab",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "AI-powered curated branch reconciliation engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"xab": "dist/index.js"
|
|
8
8
|
},
|
|
9
|
-
"private":false,
|
|
9
|
+
"private": false,
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "bun build index.ts --outdir dist --target bun --format esm --external @anthropic-ai/claude-agent-sdk --external @openai/codex-sdk --external simple-git --external ink --external ink-select-input --external ink-spinner --external ink-text-input --external react",
|
|
14
|
+
"build": "bun build index.ts --outdir dist --target bun --format esm --external @anthropic-ai/claude-agent-sdk --external @openai/codex-sdk --external simple-git --external ink --external ink-select-input --external ink-spinner --external ink-text-input --external react --external chalk",
|
|
15
15
|
"prepublishOnly": "bun run build",
|
|
16
16
|
"start": "bun run index.ts",
|
|
17
17
|
"dev": "bun run --watch index.ts"
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@anthropic-ai/claude-agent-sdk": "^0.2.85",
|
|
28
28
|
"@openai/codex-sdk": "^0.117.0",
|
|
29
|
+
"chalk": "^5.6.2",
|
|
29
30
|
"ink": "^5.2.1",
|
|
30
31
|
"ink-select-input": "^6.2.0",
|
|
31
32
|
"ink-spinner": "^5.0.0",
|