xab 4.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 +70 -13
- package/package.json +1 -1
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, {
|
|
@@ -1166,16 +1180,29 @@ async function validateApply(worktreeGit, beforeHash) {
|
|
|
1166
1180
|
const notAdded = status.not_added.filter((f) => !isOurs(f));
|
|
1167
1181
|
const conflicted = status.conflicted.filter((f) => !isOurs(f));
|
|
1168
1182
|
const worktreeClean = modified.length === 0 && created.length === 0 && deleted.length === 0 && conflicted.length === 0 && notAdded.length === 0;
|
|
1183
|
+
const dirtyFiles = [];
|
|
1169
1184
|
if (!worktreeClean) {
|
|
1170
1185
|
const parts = [];
|
|
1171
|
-
if (modified.length)
|
|
1186
|
+
if (modified.length) {
|
|
1172
1187
|
parts.push(`${modified.length} modified`);
|
|
1173
|
-
|
|
1188
|
+
for (const f of modified)
|
|
1189
|
+
dirtyFiles.push(`M ${f}`);
|
|
1190
|
+
}
|
|
1191
|
+
if (notAdded.length) {
|
|
1174
1192
|
parts.push(`${notAdded.length} untracked`);
|
|
1175
|
-
|
|
1193
|
+
for (const f of notAdded)
|
|
1194
|
+
dirtyFiles.push(`? ${f}`);
|
|
1195
|
+
}
|
|
1196
|
+
if (deleted.length) {
|
|
1176
1197
|
parts.push(`${deleted.length} deleted`);
|
|
1177
|
-
|
|
1198
|
+
for (const f of deleted)
|
|
1199
|
+
dirtyFiles.push(`D ${f}`);
|
|
1200
|
+
}
|
|
1201
|
+
if (conflicted.length) {
|
|
1178
1202
|
parts.push(`${conflicted.length} conflicted`);
|
|
1203
|
+
for (const f of conflicted)
|
|
1204
|
+
dirtyFiles.push(`C ${f}`);
|
|
1205
|
+
}
|
|
1179
1206
|
errors.push(`Working tree not clean: ${parts.join(", ")}`);
|
|
1180
1207
|
}
|
|
1181
1208
|
const conflictMarkers = [];
|
|
@@ -1196,7 +1223,15 @@ async function validateApply(worktreeGit, beforeHash) {
|
|
|
1196
1223
|
if (conflictMarkers.length > 0) {
|
|
1197
1224
|
errors.push(`Conflict markers in: ${conflictMarkers.join(", ")}`);
|
|
1198
1225
|
}
|
|
1199
|
-
return {
|
|
1226
|
+
return {
|
|
1227
|
+
valid: errors.length === 0,
|
|
1228
|
+
newCommitHash,
|
|
1229
|
+
newCommitCount,
|
|
1230
|
+
worktreeClean,
|
|
1231
|
+
conflictMarkers,
|
|
1232
|
+
dirtyFiles,
|
|
1233
|
+
errors
|
|
1234
|
+
};
|
|
1200
1235
|
}
|
|
1201
1236
|
async function getAppliedDiff(worktreeGit, beforeHash) {
|
|
1202
1237
|
return worktreeGit.raw(["diff", beforeHash, "HEAD"]);
|
|
@@ -1552,6 +1587,11 @@ async function processOneCommit(o) {
|
|
|
1552
1587
|
const validation = await validateApply(o.wtGit, headBefore);
|
|
1553
1588
|
if (!validation.valid) {
|
|
1554
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
|
+
}
|
|
1555
1595
|
await resetHard(o.wtGit, headBefore);
|
|
1556
1596
|
if (attempt === o.maxAttempts)
|
|
1557
1597
|
return mkFailed(commit, "validation", validation.errors.join("; "), start);
|
|
@@ -1844,7 +1884,13 @@ async function runBatch(opts) {
|
|
|
1844
1884
|
if (jsonl)
|
|
1845
1885
|
emitJsonl({ event: "analysis", hash: commit.hash, result: analysis });
|
|
1846
1886
|
log(` ${ts()} ${chalk.dim("analysis:")} ${analysisBadge(analysis.alreadyInTarget)}`);
|
|
1847
|
-
log(` ${chalk.dim(" summary:")} ${analysis.summary
|
|
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
|
+
}
|
|
1848
1894
|
if (analysis.affectedComponents.length > 0) {
|
|
1849
1895
|
log(` ${chalk.dim(" components:")} ${analysis.affectedComponents.join(", ")}`);
|
|
1850
1896
|
}
|
|
@@ -1863,13 +1909,24 @@ async function runBatch(opts) {
|
|
|
1863
1909
|
});
|
|
1864
1910
|
const duration = chalk.dim(`${(decision.durationMs / 1000).toFixed(1)}s`);
|
|
1865
1911
|
log(` ${ts()} ${decisionBadge(decision.kind)} ${duration}`);
|
|
1912
|
+
if (decision.newCommitHash) {
|
|
1913
|
+
log(` ${chalk.dim(" commit:")} ${decision.newCommitHash.slice(0, 8)}`);
|
|
1914
|
+
}
|
|
1866
1915
|
if (decision.kind === "failed" && decision.error) {
|
|
1867
|
-
log(` ${chalk.red(` error: ${decision.error
|
|
1916
|
+
log(` ${chalk.red(` error: ${decision.error}`)}`);
|
|
1917
|
+
}
|
|
1918
|
+
if (decision.reason && decision.kind !== "failed") {
|
|
1919
|
+
log(` ${chalk.dim(" reason:")} ${decision.reason}`);
|
|
1868
1920
|
}
|
|
1869
1921
|
if (decision.filesChanged && decision.filesChanged.length > 0) {
|
|
1870
|
-
const
|
|
1871
|
-
|
|
1872
|
-
|
|
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
|
+
}
|
|
1873
1930
|
}
|
|
1874
1931
|
},
|
|
1875
1932
|
onReview(commit, review) {
|