baro-ai 0.47.5 → 0.47.7
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/cli.mjs +136 -5
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -39754,6 +39754,13 @@ var Conductor = class extends BaseObserver {
|
|
|
39754
39754
|
* is true only when this list is empty.
|
|
39755
39755
|
*/
|
|
39756
39756
|
globalDropped = [];
|
|
39757
|
+
/**
|
|
39758
|
+
* Extra end-of-run recovery attempts, separate from each StoryAgent's own
|
|
39759
|
+
* retry loop. A story may exhaust its normal attempts, block the DAG, and
|
|
39760
|
+
* still be recoverable after sibling stories have landed more context/code.
|
|
39761
|
+
*/
|
|
39762
|
+
recoveryAttempts = /* @__PURE__ */ new Map();
|
|
39763
|
+
maxRecoveryAttemptsPerStory = 1;
|
|
39757
39764
|
totalAttempts = 0;
|
|
39758
39765
|
appliedReplans = 0;
|
|
39759
39766
|
currentLevel = null;
|
|
@@ -39860,10 +39867,23 @@ var Conductor = class extends BaseObserver {
|
|
|
39860
39867
|
async handleLevelCompute() {
|
|
39861
39868
|
if (this.phase !== "computing") return;
|
|
39862
39869
|
if (!this.prd) return;
|
|
39863
|
-
const
|
|
39870
|
+
const blockedStoryIds = this.computeBlockedStoryIds();
|
|
39871
|
+
const failedIds = new Set(this.globalFailed);
|
|
39872
|
+
const runnableStories = this.prd.userStories.filter(
|
|
39873
|
+
(s2) => !s2.passes && !failedIds.has(s2.id) && !blockedStoryIds.has(s2.id)
|
|
39874
|
+
);
|
|
39875
|
+
const levels = buildDag(runnableStories);
|
|
39864
39876
|
if (levels.length === 0) {
|
|
39865
39877
|
const allPassed = this.prd.userStories.every((s2) => s2.passes) && this.globalDropped.length === 0;
|
|
39866
|
-
|
|
39878
|
+
if (!allPassed && this.globalFailed.length > 0) {
|
|
39879
|
+
const recovered = await this.tryStartRecoveryLevel(
|
|
39880
|
+
this.globalFailed,
|
|
39881
|
+
blockedStoryIds.size > 0 ? `blocked dependencies: ${[...blockedStoryIds].join(", ")}` : "terminal failed stories"
|
|
39882
|
+
);
|
|
39883
|
+
if (recovered) return;
|
|
39884
|
+
}
|
|
39885
|
+
const abortReason = allPassed ? null : this.globalFailed.length > 0 ? blockedStoryIds.size > 0 ? `blocked by failed dependencies: failed ${this.globalFailed.join(", ")}; blocked ${[...blockedStoryIds].join(", ")}` : `stories failed: ${this.globalFailed.join(", ")}` : null;
|
|
39886
|
+
this.terminateRun(allPassed, abortReason);
|
|
39867
39887
|
return;
|
|
39868
39888
|
}
|
|
39869
39889
|
const level = levels[0];
|
|
@@ -39913,6 +39933,7 @@ var Conductor = class extends BaseObserver {
|
|
|
39913
39933
|
if (item.success) {
|
|
39914
39934
|
this.currentLevel.passed.push(item.storyId);
|
|
39915
39935
|
this.globalCompleted.push(item.storyId);
|
|
39936
|
+
this.removeGlobalFailed(item.storyId);
|
|
39916
39937
|
if (this.prd) {
|
|
39917
39938
|
this.prd = markStoryPassed(this.prd, item.storyId, item.durationSecs);
|
|
39918
39939
|
savePrd(this.opts.prdPath, this.prd);
|
|
@@ -39933,7 +39954,7 @@ var Conductor = class extends BaseObserver {
|
|
|
39933
39954
|
}
|
|
39934
39955
|
} else {
|
|
39935
39956
|
this.currentLevel.failed.push(item.storyId);
|
|
39936
|
-
this.
|
|
39957
|
+
this.addGlobalFailed(item.storyId);
|
|
39937
39958
|
}
|
|
39938
39959
|
await this.fillSpawnSlots();
|
|
39939
39960
|
if (this.currentLevel.pending.size === 0) {
|
|
@@ -40017,6 +40038,16 @@ ${prompt}`;
|
|
|
40017
40038
|
if (this.pendingReplans.length > 0 && this.prd) {
|
|
40018
40039
|
const drained = this.pendingReplans.splice(0);
|
|
40019
40040
|
for (const replan of drained) {
|
|
40041
|
+
if (replan.removedStoryIds.length > 0 && replan.addedStories.length === 0) {
|
|
40042
|
+
this.emit(
|
|
40043
|
+
ConductorState.create({
|
|
40044
|
+
phase: "running_level",
|
|
40045
|
+
detail: `skip proposal deferred (source=${replan.source}, -${replan.removedStoryIds.length}): ${replan.reason}`,
|
|
40046
|
+
currentLevel: lvl.ordinal
|
|
40047
|
+
})
|
|
40048
|
+
);
|
|
40049
|
+
continue;
|
|
40050
|
+
}
|
|
40020
40051
|
this.prd = applyReplan(this.prd, replan);
|
|
40021
40052
|
this.appliedReplans += 1;
|
|
40022
40053
|
replannedThisLevel = true;
|
|
@@ -40049,6 +40080,11 @@ ${prompt}`;
|
|
|
40049
40080
|
const anySuccess = lvl.passed.length > 0;
|
|
40050
40081
|
const totalThisLevel = lvl.passed.length + lvl.failed.length;
|
|
40051
40082
|
if (!anySuccess && totalThisLevel > 0 && !replannedThisLevel) {
|
|
40083
|
+
const recovered = await this.tryStartRecoveryLevel(
|
|
40084
|
+
lvl.failed,
|
|
40085
|
+
"all stories in level failed"
|
|
40086
|
+
);
|
|
40087
|
+
if (recovered) return;
|
|
40052
40088
|
this.terminateRun(
|
|
40053
40089
|
false,
|
|
40054
40090
|
"all stories in level failed; aborting remaining levels"
|
|
@@ -40094,6 +40130,99 @@ ${prompt}`;
|
|
|
40094
40130
|
}
|
|
40095
40131
|
this.resolveDone(summary);
|
|
40096
40132
|
}
|
|
40133
|
+
/**
|
|
40134
|
+
* Stories whose dependency chain includes a terminally failed story cannot
|
|
40135
|
+
* become runnable in this run. Keep them out of the remaining DAG so
|
|
40136
|
+
* `buildDag` cannot silently promote them after the failed dependency is
|
|
40137
|
+
* filtered out. Do NOT mark them passed/dropped here: this is a checkpoint,
|
|
40138
|
+
* and the user may choose to rerun the failed prerequisite on resume.
|
|
40139
|
+
*/
|
|
40140
|
+
computeBlockedStoryIds() {
|
|
40141
|
+
if (!this.prd || this.globalFailed.length === 0) {
|
|
40142
|
+
return /* @__PURE__ */ new Set();
|
|
40143
|
+
}
|
|
40144
|
+
const failed = new Set(this.globalFailed);
|
|
40145
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
40146
|
+
let changed = true;
|
|
40147
|
+
while (changed) {
|
|
40148
|
+
changed = false;
|
|
40149
|
+
for (const story of this.prd.userStories) {
|
|
40150
|
+
if (story.passes || failed.has(story.id) || blocked.has(story.id)) {
|
|
40151
|
+
continue;
|
|
40152
|
+
}
|
|
40153
|
+
if ((story.dependsOn ?? []).some((id) => failed.has(id) || blocked.has(id))) {
|
|
40154
|
+
blocked.add(story.id);
|
|
40155
|
+
changed = true;
|
|
40156
|
+
}
|
|
40157
|
+
}
|
|
40158
|
+
}
|
|
40159
|
+
return blocked;
|
|
40160
|
+
}
|
|
40161
|
+
addGlobalFailed(storyId) {
|
|
40162
|
+
if (!this.globalFailed.includes(storyId)) {
|
|
40163
|
+
this.globalFailed.push(storyId);
|
|
40164
|
+
}
|
|
40165
|
+
}
|
|
40166
|
+
removeGlobalFailed(storyId) {
|
|
40167
|
+
for (let i2 = this.globalFailed.length - 1; i2 >= 0; i2--) {
|
|
40168
|
+
if (this.globalFailed[i2] === storyId) {
|
|
40169
|
+
this.globalFailed.splice(i2, 1);
|
|
40170
|
+
}
|
|
40171
|
+
}
|
|
40172
|
+
}
|
|
40173
|
+
async tryStartRecoveryLevel(candidateIds, reason) {
|
|
40174
|
+
if (!this.prd) return false;
|
|
40175
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40176
|
+
const stories = [];
|
|
40177
|
+
for (const id of candidateIds) {
|
|
40178
|
+
if (seen.has(id)) continue;
|
|
40179
|
+
seen.add(id);
|
|
40180
|
+
const attempts = this.recoveryAttempts.get(id) ?? 0;
|
|
40181
|
+
if (attempts >= this.maxRecoveryAttemptsPerStory) continue;
|
|
40182
|
+
const story = this.prd.userStories.find((s2) => s2.id === id);
|
|
40183
|
+
if (!story || story.passes) continue;
|
|
40184
|
+
stories.push(story);
|
|
40185
|
+
}
|
|
40186
|
+
if (stories.length === 0) return false;
|
|
40187
|
+
for (const story of stories) {
|
|
40188
|
+
this.recoveryAttempts.set(
|
|
40189
|
+
story.id,
|
|
40190
|
+
(this.recoveryAttempts.get(story.id) ?? 0) + 1
|
|
40191
|
+
);
|
|
40192
|
+
this.removeGlobalFailed(story.id);
|
|
40193
|
+
}
|
|
40194
|
+
const ordinal = (this.currentLevel?.ordinal ?? 0) + 1;
|
|
40195
|
+
const totalLevelsHint = ordinal;
|
|
40196
|
+
this.currentLevel = {
|
|
40197
|
+
ordinal,
|
|
40198
|
+
totalLevelsHint,
|
|
40199
|
+
storyIds: stories.map((s2) => s2.id),
|
|
40200
|
+
pending: new Set(stories.map((s2) => s2.id)),
|
|
40201
|
+
passed: [],
|
|
40202
|
+
failed: [],
|
|
40203
|
+
perStoryAttempts: /* @__PURE__ */ new Map()
|
|
40204
|
+
};
|
|
40205
|
+
this.emit(
|
|
40206
|
+
LevelStarted.create({
|
|
40207
|
+
ordinal,
|
|
40208
|
+
totalLevelsHint,
|
|
40209
|
+
storyIds: this.currentLevel.storyIds
|
|
40210
|
+
})
|
|
40211
|
+
);
|
|
40212
|
+
this.emit(
|
|
40213
|
+
ConductorState.create({
|
|
40214
|
+
phase: "running_level",
|
|
40215
|
+
detail: `auto-recovery retry for ${this.currentLevel.storyIds.join(", ")} (${reason})`,
|
|
40216
|
+
currentLevel: ordinal,
|
|
40217
|
+
totalLevels: totalLevelsHint,
|
|
40218
|
+
storyIds: this.currentLevel.storyIds
|
|
40219
|
+
})
|
|
40220
|
+
);
|
|
40221
|
+
this.phase = "running";
|
|
40222
|
+
this.spawnQueue.push(...stories);
|
|
40223
|
+
await this.fillSpawnSlots();
|
|
40224
|
+
return true;
|
|
40225
|
+
}
|
|
40097
40226
|
resolvePrompt(story) {
|
|
40098
40227
|
const candidatePath = this.opts.promptTemplatePath ?? join(this.opts.cwd, "prompt.md");
|
|
40099
40228
|
let prompt;
|
|
@@ -40920,8 +41049,10 @@ var Finalizer = class extends BaseObserver {
|
|
|
40920
41049
|
}
|
|
40921
41050
|
async finalize(run) {
|
|
40922
41051
|
if (!this.opts.createPr) return;
|
|
40923
|
-
if (!run.success
|
|
40924
|
-
this.log(
|
|
41052
|
+
if (!run.success) {
|
|
41053
|
+
this.log(
|
|
41054
|
+
`[finalizer] run did not complete successfully (${run.abortReason ?? "no reason"}); skipping PR`
|
|
41055
|
+
);
|
|
40925
41056
|
this.emit(
|
|
40926
41057
|
PrCreated.create({
|
|
40927
41058
|
url: null,
|