baro-ai 0.110.0 → 0.111.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/cli.mjs +121 -13
- package/dist/cli.mjs.map +1 -1
- package/dist/operator.mjs +110 -11
- package/dist/operator.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -44476,6 +44476,14 @@ var WorktreeManager = class {
|
|
|
44476
44476
|
try {
|
|
44477
44477
|
await this.autoCommitLeftovers(storyId, path6);
|
|
44478
44478
|
const mergeTarget = candidateSeal ? await this.sealedMergeTarget(storyId, path6, candidateSeal) : branch;
|
|
44479
|
+
const blocked = await this.hostCheckoutBlocks(mergeTarget);
|
|
44480
|
+
if (blocked.length) {
|
|
44481
|
+
this.markPreserved(storyId);
|
|
44482
|
+
throw new WorktreeRefusalError(
|
|
44483
|
+
"host_checkout_dirty",
|
|
44484
|
+
`story ${storyId} cannot land: the host checkout has uncommitted changes on [${blocked.join(", ")}]; the story is intact on ${branch} \u2014 commit or stash those files, then merge it`
|
|
44485
|
+
);
|
|
44486
|
+
}
|
|
44479
44487
|
const msg = `baro: merge story ${storyId}`;
|
|
44480
44488
|
try {
|
|
44481
44489
|
await runRepositoryCommand("git", ["merge", "--no-ff", "-m", msg, mergeTarget], {
|
|
@@ -44501,8 +44509,9 @@ var WorktreeManager = class {
|
|
|
44501
44509
|
}
|
|
44502
44510
|
if (!this.resolveConflictsWithTheirs) {
|
|
44503
44511
|
this.markPreserved(storyId);
|
|
44504
|
-
throw new
|
|
44505
|
-
|
|
44512
|
+
throw new WorktreeRefusalError(
|
|
44513
|
+
"merge_conflict",
|
|
44514
|
+
conflicts.length ? `story ${storyId} conflicts with already-merged work on [${conflicts.join(", ")}]` : `story ${storyId} merge-back failed without a conflict: ${gitFailureDetail(error)}`
|
|
44506
44515
|
);
|
|
44507
44516
|
}
|
|
44508
44517
|
this.log(
|
|
@@ -44997,6 +45006,23 @@ ${missing.join("\n")}
|
|
|
44997
45006
|
}
|
|
44998
45007
|
this.preserved.delete(storyId);
|
|
44999
45008
|
}
|
|
45009
|
+
/** Tracked paths dirty in the host checkout that the merge would also
|
|
45010
|
+
* write. git refuses such a merge outright; reported as a conflict it
|
|
45011
|
+
* sent two recoveries after the same wall on the first self-hosting run. */
|
|
45012
|
+
async hostCheckoutBlocks(mergeTarget) {
|
|
45013
|
+
const [{ stdout: status }, { stdout: touched }] = await Promise.all([
|
|
45014
|
+
runRepositoryCommand("git", ["status", "--porcelain", "--untracked-files=no"], {
|
|
45015
|
+
cwd: this.repoRoot
|
|
45016
|
+
}),
|
|
45017
|
+
runRepositoryCommand("git", ["diff", "--name-only", "HEAD", mergeTarget], {
|
|
45018
|
+
cwd: this.repoRoot
|
|
45019
|
+
})
|
|
45020
|
+
]);
|
|
45021
|
+
const dirty = new Set(
|
|
45022
|
+
status.split("\n").filter(Boolean).map(porcelainPath)
|
|
45023
|
+
);
|
|
45024
|
+
return touched.split("\n").map((line) => line.trim()).filter((path6) => path6 && dirty.has(path6));
|
|
45025
|
+
}
|
|
45000
45026
|
async conflictedPaths() {
|
|
45001
45027
|
try {
|
|
45002
45028
|
const { stdout } = await runRepositoryCommand(
|
|
@@ -45077,6 +45103,18 @@ function rmSyncQuiet(path6) {
|
|
|
45077
45103
|
function errMsg(e2) {
|
|
45078
45104
|
return e2?.message ?? String(e2);
|
|
45079
45105
|
}
|
|
45106
|
+
function gitFailureDetail(e2) {
|
|
45107
|
+
if (e2 instanceof RepositoryCommandError) {
|
|
45108
|
+
const line = e2.stderr.split("\n").find((l) => l.trim());
|
|
45109
|
+
if (line) return line.trim();
|
|
45110
|
+
}
|
|
45111
|
+
return errMsg(e2);
|
|
45112
|
+
}
|
|
45113
|
+
function porcelainPath(line) {
|
|
45114
|
+
const entry = line.slice(3);
|
|
45115
|
+
const renamed = entry.indexOf(" -> ");
|
|
45116
|
+
return (renamed === -1 ? entry : entry.slice(renamed + 4)).trim();
|
|
45117
|
+
}
|
|
45080
45118
|
|
|
45081
45119
|
// ../baro-orchestrator/src/runtime/story-outcome-authority.ts
|
|
45082
45120
|
var StoryOutcomeAuthority = class {
|
|
@@ -66597,6 +66635,10 @@ function translateDeclaredTests(cwd, requirements, packageManagers) {
|
|
|
66597
66635
|
if (requirement.declarationError) {
|
|
66598
66636
|
return incomplete(requirement, requirement.declarationError);
|
|
66599
66637
|
}
|
|
66638
|
+
const scoped = splitCdPrefix(requirement.command);
|
|
66639
|
+
if (scoped) {
|
|
66640
|
+
return translateCdScoped(cwd, requirement, scoped, packageManagers);
|
|
66641
|
+
}
|
|
66600
66642
|
const parsed = tokenize2(requirement.command);
|
|
66601
66643
|
if (typeof parsed === "string") return incomplete(requirement, parsed);
|
|
66602
66644
|
return dispatchDeclared(
|
|
@@ -66660,6 +66702,68 @@ function dispatchDeclared(cwd, requirement, parsed, packageManagers, insideDdev)
|
|
|
66660
66702
|
"unsupported declared test; allowed tools are npm/pnpm/yarn, exact npx rstest run paths, cargo, node, git diff --check, composer, vendor/bin/phpunit, and ddev exec"
|
|
66661
66703
|
);
|
|
66662
66704
|
}
|
|
66705
|
+
var CD_PREFIX = /^cd\s+([^\s&]+)\s*&&\s*([^]*)$/;
|
|
66706
|
+
function splitCdPrefix(command) {
|
|
66707
|
+
if (typeof command !== "string" || command.length > MAX_COMMAND_LENGTH) {
|
|
66708
|
+
return null;
|
|
66709
|
+
}
|
|
66710
|
+
const match = CD_PREFIX.exec(command.trim());
|
|
66711
|
+
return match ? { dir: match[1], inner: match[2] } : null;
|
|
66712
|
+
}
|
|
66713
|
+
function translateCdScoped(root, requirement, scoped, packageManagers) {
|
|
66714
|
+
const dirTokens = tokenize2(scoped.dir);
|
|
66715
|
+
if (typeof dirTokens === "string") return incomplete(requirement, dirTokens);
|
|
66716
|
+
const parsed = tokenize2(scoped.inner);
|
|
66717
|
+
if (typeof parsed === "string") return incomplete(requirement, parsed);
|
|
66718
|
+
const dir = dirTokens.tokens[0];
|
|
66719
|
+
const contained = containedPath(root, dir, false);
|
|
66720
|
+
let isDirectory = false;
|
|
66721
|
+
if (contained.path) {
|
|
66722
|
+
try {
|
|
66723
|
+
isDirectory = statSync3(
|
|
66724
|
+
realpathSync(resolve4(root, contained.path))
|
|
66725
|
+
).isDirectory();
|
|
66726
|
+
} catch {
|
|
66727
|
+
isDirectory = false;
|
|
66728
|
+
}
|
|
66729
|
+
}
|
|
66730
|
+
if (!contained.path || !isDirectory) {
|
|
66731
|
+
return incomplete(
|
|
66732
|
+
requirement,
|
|
66733
|
+
`cd target '${dir}' must be an existing directory inside the repository`
|
|
66734
|
+
);
|
|
66735
|
+
}
|
|
66736
|
+
if (contained.path === ".") {
|
|
66737
|
+
return dispatchDeclared(root, requirement, parsed, packageManagers, false);
|
|
66738
|
+
}
|
|
66739
|
+
const rel = contained.path;
|
|
66740
|
+
const scopeCwd = resolve4(root, rel);
|
|
66741
|
+
const scopedIncomplete = (reason) => incomplete(requirement, `cd ${rel}: ${reason}`);
|
|
66742
|
+
const tool = parsed.tokens[0];
|
|
66743
|
+
if (tool === "ddev" || tool === "npx") {
|
|
66744
|
+
return scopedIncomplete(
|
|
66745
|
+
`'${tool}' declarations cannot be scoped with cd; declare them from the repository root`
|
|
66746
|
+
);
|
|
66747
|
+
}
|
|
66748
|
+
const alias = trustedScriptAlias(scopeCwd, parsed.tokens);
|
|
66749
|
+
if (alias || /^(npm|pnpm|yarn)$/.test(tool ?? "")) {
|
|
66750
|
+
const base = alias ? ["npm", "run", alias] : parsed.tokens;
|
|
66751
|
+
const [manager, operation, ...rest] = base;
|
|
66752
|
+
const tokens2 = operation === void 0 ? base : [manager, operation, `--workspace=${rel}`, ...rest];
|
|
66753
|
+
const spec2 = translatePackage(
|
|
66754
|
+
root,
|
|
66755
|
+
requirement,
|
|
66756
|
+
{ normalized: tokens2.join(" "), tokens: tokens2 },
|
|
66757
|
+
packageManagers
|
|
66758
|
+
);
|
|
66759
|
+
return spec2.incompleteReason === void 0 ? spec2 : scopedIncomplete(spec2.incompleteReason);
|
|
66760
|
+
}
|
|
66761
|
+
const spec = tool === "node" ? translateNode(scopeCwd, requirement, parsed, root) : dispatchDeclared(scopeCwd, requirement, parsed, packageManagers, false);
|
|
66762
|
+
if (spec.incompleteReason !== void 0) {
|
|
66763
|
+
return scopedIncomplete(spec.incompleteReason);
|
|
66764
|
+
}
|
|
66765
|
+
return { ...spec, label: `cd ${rel} && ${spec.label}`, cwd: scopeCwd };
|
|
66766
|
+
}
|
|
66663
66767
|
function unwrapQuotedToken(token) {
|
|
66664
66768
|
if (!/["']/.test(token)) return token;
|
|
66665
66769
|
if (token.length >= 2 && (token[0] === '"' || token[0] === "'") && token[token.length - 1] === token[0]) {
|
|
@@ -67166,12 +67270,12 @@ function containedPath(cwd, candidate, requireFile) {
|
|
|
67166
67270
|
}
|
|
67167
67271
|
return { path: (fromRoot || ".").replace(/\\/g, "/") };
|
|
67168
67272
|
}
|
|
67169
|
-
function translateNode(cwd, requirement, parsed) {
|
|
67273
|
+
function translateNode(cwd, requirement, parsed, manifestRoot = cwd) {
|
|
67170
67274
|
const hasTsxLoader = parsed.tokens[1] === "--import" && parsed.tokens[2] === "tsx";
|
|
67171
67275
|
const loaderArgs = hasTsxLoader ? ["--import", "tsx"] : [];
|
|
67172
67276
|
const rest = parsed.tokens.slice(1 + loaderArgs.length);
|
|
67173
67277
|
const mode = rest[0];
|
|
67174
|
-
if (rest.length === 1 && typeof mode === "string" && !mode.startsWith("-") && !existsSync5(join8(cwd, "package.json"))) {
|
|
67278
|
+
if (rest.length === 1 && typeof mode === "string" && !mode.startsWith("-") && !existsSync5(join8(cwd, "package.json")) && !existsSync5(join8(manifestRoot, "package.json"))) {
|
|
67175
67279
|
const contained = containedPath(cwd, mode, true);
|
|
67176
67280
|
if (!contained.path) {
|
|
67177
67281
|
return incomplete(
|
|
@@ -69255,27 +69359,31 @@ var GitCoordinator = class extends SerializedObserver {
|
|
|
69255
69359
|
);
|
|
69256
69360
|
} catch (e2) {
|
|
69257
69361
|
const error = e2?.message ?? String(e2);
|
|
69362
|
+
const invariant = e2?.invariant ?? "unknown";
|
|
69258
69363
|
let branch = worktrees.branchName(storyId);
|
|
69259
69364
|
let retryable = false;
|
|
69260
69365
|
let preparationError = null;
|
|
69261
|
-
|
|
69262
|
-
|
|
69263
|
-
|
|
69264
|
-
|
|
69265
|
-
|
|
69266
|
-
|
|
69366
|
+
const blockedByHost = invariant === "host_checkout_dirty";
|
|
69367
|
+
if (!blockedByHost) {
|
|
69368
|
+
try {
|
|
69369
|
+
branch = await worktrees.prepareConflictRetry(storyId);
|
|
69370
|
+
retryable = true;
|
|
69371
|
+
} catch (prepareError) {
|
|
69372
|
+
preparationError = prepareError?.message ?? String(prepareError);
|
|
69373
|
+
retryable = isRepositoryCommandSignalDeath(e2);
|
|
69374
|
+
}
|
|
69267
69375
|
}
|
|
69268
69376
|
this.emitIntegrationRefused({
|
|
69269
69377
|
storyId,
|
|
69270
69378
|
runId: correlation?.runId ?? null,
|
|
69271
69379
|
leaseId: correlation?.leaseId ?? null,
|
|
69272
|
-
invariant
|
|
69380
|
+
invariant,
|
|
69273
69381
|
detail: error,
|
|
69274
69382
|
branch,
|
|
69275
69383
|
retryable,
|
|
69276
69384
|
// Only a successful prepareConflictRetry mints an immutable
|
|
69277
69385
|
// recovery ref; otherwise `branch` is still the logical one.
|
|
69278
|
-
recoveryRef: preparationError ? null : branch
|
|
69386
|
+
recoveryRef: preparationError || blockedByHost ? null : branch
|
|
69279
69387
|
});
|
|
69280
69388
|
this.emitBus(
|
|
69281
69389
|
StoryMergeFailed.create({
|
|
@@ -69287,7 +69395,7 @@ var GitCoordinator = class extends SerializedObserver {
|
|
|
69287
69395
|
})
|
|
69288
69396
|
);
|
|
69289
69397
|
log2(
|
|
69290
|
-
retryable ? `[git] merge-back failed; attempt preserved at ${branch} and queued for recovery: ${error}` : `[git] merge-back failed; worktree preserved for manual recovery: ${error}`
|
|
69398
|
+
retryable ? `[git] merge-back failed; attempt preserved at ${branch} and queued for recovery: ${error}` : blockedByHost ? `[git] merge-back blocked by the host checkout; story kept on ${branch}: ${error}` : `[git] merge-back failed; worktree preserved for manual recovery: ${error}`
|
|
69291
69399
|
);
|
|
69292
69400
|
if (emitTui) {
|
|
69293
69401
|
emit({ type: "push_status", id: storyId, success: false, error });
|