baro-ai 0.125.0 → 0.126.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 +162 -12
- package/dist/cli.mjs.map +1 -1
- package/dist/runner.mjs +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.js +55 -23
package/dist/cli.mjs
CHANGED
|
@@ -70955,8 +70955,8 @@ async function getCurrentBranch(cwd) {
|
|
|
70955
70955
|
}
|
|
70956
70956
|
async function ensureGreenfieldRepo(cwd, onLog) {
|
|
70957
70957
|
if (await isInsideGitRepo(cwd)) return false;
|
|
70958
|
-
const { readdir } = await import("fs/promises");
|
|
70959
|
-
const entries = (await
|
|
70958
|
+
const { readdir: readdir2 } = await import("fs/promises");
|
|
70959
|
+
const entries = (await readdir2(cwd)).filter(
|
|
70960
70960
|
(name) => name !== ".DS_Store" && name !== "Thumbs.db" && // baro's own pre-branch artifacts don't make a directory a project.
|
|
70961
70961
|
name !== "prd.json" && name !== "baro.lock" && name !== ".baro"
|
|
70962
70962
|
);
|
|
@@ -90624,10 +90624,12 @@ function extractVerdictJson(text3) {
|
|
|
90624
90624
|
}
|
|
90625
90625
|
|
|
90626
90626
|
// ../baro-orchestrator/src/acceptance/critic-evidence.ts
|
|
90627
|
+
import { execFile as execFile4 } from "child_process";
|
|
90627
90628
|
import { createHash as createHash18 } from "crypto";
|
|
90628
90629
|
import { constants as constants2 } from "fs";
|
|
90629
|
-
import { lstat as lstat2, open as open2, readlink, realpath } from "fs/promises";
|
|
90630
|
+
import { lstat as lstat2, open as open2, readdir, readlink, realpath } from "fs/promises";
|
|
90630
90631
|
import { isAbsolute as isAbsolute6, relative as relative7, resolve as resolve11, sep as sep4 } from "path";
|
|
90632
|
+
import { promisify as promisify2 } from "util";
|
|
90631
90633
|
|
|
90632
90634
|
// ../baro-orchestrator/src/runtime/participant-identity.ts
|
|
90633
90635
|
function participantAgentId(source) {
|
|
@@ -90794,6 +90796,110 @@ async function readLineCount(cwd, path7) {
|
|
|
90794
90796
|
return countLines(await readFile(target, "utf8"));
|
|
90795
90797
|
}
|
|
90796
90798
|
|
|
90799
|
+
// ../baro-orchestrator/src/acceptance/content-preserving-command.ts
|
|
90800
|
+
var NOT_PRESERVING = { preserving: false, commits: false };
|
|
90801
|
+
var READ_ONLY = /* @__PURE__ */ new Set([
|
|
90802
|
+
"cd",
|
|
90803
|
+
"pwd",
|
|
90804
|
+
"ls",
|
|
90805
|
+
"cat",
|
|
90806
|
+
"head",
|
|
90807
|
+
"tail",
|
|
90808
|
+
"wc",
|
|
90809
|
+
"grep",
|
|
90810
|
+
"egrep",
|
|
90811
|
+
"fgrep",
|
|
90812
|
+
"rg",
|
|
90813
|
+
"echo",
|
|
90814
|
+
"printf",
|
|
90815
|
+
"true",
|
|
90816
|
+
"test",
|
|
90817
|
+
"[",
|
|
90818
|
+
"stat",
|
|
90819
|
+
"which",
|
|
90820
|
+
"type",
|
|
90821
|
+
"diff",
|
|
90822
|
+
"cmp",
|
|
90823
|
+
"cut",
|
|
90824
|
+
"tr",
|
|
90825
|
+
"basename",
|
|
90826
|
+
"dirname",
|
|
90827
|
+
"realpath",
|
|
90828
|
+
"printenv",
|
|
90829
|
+
"sleep",
|
|
90830
|
+
"jq"
|
|
90831
|
+
]);
|
|
90832
|
+
var GIT_READ_ONLY = /* @__PURE__ */ new Set([
|
|
90833
|
+
"status",
|
|
90834
|
+
"diff",
|
|
90835
|
+
"log",
|
|
90836
|
+
"show",
|
|
90837
|
+
"rev-parse",
|
|
90838
|
+
"ls-files",
|
|
90839
|
+
"ls-tree",
|
|
90840
|
+
"cat-file",
|
|
90841
|
+
"blame",
|
|
90842
|
+
"grep",
|
|
90843
|
+
"describe",
|
|
90844
|
+
"shortlog",
|
|
90845
|
+
"merge-base",
|
|
90846
|
+
"rev-list",
|
|
90847
|
+
"name-rev"
|
|
90848
|
+
]);
|
|
90849
|
+
var GIT_INDEX_ONLY = /* @__PURE__ */ new Set(["add"]);
|
|
90850
|
+
var SHELL_WRAPPER = /^(?:\/(?:usr\/)?bin\/)?(?:ba|z)?sh\s+-l?c\s+(['"])([\s\S]*)\1\s*$/u;
|
|
90851
|
+
var HARMLESS_REDIRECT = /\s*(?:\d?>\s*\/dev\/null|\d>&\d)/gu;
|
|
90852
|
+
var HEREDOC_MESSAGE = /"\$\(cat <<-?\s*(['"])(\w+)\1\n[\s\S]*?\n\s*\2\s*\)"/gu;
|
|
90853
|
+
var SINGLE_QUOTED = /'[^']*'/gu;
|
|
90854
|
+
var DOUBLE_QUOTED = /"(?:[^"\\$`]|\\.)*"/gu;
|
|
90855
|
+
var UNSAFE = /[<>`$"']|\b(?:xargs|tee)\b/u;
|
|
90856
|
+
var UNSAFE_OPTION = /^(?:--output|--pre\b|-O$|--open-files-in-pager|--ext-diff)/u;
|
|
90857
|
+
function contentPreservingCommand(command) {
|
|
90858
|
+
let script = command.trim();
|
|
90859
|
+
const wrapped = SHELL_WRAPPER.exec(script);
|
|
90860
|
+
if (wrapped) script = wrapped[2].trim();
|
|
90861
|
+
script = script.replace(HEREDOC_MESSAGE, "MSG").replace(SINGLE_QUOTED, "Q").replace(DOUBLE_QUOTED, "Q").replace(HARMLESS_REDIRECT, "");
|
|
90862
|
+
if (script === "" || UNSAFE.test(script)) return NOT_PRESERVING;
|
|
90863
|
+
let commits = false;
|
|
90864
|
+
for (const segment of script.split(/&&|\|\||[;|\n]/u)) {
|
|
90865
|
+
const words = segment.trim().split(/\s+/u).filter(Boolean);
|
|
90866
|
+
if (words.length === 0) continue;
|
|
90867
|
+
const [program, ...rest] = words;
|
|
90868
|
+
if (rest.some((w) => UNSAFE_OPTION.test(w))) return NOT_PRESERVING;
|
|
90869
|
+
if (program === "git") {
|
|
90870
|
+
const sub = gitSubcommand(rest);
|
|
90871
|
+
if (sub === null) return NOT_PRESERVING;
|
|
90872
|
+
if (sub === "commit") {
|
|
90873
|
+
commits = true;
|
|
90874
|
+
continue;
|
|
90875
|
+
}
|
|
90876
|
+
if (GIT_READ_ONLY.has(sub) || GIT_INDEX_ONLY.has(sub)) continue;
|
|
90877
|
+
return NOT_PRESERVING;
|
|
90878
|
+
}
|
|
90879
|
+
if (program === "sed") {
|
|
90880
|
+
if (rest.some((w) => /^-[a-zA-Z]*i/u.test(w) || w.startsWith("--in-place"))) return NOT_PRESERVING;
|
|
90881
|
+
if (!rest.includes("-n")) return NOT_PRESERVING;
|
|
90882
|
+
continue;
|
|
90883
|
+
}
|
|
90884
|
+
if (program === "find") {
|
|
90885
|
+
if (rest.some((w) => /^-(?:delete|exec|execdir|ok|okdir|fprint|fprintf|fls)$/u.test(w))) return NOT_PRESERVING;
|
|
90886
|
+
continue;
|
|
90887
|
+
}
|
|
90888
|
+
if (!READ_ONLY.has(program)) return NOT_PRESERVING;
|
|
90889
|
+
}
|
|
90890
|
+
return { preserving: true, commits };
|
|
90891
|
+
}
|
|
90892
|
+
function gitSubcommand(words) {
|
|
90893
|
+
let i2 = 0;
|
|
90894
|
+
while (i2 < words.length && words[i2].startsWith("-")) {
|
|
90895
|
+
const option = words[i2];
|
|
90896
|
+
if (option === "-C") i2 += 2;
|
|
90897
|
+
else if (option === "--no-pager") i2 += 1;
|
|
90898
|
+
else return null;
|
|
90899
|
+
}
|
|
90900
|
+
return words[i2] ?? null;
|
|
90901
|
+
}
|
|
90902
|
+
|
|
90797
90903
|
// ../baro-orchestrator/src/acceptance/critic-evidence.ts
|
|
90798
90904
|
var DEFAULT_GIT_TIMEOUT_MS = 1e4;
|
|
90799
90905
|
var DEFAULT_MAX_DIFF_CHARS = 32e3;
|
|
@@ -90871,6 +90977,9 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
90871
90977
|
pending = /* @__PURE__ */ new Map();
|
|
90872
90978
|
fingerprintTasks = /* @__PURE__ */ new Map();
|
|
90873
90979
|
fallbackRevisions = /* @__PURE__ */ new Map();
|
|
90980
|
+
/** What advanced each revision, so a fingerprint raced only by commands
|
|
90981
|
+
* that cannot change content (git add/commit, git status, reads) is kept. */
|
|
90982
|
+
activity = /* @__PURE__ */ new Map();
|
|
90874
90983
|
onExternalEvent(source, event) {
|
|
90875
90984
|
if (AgentState.is(event) && this.acceptsSource(source, event.payload.agentId) && event.payload.phase === "running" && (event.payload.detail?.startsWith("attempt ") === true || event.payload.detail === "first turn")) {
|
|
90876
90985
|
this.resetAttempt(event.payload.agentId);
|
|
@@ -90881,7 +90990,7 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
90881
90990
|
if (!agentId) return;
|
|
90882
90991
|
if (!this.acceptsSource(source, agentId)) return;
|
|
90883
90992
|
if (isWorkspaceWriteTool(item.name)) {
|
|
90884
|
-
this.advanceFallbackRevision(agentId);
|
|
90993
|
+
this.advanceFallbackRevision(agentId, { preserving: false, commits: false });
|
|
90885
90994
|
return;
|
|
90886
90995
|
}
|
|
90887
90996
|
if (!isShellTool(item.name)) return;
|
|
@@ -90891,7 +91000,7 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
90891
91000
|
existing.command = redactSensitiveText(extractCommand(item.args));
|
|
90892
91001
|
return;
|
|
90893
91002
|
}
|
|
90894
|
-
this.advanceFallbackRevision(agentId);
|
|
91003
|
+
this.advanceFallbackRevision(agentId, contentPreservingCommand(extractCommand(item.args)));
|
|
90895
91004
|
const entry = {
|
|
90896
91005
|
callId: item.callId,
|
|
90897
91006
|
tool: item.name,
|
|
@@ -90985,6 +91094,7 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
90985
91094
|
resetAttempt(agentId) {
|
|
90986
91095
|
this.commands.delete(agentId);
|
|
90987
91096
|
this.fallbackRevisions.delete(agentId);
|
|
91097
|
+
this.activity.delete(agentId);
|
|
90988
91098
|
const prefix = `${agentId}\0`;
|
|
90989
91099
|
for (const key of this.pending.keys()) {
|
|
90990
91100
|
if (key.startsWith(prefix)) this.pending.delete(key);
|
|
@@ -91021,12 +91131,13 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
91021
91131
|
return;
|
|
91022
91132
|
}
|
|
91023
91133
|
const task = (async () => {
|
|
91134
|
+
const resolved = await target;
|
|
91024
91135
|
const fingerprint = await this.fingerprintResolvedTarget(
|
|
91025
|
-
|
|
91136
|
+
resolved,
|
|
91026
91137
|
fallbackRevision
|
|
91027
91138
|
);
|
|
91028
91139
|
const completedRevision = this.fallbackRevisions.get(agentId) ?? 0;
|
|
91029
|
-
entry.fingerprint = completedRevision === fallbackRevision ? fingerprint : {
|
|
91140
|
+
entry.fingerprint = completedRevision === fallbackRevision || await this.onlyContentPreservingSince(agentId, fallbackRevision, completedRevision, resolved) ? fingerprint : {
|
|
91030
91141
|
state: "unavailable",
|
|
91031
91142
|
reason: "shell/write activity advanced while the command fingerprint was being captured"
|
|
91032
91143
|
};
|
|
@@ -91075,11 +91186,32 @@ var CriticCommandEvidenceCollector = class extends BusMember {
|
|
|
91075
91186
|
};
|
|
91076
91187
|
}
|
|
91077
91188
|
}
|
|
91078
|
-
advanceFallbackRevision(agentId) {
|
|
91079
|
-
this.fallbackRevisions.
|
|
91080
|
-
|
|
91081
|
-
|
|
91082
|
-
)
|
|
91189
|
+
advanceFallbackRevision(agentId, kind) {
|
|
91190
|
+
const revision = (this.fallbackRevisions.get(agentId) ?? 0) + 1;
|
|
91191
|
+
this.fallbackRevisions.set(agentId, revision);
|
|
91192
|
+
let log2 = this.activity.get(agentId);
|
|
91193
|
+
if (!log2) {
|
|
91194
|
+
log2 = /* @__PURE__ */ new Map();
|
|
91195
|
+
this.activity.set(agentId, log2);
|
|
91196
|
+
}
|
|
91197
|
+
log2.set(revision, kind);
|
|
91198
|
+
for (const old of log2.keys()) {
|
|
91199
|
+
if (old > revision - MAX_ACTIVITY_LOG) break;
|
|
91200
|
+
log2.delete(old);
|
|
91201
|
+
}
|
|
91202
|
+
}
|
|
91203
|
+
/** True when every activity in (from, to] provably left the working tree
|
|
91204
|
+
* as it was, so a fingerprint taken meanwhile still describes the command. */
|
|
91205
|
+
async onlyContentPreservingSince(agentId, from, to, target) {
|
|
91206
|
+
if (!target) return false;
|
|
91207
|
+
const log2 = this.activity.get(agentId);
|
|
91208
|
+
let commits = false;
|
|
91209
|
+
for (let revision = from + 1; revision <= to; revision++) {
|
|
91210
|
+
const kind = log2?.get(revision);
|
|
91211
|
+
if (!kind?.preserving) return false;
|
|
91212
|
+
commits ||= kind.commits;
|
|
91213
|
+
}
|
|
91214
|
+
return !commits || !await hasCommitHooks(target.cwd);
|
|
91083
91215
|
}
|
|
91084
91216
|
async drainFingerprintTasks(agentId) {
|
|
91085
91217
|
while ((this.fingerprintTasks.get(agentId)?.size ?? 0) > 0) {
|
|
@@ -91945,6 +92077,24 @@ async function collectRepositoryEvidence(target, opts) {
|
|
|
91945
92077
|
renderGitOutput(commits, MAX_LOG_CHARS)
|
|
91946
92078
|
].join("\n");
|
|
91947
92079
|
}
|
|
92080
|
+
var MAX_ACTIVITY_LOG = 256;
|
|
92081
|
+
var execFileAsync = promisify2(execFile4);
|
|
92082
|
+
var COMMIT_HOOKS = /* @__PURE__ */ new Set(["pre-commit", "prepare-commit-msg", "commit-msg", "post-commit"]);
|
|
92083
|
+
async function hasCommitHooks(cwd) {
|
|
92084
|
+
try {
|
|
92085
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--git-path", "hooks"], {
|
|
92086
|
+
cwd: resolve11(cwd),
|
|
92087
|
+
timeout: DEFAULT_GIT_TIMEOUT_MS
|
|
92088
|
+
});
|
|
92089
|
+
const names = await readdir(resolve11(cwd, stdout.trim())).catch((error) => {
|
|
92090
|
+
if (error.code === "ENOENT") return [];
|
|
92091
|
+
throw error;
|
|
92092
|
+
});
|
|
92093
|
+
return names.some((name) => COMMIT_HOOKS.has(name));
|
|
92094
|
+
} catch {
|
|
92095
|
+
return true;
|
|
92096
|
+
}
|
|
92097
|
+
}
|
|
91948
92098
|
async function runGit(cwd, args, timeoutMs) {
|
|
91949
92099
|
const nullDevice = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
91950
92100
|
const hardenedArgs = [
|