baro-ai 0.73.0 → 0.73.1
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 +72 -0
- package/dist/cli.mjs.map +1 -1
- package/dist/runner.mjs +1 -1
- package/dist/runner.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -40948,6 +40948,15 @@ var Conductor = class extends BaseObserver {
|
|
|
40948
40948
|
recoveryLevelsStarted = 0;
|
|
40949
40949
|
totalAttempts = 0;
|
|
40950
40950
|
appliedReplans = 0;
|
|
40951
|
+
/**
|
|
40952
|
+
* Healing actions (replan applications + recovery-level starts) since
|
|
40953
|
+
* the last successful story. The Surgeon may propose forever; this is
|
|
40954
|
+
* the Conductor's brake — when it reaches the budget the run ends
|
|
40955
|
+
* gracefully so the Finalizer can ship completed work (checkpoint PR).
|
|
40956
|
+
*/
|
|
40957
|
+
replansSinceProgress = 0;
|
|
40958
|
+
replanProgressBudget;
|
|
40959
|
+
softDeadlineSecs;
|
|
40951
40960
|
currentLevel = null;
|
|
40952
40961
|
/** Replan payloads emitted during a level. Applied at level boundary. */
|
|
40953
40962
|
pendingReplans = [];
|
|
@@ -40984,6 +40993,8 @@ var Conductor = class extends BaseObserver {
|
|
|
40984
40993
|
if (this.opts.intraLevelDelaySecs == null) {
|
|
40985
40994
|
this.opts.intraLevelDelaySecs = 10;
|
|
40986
40995
|
}
|
|
40996
|
+
this.replanProgressBudget = opts.replanProgressBudget ?? envNonNegativeInt("BARO_REPLAN_PROGRESS_BUDGET", 3);
|
|
40997
|
+
this.softDeadlineSecs = opts.softDeadlineSecs ?? envNonNegativeInt("BARO_RUN_SOFT_DEADLINE_SECS", 0);
|
|
40987
40998
|
this.done = new Promise((resolve4) => {
|
|
40988
40999
|
this.resolveDone = resolve4;
|
|
40989
41000
|
});
|
|
@@ -41076,6 +41087,11 @@ var Conductor = class extends BaseObserver {
|
|
|
41076
41087
|
if (levels.length === 0) {
|
|
41077
41088
|
const allPassed = this.prd.userStories.every((s2) => s2.passes) && this.globalDropped.length === 0;
|
|
41078
41089
|
if (!allPassed && this.globalFailed.length > 0) {
|
|
41090
|
+
const halt = this.healingHaltReason();
|
|
41091
|
+
if (halt) {
|
|
41092
|
+
this.terminateRun(false, halt);
|
|
41093
|
+
return;
|
|
41094
|
+
}
|
|
41079
41095
|
const recovered = await this.tryStartRecoveryLevel(
|
|
41080
41096
|
this.globalFailed,
|
|
41081
41097
|
blockedStoryIds.size > 0 ? `blocked dependencies: ${[...blockedStoryIds].join(", ")}` : "terminal failed stories"
|
|
@@ -41086,6 +41102,11 @@ var Conductor = class extends BaseObserver {
|
|
|
41086
41102
|
this.terminateRun(allPassed, abortReason);
|
|
41087
41103
|
return;
|
|
41088
41104
|
}
|
|
41105
|
+
const softDeadline = this.softDeadlineReason();
|
|
41106
|
+
if (softDeadline) {
|
|
41107
|
+
this.terminateRun(false, softDeadline);
|
|
41108
|
+
return;
|
|
41109
|
+
}
|
|
41089
41110
|
const level = levels[0];
|
|
41090
41111
|
const ordinal = (this.currentLevel?.ordinal ?? 0) + 1;
|
|
41091
41112
|
const totalLevelsHint = ordinal + levels.length - 1;
|
|
@@ -41134,6 +41155,7 @@ var Conductor = class extends BaseObserver {
|
|
|
41134
41155
|
this.currentLevel.passed.push(item.storyId);
|
|
41135
41156
|
this.globalCompleted.push(item.storyId);
|
|
41136
41157
|
this.removeGlobalFailed(item.storyId);
|
|
41158
|
+
this.replansSinceProgress = 0;
|
|
41137
41159
|
if (this.prd) {
|
|
41138
41160
|
this.prd = markStoryPassed(this.prd, item.storyId, item.durationSecs);
|
|
41139
41161
|
savePrd(this.opts.prdPath, this.prd);
|
|
@@ -41249,6 +41271,7 @@ ${prompt}`;
|
|
|
41249
41271
|
})
|
|
41250
41272
|
);
|
|
41251
41273
|
let replannedThisLevel = false;
|
|
41274
|
+
let healingHalt = null;
|
|
41252
41275
|
if (this.pendingReplans.length > 0 && this.prd) {
|
|
41253
41276
|
const drained = this.pendingReplans.splice(0);
|
|
41254
41277
|
for (const replan of drained) {
|
|
@@ -41262,8 +41285,11 @@ ${prompt}`;
|
|
|
41262
41285
|
);
|
|
41263
41286
|
continue;
|
|
41264
41287
|
}
|
|
41288
|
+
healingHalt = this.healingHaltReason();
|
|
41289
|
+
if (healingHalt) break;
|
|
41265
41290
|
this.prd = applyReplan(this.prd, replan);
|
|
41266
41291
|
this.appliedReplans += 1;
|
|
41292
|
+
this.noteHealingAction(lvl.ordinal);
|
|
41267
41293
|
replannedThisLevel = true;
|
|
41268
41294
|
if (replan.removedStoryIds.length > 0) {
|
|
41269
41295
|
const removeSet = new Set(replan.removedStoryIds);
|
|
@@ -41291,9 +41317,18 @@ ${prompt}`;
|
|
|
41291
41317
|
}
|
|
41292
41318
|
savePrd(this.opts.prdPath, this.prd);
|
|
41293
41319
|
}
|
|
41320
|
+
if (healingHalt) {
|
|
41321
|
+
this.terminateRun(false, healingHalt);
|
|
41322
|
+
return;
|
|
41323
|
+
}
|
|
41294
41324
|
const anySuccess = lvl.passed.length > 0;
|
|
41295
41325
|
const totalThisLevel = lvl.passed.length + lvl.failed.length;
|
|
41296
41326
|
if (!anySuccess && totalThisLevel > 0 && !replannedThisLevel) {
|
|
41327
|
+
const halt = this.healingHaltReason();
|
|
41328
|
+
if (halt) {
|
|
41329
|
+
this.terminateRun(false, halt);
|
|
41330
|
+
return;
|
|
41331
|
+
}
|
|
41297
41332
|
const recovered = await this.tryStartRecoveryLevel(
|
|
41298
41333
|
lvl.failed,
|
|
41299
41334
|
"all stories in level failed"
|
|
@@ -41372,6 +41407,36 @@ ${prompt}`;
|
|
|
41372
41407
|
}
|
|
41373
41408
|
return blocked;
|
|
41374
41409
|
}
|
|
41410
|
+
/**
|
|
41411
|
+
* Non-null when healing must stop: the progress budget is spent or
|
|
41412
|
+
* the soft deadline has passed. Callers terminate the run with the
|
|
41413
|
+
* returned reason instead of applying a replan / starting recovery.
|
|
41414
|
+
*/
|
|
41415
|
+
healingHaltReason() {
|
|
41416
|
+
if (this.replanProgressBudget > 0 && this.replansSinceProgress >= this.replanProgressBudget) {
|
|
41417
|
+
const n = this.replansSinceProgress;
|
|
41418
|
+
return `no progress after ${n} replan${n === 1 ? "" : "s"} \u2014 stopping so completed work can ship`;
|
|
41419
|
+
}
|
|
41420
|
+
return this.softDeadlineReason();
|
|
41421
|
+
}
|
|
41422
|
+
softDeadlineReason() {
|
|
41423
|
+
if (this.softDeadlineSecs <= 0) return null;
|
|
41424
|
+
const elapsedSecs = (Date.now() - this.startedAt) / 1e3;
|
|
41425
|
+
if (elapsedSecs < this.softDeadlineSecs) return null;
|
|
41426
|
+
return `soft deadline reached (${this.softDeadlineSecs}s) \u2014 stopping so completed work can ship`;
|
|
41427
|
+
}
|
|
41428
|
+
noteHealingAction(currentLevel) {
|
|
41429
|
+
this.replansSinceProgress += 1;
|
|
41430
|
+
if (this.replanProgressBudget > 0) {
|
|
41431
|
+
this.emit(
|
|
41432
|
+
ConductorState.create({
|
|
41433
|
+
phase: "running_level",
|
|
41434
|
+
detail: `replan ${this.replansSinceProgress}/${this.replanProgressBudget} without progress`,
|
|
41435
|
+
...currentLevel != null ? { currentLevel } : {}
|
|
41436
|
+
})
|
|
41437
|
+
);
|
|
41438
|
+
}
|
|
41439
|
+
}
|
|
41375
41440
|
addGlobalFailed(storyId) {
|
|
41376
41441
|
if (!this.globalFailed.includes(storyId)) {
|
|
41377
41442
|
this.globalFailed.push(storyId);
|
|
@@ -41398,6 +41463,7 @@ ${prompt}`;
|
|
|
41398
41463
|
stories.push(story);
|
|
41399
41464
|
}
|
|
41400
41465
|
if (stories.length === 0) return false;
|
|
41466
|
+
this.noteHealingAction(this.currentLevel?.ordinal);
|
|
41401
41467
|
for (const story of stories) {
|
|
41402
41468
|
this.recoveryAttempts.set(
|
|
41403
41469
|
story.id,
|
|
@@ -41513,6 +41579,12 @@ function applyReplan(prd, replan) {
|
|
|
41513
41579
|
}
|
|
41514
41580
|
return { ...prd, userStories: stories };
|
|
41515
41581
|
}
|
|
41582
|
+
function envNonNegativeInt(name, fallback) {
|
|
41583
|
+
const raw = process.env[name];
|
|
41584
|
+
if (raw == null || raw.trim() === "") return fallback;
|
|
41585
|
+
const n = Number(raw);
|
|
41586
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : fallback;
|
|
41587
|
+
}
|
|
41516
41588
|
function readFileSyncSafe(path6) {
|
|
41517
41589
|
try {
|
|
41518
41590
|
return readFileSync2(path6, "utf8");
|