@pitboss/cli 0.4.13 → 0.4.14
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.js +98 -61
- package/dist/event-worker.js +16 -10
- package/dist/mcp.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -18006,11 +18006,26 @@ var dist_default7 = createPrompt((config, done) => {
|
|
|
18006
18006
|
// src/config.ts
|
|
18007
18007
|
import { homedir } from "node:os";
|
|
18008
18008
|
import { join, dirname } from "node:path";
|
|
18009
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync, existsSync, renameSync, rmSync as rmSync2, lstatSync, statSync } from "node:fs";
|
|
18009
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync, existsSync, renameSync, rmSync as rmSync2, lstatSync, statSync, readdirSync } from "node:fs";
|
|
18010
18010
|
import { randomBytes } from "node:crypto";
|
|
18011
18011
|
var configDirOverride = () => process.env.PITBOSS_CONFIG_DIR || process.env.RELAI_CONFIG_DIR || void 0;
|
|
18012
|
+
function defaultConfigRoot() {
|
|
18013
|
+
const shipster = join(homedir(), ".config", "shipster");
|
|
18014
|
+
const pitboss = join(homedir(), ".config", "pitboss");
|
|
18015
|
+
if (existsSync(join(shipster, "config.json"))) return shipster;
|
|
18016
|
+
if (existsSync(join(pitboss, "config.json")) || existsSync(join(pitboss, "agents.json"))) return pitboss;
|
|
18017
|
+
if (existsSync(shipster)) return shipster;
|
|
18018
|
+
return dirHasEntries(pitboss) ? pitboss : shipster;
|
|
18019
|
+
}
|
|
18020
|
+
function dirHasEntries(dir) {
|
|
18021
|
+
try {
|
|
18022
|
+
return readdirSync(dir).length > 0;
|
|
18023
|
+
} catch {
|
|
18024
|
+
return false;
|
|
18025
|
+
}
|
|
18026
|
+
}
|
|
18012
18027
|
function configDir() {
|
|
18013
|
-
return configDirOverride() ??
|
|
18028
|
+
return configDirOverride() ?? defaultConfigRoot();
|
|
18014
18029
|
}
|
|
18015
18030
|
function configPath() {
|
|
18016
18031
|
return join(configDir(), "config.json");
|
|
@@ -18984,7 +18999,7 @@ import { join as join4 } from "node:path";
|
|
|
18984
18999
|
|
|
18985
19000
|
// src/lib/wake.ts
|
|
18986
19001
|
import { execFileSync } from "node:child_process";
|
|
18987
|
-
import { mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, realpathSync, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
19002
|
+
import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, readFileSync as readFileSync3, realpathSync, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
18988
19003
|
import { createHash, randomBytes as randomBytes2 } from "node:crypto";
|
|
18989
19004
|
import { join as join2, resolve } from "node:path";
|
|
18990
19005
|
var EVENT_ID = /^evt_[A-Za-z0-9_-]{1,64}$/;
|
|
@@ -19098,7 +19113,7 @@ function resetFollowups(dir, key) {
|
|
|
19098
19113
|
function resetAgentFollowups(dir, agentId) {
|
|
19099
19114
|
let names2;
|
|
19100
19115
|
try {
|
|
19101
|
-
names2 =
|
|
19116
|
+
names2 = readdirSync2(dir);
|
|
19102
19117
|
} catch {
|
|
19103
19118
|
return;
|
|
19104
19119
|
}
|
|
@@ -19128,7 +19143,7 @@ function psCommand(pid) {
|
|
|
19128
19143
|
function watcherAlive(dir, key, { commandOf = psCommand } = {}) {
|
|
19129
19144
|
let names2;
|
|
19130
19145
|
try {
|
|
19131
|
-
names2 =
|
|
19146
|
+
names2 = readdirSync2(dir);
|
|
19132
19147
|
} catch {
|
|
19133
19148
|
return false;
|
|
19134
19149
|
}
|
|
@@ -19833,12 +19848,11 @@ async function cloneFromBase(run4, base2, dest, repoUrl, env2, opts) {
|
|
|
19833
19848
|
}
|
|
19834
19849
|
|
|
19835
19850
|
// src/lib/agents-state.ts
|
|
19836
|
-
import { homedir as homedir3 } from "node:os";
|
|
19837
19851
|
import { join as join5, resolve as resolve2, dirname as dirname2 } from "node:path";
|
|
19838
19852
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3, existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
|
|
19839
19853
|
var stateOverridden = () => Boolean(process.env.PITBOSS_AGENTS_STATE || process.env.RELAI_AGENTS_STATE);
|
|
19840
19854
|
function statePath() {
|
|
19841
|
-
return process.env.PITBOSS_AGENTS_STATE || process.env.RELAI_AGENTS_STATE || join5(
|
|
19855
|
+
return process.env.PITBOSS_AGENTS_STATE || process.env.RELAI_AGENTS_STATE || join5(defaultConfigRoot(), "agents.json");
|
|
19842
19856
|
}
|
|
19843
19857
|
function agentsStatePath() {
|
|
19844
19858
|
return statePath();
|
|
@@ -20188,7 +20202,7 @@ function logoutCommand(opts = {}) {
|
|
|
20188
20202
|
// src/commands/join.ts
|
|
20189
20203
|
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync8, appendFileSync, realpathSync as realpathSync3 } from "node:fs";
|
|
20190
20204
|
import { dirname as dirname5, join as join8 } from "node:path";
|
|
20191
|
-
import { homedir as
|
|
20205
|
+
import { homedir as homedir3 } from "node:os";
|
|
20192
20206
|
|
|
20193
20207
|
// src/lib/mcp-entry.ts
|
|
20194
20208
|
var MCP_SERVER_ENTRY = {
|
|
@@ -20505,7 +20519,7 @@ async function run(opts) {
|
|
|
20505
20519
|
const api = (opts.api ?? DEFAULT_API).replace(/\/+$/, "");
|
|
20506
20520
|
const cwd = process.cwd();
|
|
20507
20521
|
const { root, remote, repoName } = describeRepo(cwd);
|
|
20508
|
-
const home =
|
|
20522
|
+
const home = homedir3();
|
|
20509
20523
|
const host = detectHostRuntime();
|
|
20510
20524
|
console.log(source_default.bold("\npitboss join\n"));
|
|
20511
20525
|
console.log(` Repo ${source_default.cyan(repoName)}${remote ? source_default.dim(` (${remote})`) : ""}`);
|
|
@@ -21586,7 +21600,8 @@ function plannedCount({ budgetMs, workers, baselineMs }) {
|
|
|
21586
21600
|
}
|
|
21587
21601
|
|
|
21588
21602
|
// src/mutate/config.ts
|
|
21589
|
-
var CONFIG_PATH = ".
|
|
21603
|
+
var CONFIG_PATH = ".shipster/mutate.json";
|
|
21604
|
+
var LEGACY_CONFIG_PATH = ".pitboss/mutate.json";
|
|
21590
21605
|
function globToRegExp(glob) {
|
|
21591
21606
|
let out = "";
|
|
21592
21607
|
for (let i = 0; i < glob.length; i++) {
|
|
@@ -21602,30 +21617,30 @@ function globToRegExp(glob) {
|
|
|
21602
21617
|
return new RegExp(`^${out}$`);
|
|
21603
21618
|
}
|
|
21604
21619
|
var strings = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "string" && v.length > 0) : [];
|
|
21605
|
-
function parseMutateConfig(text) {
|
|
21620
|
+
function parseMutateConfig(text, label = CONFIG_PATH) {
|
|
21606
21621
|
const fallback2 = { riskyPatterns: PRIORITY_PATTERNS, paths: [], pool: null };
|
|
21607
21622
|
if (text === null) return fallback2;
|
|
21608
21623
|
let raw;
|
|
21609
21624
|
try {
|
|
21610
21625
|
raw = JSON.parse(text);
|
|
21611
21626
|
} catch {
|
|
21612
|
-
throw new Error(`${
|
|
21627
|
+
throw new Error(`${label} is not valid JSON`);
|
|
21613
21628
|
}
|
|
21614
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new Error(`${
|
|
21629
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new Error(`${label} must be a JSON object`);
|
|
21615
21630
|
const obj = raw;
|
|
21616
21631
|
const risky = strings(obj.risky);
|
|
21617
21632
|
const pool = obj.pool;
|
|
21618
21633
|
let hook2 = null;
|
|
21619
21634
|
if (pool && typeof pool === "object") {
|
|
21620
|
-
if (typeof pool.module !== "string" || pool.module.length === 0) throw new Error(`${
|
|
21635
|
+
if (typeof pool.module !== "string" || pool.module.length === 0) throw new Error(`${label}: pool.module must be a path`);
|
|
21621
21636
|
const workers = typeof pool.workers === "number" && Number.isInteger(pool.workers) && pool.workers >= 1 ? Math.min(pool.workers, 16) : 1;
|
|
21622
21637
|
hook2 = { module: pool.module, workers };
|
|
21623
21638
|
}
|
|
21624
21639
|
return { riskyPatterns: risky.length > 0 ? risky.map(globToRegExp) : PRIORITY_PATTERNS, paths: strings(obj.paths), pool: hook2 };
|
|
21625
21640
|
}
|
|
21626
21641
|
function loadMutateConfig(root) {
|
|
21627
|
-
const
|
|
21628
|
-
return parseMutateConfig(
|
|
21642
|
+
const rel = [CONFIG_PATH, LEGACY_CONFIG_PATH].find((p) => existsSync7(join12(root, p)));
|
|
21643
|
+
return parseMutateConfig(rel ? readFileSync11(join12(root, rel), "utf8") : null, rel ?? CONFIG_PATH);
|
|
21629
21644
|
}
|
|
21630
21645
|
var VITEST_CONFIGS = ["vitest.config.ts", "vitest.config.mts", "vitest.config.js", "vitest.config.mjs"];
|
|
21631
21646
|
function findPackageDir(root, file, exists = existsSync7) {
|
|
@@ -22328,7 +22343,7 @@ async function mutateDiffCommand(opts) {
|
|
|
22328
22343
|
// src/commands/onboard.ts
|
|
22329
22344
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
22330
22345
|
import { accessSync, constants, existsSync as existsSync14, mkdirSync as mkdirSync12, readFileSync as readFileSync16, realpathSync as realpathSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
22331
|
-
import { homedir as
|
|
22346
|
+
import { homedir as homedir6 } from "node:os";
|
|
22332
22347
|
import { delimiter, join as join22 } from "node:path";
|
|
22333
22348
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
22334
22349
|
|
|
@@ -22867,7 +22882,7 @@ var GIT_TIMEOUT_MS = 5e3;
|
|
|
22867
22882
|
var LESSONS_MAX_BUFFER = 64 * 1024;
|
|
22868
22883
|
var TREE_MAX_BUFFER = 32 * 1024 * 1024;
|
|
22869
22884
|
var MAX_TREE_ENTRIES = 2e5;
|
|
22870
|
-
var
|
|
22885
|
+
var LESSONS_PATHS = [".shipster/lessons.md", ".pitboss/lessons.md"];
|
|
22871
22886
|
var BRANCH_RE = /^[A-Za-z0-9._/-]{1,100}$/;
|
|
22872
22887
|
var SHA_RE = /^[0-9a-f]{40}$/;
|
|
22873
22888
|
var BLOB_MODES = /* @__PURE__ */ new Set(["100644", "100755"]);
|
|
@@ -22919,25 +22934,31 @@ function entryFor(repoPath, sha) {
|
|
|
22919
22934
|
}
|
|
22920
22935
|
return entry;
|
|
22921
22936
|
}
|
|
22922
|
-
async function
|
|
22923
|
-
const ref = resolved.sha;
|
|
22937
|
+
async function blobAt(exec4, repoPath, ref, path3) {
|
|
22924
22938
|
let listing;
|
|
22925
22939
|
try {
|
|
22926
|
-
listing = await git2(exec4, repoPath, ["ls-tree", "-z", ref, "--",
|
|
22940
|
+
listing = await git2(exec4, repoPath, ["ls-tree", "-z", ref, "--", path3]);
|
|
22927
22941
|
} catch {
|
|
22928
22942
|
return null;
|
|
22929
22943
|
}
|
|
22930
22944
|
const row = listing.split("\0").find((r) => r !== "");
|
|
22931
|
-
|
|
22932
|
-
|
|
22933
|
-
|
|
22945
|
+
if (!row) return void 0;
|
|
22946
|
+
const match = row.match(/^(\d{6}) (\w+) ([0-9a-f]{40})\t(.+)$/);
|
|
22947
|
+
if (!match || match[4] !== path3 || match[2] !== "blob" || !BLOB_MODES.has(match[1])) return null;
|
|
22934
22948
|
try {
|
|
22935
|
-
|
|
22949
|
+
return await git2(exec4, repoPath, ["cat-file", "blob", match[3]]);
|
|
22936
22950
|
} catch {
|
|
22937
22951
|
return null;
|
|
22938
22952
|
}
|
|
22939
|
-
|
|
22940
|
-
|
|
22953
|
+
}
|
|
22954
|
+
async function readLessons(repoPath, exec4, resolved) {
|
|
22955
|
+
for (const path3 of LESSONS_PATHS) {
|
|
22956
|
+
const text = await blobAt(exec4, repoPath, resolved.sha, path3);
|
|
22957
|
+
if (text === void 0) continue;
|
|
22958
|
+
if (text === null || text.includes("\0")) return null;
|
|
22959
|
+
return { text, branch: resolved.branch, sha: resolved.sha };
|
|
22960
|
+
}
|
|
22961
|
+
return null;
|
|
22941
22962
|
}
|
|
22942
22963
|
async function loadLessons(repoPath, exec4) {
|
|
22943
22964
|
const resolved = await resolveDefaultBranch(repoPath, exec4);
|
|
@@ -23950,7 +23971,7 @@ function grantFromEnv(env2 = process.env) {
|
|
|
23950
23971
|
}
|
|
23951
23972
|
|
|
23952
23973
|
// ../claude-worker/src/capacity-store.ts
|
|
23953
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readdirSync as
|
|
23974
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readdirSync as readdirSync3, readFileSync as readFileSync14, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
23954
23975
|
import { join as join14 } from "node:path";
|
|
23955
23976
|
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
23956
23977
|
|
|
@@ -24043,7 +24064,7 @@ function readCapacity(dir, now) {
|
|
|
24043
24064
|
if (!existsSync9(dir)) return out;
|
|
24044
24065
|
let names2;
|
|
24045
24066
|
try {
|
|
24046
|
-
names2 =
|
|
24067
|
+
names2 = readdirSync3(dir);
|
|
24047
24068
|
} catch {
|
|
24048
24069
|
return out;
|
|
24049
24070
|
}
|
|
@@ -24502,10 +24523,10 @@ var copilotAdapter = {
|
|
|
24502
24523
|
// ../claude-worker/src/adapters/codex.ts
|
|
24503
24524
|
import { spawn as spawn6 } from "child_process";
|
|
24504
24525
|
import { chmodSync, mkdirSync as mkdirSync9, unlinkSync as unlinkSync3, writeFileSync as writeFileSync11 } from "fs";
|
|
24505
|
-
import { homedir as
|
|
24526
|
+
import { homedir as homedir4 } from "os";
|
|
24506
24527
|
import { join as join17 } from "path";
|
|
24507
24528
|
var bin3 = () => process.env.CODEX_BIN ?? "codex";
|
|
24508
|
-
var codexHome = () => process.env.CODEX_HOME ?? join17(
|
|
24529
|
+
var codexHome = () => process.env.CODEX_HOME ?? join17(homedir4(), ".codex");
|
|
24509
24530
|
var QUOTA2 = [/usage limit/i, /rate limit reached for/i, /upgrade to (plus|pro)/i];
|
|
24510
24531
|
var CREDENTIALS = [/not logged in/i, /codex login/i, /401 unauthorized/i];
|
|
24511
24532
|
function codexArgs(repoPath, prompt, profile, model) {
|
|
@@ -24843,7 +24864,7 @@ function originHost(origin) {
|
|
|
24843
24864
|
|
|
24844
24865
|
// src/node/spec.ts
|
|
24845
24866
|
import { existsSync as existsSync11, realpathSync as realpathSync4, statSync as statSync2 } from "node:fs";
|
|
24846
|
-
import { homedir as
|
|
24867
|
+
import { homedir as homedir5 } from "node:os";
|
|
24847
24868
|
import { join as join19, parse as parsePath, resolve as resolve7, sep as sep2 } from "node:path";
|
|
24848
24869
|
var DEFAULT_API2 = "https://api.pitboss.dev";
|
|
24849
24870
|
var MAX_POOL_SIZE = 32;
|
|
@@ -25149,7 +25170,7 @@ function parseSpec(text, specDir, opts = {}) {
|
|
|
25149
25170
|
worktrees.set(a.worktree, a.name);
|
|
25150
25171
|
}
|
|
25151
25172
|
if (body.janitorEnabled !== void 0 && typeof body.janitorEnabled !== "boolean") throw new Error("janitorEnabled must be true or false");
|
|
25152
|
-
const janitor = body.janitorRoots === void 0 ? void 0 : janitorRootsOf(body.janitorRoots, specDir, agents, pools, opts.homeDir ??
|
|
25173
|
+
const janitor = body.janitorRoots === void 0 ? void 0 : janitorRootsOf(body.janitorRoots, specDir, agents, pools, opts.homeDir ?? homedir5());
|
|
25153
25174
|
return {
|
|
25154
25175
|
api: api.replace(/\/+$/, ""),
|
|
25155
25176
|
agents,
|
|
@@ -25161,7 +25182,7 @@ function parseSpec(text, specDir, opts = {}) {
|
|
|
25161
25182
|
}
|
|
25162
25183
|
|
|
25163
25184
|
// src/node/store.ts
|
|
25164
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readdirSync as
|
|
25185
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync10, readdirSync as readdirSync4, readFileSync as readFileSync15, renameSync as renameSync5, rmSync as rmSync6, writeFileSync as writeFileSync12 } from "node:fs";
|
|
25165
25186
|
import { dirname as dirname10, join as join20 } from "node:path";
|
|
25166
25187
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
25167
25188
|
var nodeDir = () => join20(configDir(), "node");
|
|
@@ -25201,7 +25222,7 @@ var removeCreds = (name) => {
|
|
|
25201
25222
|
var listStoredAgentNames = () => {
|
|
25202
25223
|
const dir = join20(nodeDir(), "agents");
|
|
25203
25224
|
if (!existsSync12(dir)) return [];
|
|
25204
|
-
return
|
|
25225
|
+
return readdirSync4(dir).filter((n) => n.endsWith(".json")).map((n) => n.slice(0, -".json".length)).sort();
|
|
25205
25226
|
};
|
|
25206
25227
|
var readState = () => readJson2(statePath2());
|
|
25207
25228
|
function readRetirePending() {
|
|
@@ -25735,7 +25756,7 @@ async function onboardCommand(url, opts) {
|
|
|
25735
25756
|
rl?.close();
|
|
25736
25757
|
}
|
|
25737
25758
|
const plan2 = planOnboard(url, {
|
|
25738
|
-
home:
|
|
25759
|
+
home: homedir6(),
|
|
25739
25760
|
parent: opts.dir,
|
|
25740
25761
|
architect: roles.architect,
|
|
25741
25762
|
writer: roles.writer,
|
|
@@ -25855,10 +25876,10 @@ async function fetchPoolSize(creds, name) {
|
|
|
25855
25876
|
}
|
|
25856
25877
|
|
|
25857
25878
|
// src/node/owner-pool.ts
|
|
25858
|
-
import { chmodSync as chmodSync2, existsSync as existsSync15, lstatSync as lstatSync4, mkdirSync as mkdirSync13, readdirSync as
|
|
25879
|
+
import { chmodSync as chmodSync2, existsSync as existsSync15, lstatSync as lstatSync4, mkdirSync as mkdirSync13, readdirSync as readdirSync5, readFileSync as readFileSync18, realpathSync as realpathSync7, rmSync as rmSync7 } from "node:fs";
|
|
25859
25880
|
import { basename as basename4, dirname as dirname12, join as join24, resolve as resolve9 } from "node:path";
|
|
25860
25881
|
import { execFileSync as execFileSync12, spawnSync as spawnSync2 } from "node:child_process";
|
|
25861
|
-
import { homedir as
|
|
25882
|
+
import { homedir as homedir7 } from "node:os";
|
|
25862
25883
|
|
|
25863
25884
|
// src/node/runas.ts
|
|
25864
25885
|
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
@@ -26049,7 +26070,7 @@ var GIT_ENV_PREFIX = Object.entries(SLOT_GIT_ENV).map(([k, v]) => `${k}=${v}`).j
|
|
|
26049
26070
|
var SEAT_RESET_SCRIPT = `chmod -R u+rwX -- "$1" 2>/dev/null; find "$1" -mindepth 1 -delete && ${GIT_ENV_PREFIX} git ${SLOT_GIT_INIT_ARGS.join(" ")} "$1"`;
|
|
26050
26071
|
var realSlotResetDeps = () => ({
|
|
26051
26072
|
lstat: (path3) => lstatSync4(path3),
|
|
26052
|
-
readdir: (path3) =>
|
|
26073
|
+
readdir: (path3) => readdirSync5(path3),
|
|
26053
26074
|
makeWritable: (path3) => {
|
|
26054
26075
|
chmodSync2(path3, 448);
|
|
26055
26076
|
},
|
|
@@ -26127,7 +26148,7 @@ function probe(cmd, args, env2, timeout) {
|
|
|
26127
26148
|
}
|
|
26128
26149
|
function realAmbientCredentialProbes(env2 = process.env, timeout = 1e4) {
|
|
26129
26150
|
const seat = workerEnv("claude", env2);
|
|
26130
|
-
const home = seat.HOME ??
|
|
26151
|
+
const home = seat.HOME ?? homedir7();
|
|
26131
26152
|
const configHome = seat.XDG_CONFIG_HOME || join24(home, ".config");
|
|
26132
26153
|
return {
|
|
26133
26154
|
ghAuthLoggedIn() {
|
|
@@ -27589,7 +27610,7 @@ function httpLoginApi(creds) {
|
|
|
27589
27610
|
}
|
|
27590
27611
|
|
|
27591
27612
|
// src/node/enroll.ts
|
|
27592
|
-
import { hostname, arch, platform, homedir as
|
|
27613
|
+
import { hostname, arch, platform, homedir as homedir8 } from "node:os";
|
|
27593
27614
|
import { chmodSync as chmodSync5, mkdirSync as mkdirSync18, realpathSync as realpathSync8, rmSync as rmSync11, statSync as statSync3, writeFileSync as writeFileSync17 } from "node:fs";
|
|
27594
27615
|
import { join as join31, parse, resolve as resolve11 } from "node:path";
|
|
27595
27616
|
var EnrollError = class extends Error {
|
|
@@ -27633,9 +27654,9 @@ function prepareRoot(input, seats = false) {
|
|
|
27633
27654
|
const real3 = realpathSync8(wanted);
|
|
27634
27655
|
const home = (() => {
|
|
27635
27656
|
try {
|
|
27636
|
-
return realpathSync8(
|
|
27657
|
+
return realpathSync8(homedir8());
|
|
27637
27658
|
} catch {
|
|
27638
|
-
return
|
|
27659
|
+
return homedir8();
|
|
27639
27660
|
}
|
|
27640
27661
|
})();
|
|
27641
27662
|
if (real3 === parse(real3).root || real3 === home) {
|
|
@@ -28577,7 +28598,7 @@ async function provisionSeatClones(entries, deps) {
|
|
|
28577
28598
|
|
|
28578
28599
|
// src/node/owner-pool-bases.ts
|
|
28579
28600
|
import { execFile as execFile8 } from "node:child_process";
|
|
28580
|
-
import { chmodSync as chmodSync7, existsSync as existsSync22, lstatSync as lstatSync6, mkdirSync as mkdirSync21, readdirSync as
|
|
28601
|
+
import { chmodSync as chmodSync7, existsSync as existsSync22, lstatSync as lstatSync6, mkdirSync as mkdirSync21, readdirSync as readdirSync6, rmSync as rmSync12 } from "node:fs";
|
|
28581
28602
|
import { dirname as dirname19, join as join34 } from "node:path";
|
|
28582
28603
|
import { promisify as promisify3 } from "node:util";
|
|
28583
28604
|
var exec3 = promisify3(execFile8);
|
|
@@ -28755,7 +28776,7 @@ function realOwnerPoolBasesDeps(root, env2 = process.env, tokenHosts = [], log =
|
|
|
28755
28776
|
lockdown,
|
|
28756
28777
|
list() {
|
|
28757
28778
|
try {
|
|
28758
|
-
return
|
|
28779
|
+
return readdirSync6(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
28759
28780
|
} catch {
|
|
28760
28781
|
return [];
|
|
28761
28782
|
}
|
|
@@ -29898,7 +29919,7 @@ function setEnabled(path3, enabled) {
|
|
|
29898
29919
|
}
|
|
29899
29920
|
|
|
29900
29921
|
// src/node/janitor/size.ts
|
|
29901
|
-
import { lstatSync as lstatSync7, readdirSync as
|
|
29922
|
+
import { lstatSync as lstatSync7, readdirSync as readdirSync7 } from "node:fs";
|
|
29902
29923
|
import { join as join39 } from "node:path";
|
|
29903
29924
|
var SIZE_WALK_LIMIT = 5e5;
|
|
29904
29925
|
function diskUsage(path3, limit = SIZE_WALK_LIMIT) {
|
|
@@ -29918,7 +29939,7 @@ function diskUsage(path3, limit = SIZE_WALK_LIMIT) {
|
|
|
29918
29939
|
if (st.isDirectory()) {
|
|
29919
29940
|
let names2;
|
|
29920
29941
|
try {
|
|
29921
|
-
names2 =
|
|
29942
|
+
names2 = readdirSync7(p);
|
|
29922
29943
|
} catch {
|
|
29923
29944
|
continue;
|
|
29924
29945
|
}
|
|
@@ -30182,7 +30203,7 @@ function createDockerClient(run4 = runDocker2) {
|
|
|
30182
30203
|
import { resolve as resolve14, sep as sep5 } from "node:path";
|
|
30183
30204
|
|
|
30184
30205
|
// src/node/janitor/scratch.ts
|
|
30185
|
-
import { lstatSync as lstatSync8, readdirSync as
|
|
30206
|
+
import { lstatSync as lstatSync8, readdirSync as readdirSync8 } from "node:fs";
|
|
30186
30207
|
import { basename as basename5, isAbsolute as isAbsolute3, join as join40, relative as relative3, resolve as resolve13, sep as sep4 } from "node:path";
|
|
30187
30208
|
var SCRATCH_WALK_LIMIT = 2e4;
|
|
30188
30209
|
var GO_BUILD_DIR = "go-build";
|
|
@@ -30205,7 +30226,7 @@ function newestMtime(path3, limit = SCRATCH_WALK_LIMIT, skipVendored = false) {
|
|
|
30205
30226
|
if (st.isDirectory() && !(skipVendored && p !== path3 && (basename5(p) === ".git" || basename5(p) === REBUILDABLE_DIR))) {
|
|
30206
30227
|
let children;
|
|
30207
30228
|
try {
|
|
30208
|
-
children =
|
|
30229
|
+
children = readdirSync8(p);
|
|
30209
30230
|
} catch {
|
|
30210
30231
|
return { ok: false, reason: "unreadable" };
|
|
30211
30232
|
}
|
|
@@ -30221,7 +30242,7 @@ var within = (root, path3) => {
|
|
|
30221
30242
|
};
|
|
30222
30243
|
var names = (dir) => {
|
|
30223
30244
|
try {
|
|
30224
|
-
return
|
|
30245
|
+
return readdirSync8(dir);
|
|
30225
30246
|
} catch {
|
|
30226
30247
|
return [];
|
|
30227
30248
|
}
|
|
@@ -30355,7 +30376,7 @@ function isBusy(path3, agents, now = Date.now(), walkLimit) {
|
|
|
30355
30376
|
|
|
30356
30377
|
// src/node/janitor/worktrees.ts
|
|
30357
30378
|
import { execFile as execFile10 } from "node:child_process";
|
|
30358
|
-
import { existsSync as existsSync24, readdirSync as
|
|
30379
|
+
import { existsSync as existsSync24, readdirSync as readdirSync9, realpathSync as realpathSync11, statSync as statSync6 } from "node:fs";
|
|
30359
30380
|
import { dirname as dirname22, isAbsolute as isAbsolute4, join as join41, relative as relative4, sep as sep6 } from "node:path";
|
|
30360
30381
|
import { promisify as promisify4 } from "node:util";
|
|
30361
30382
|
var execFileP = promisify4(execFile10);
|
|
@@ -30410,7 +30431,7 @@ function defaultAgeOf(now) {
|
|
|
30410
30431
|
function baseClones(root) {
|
|
30411
30432
|
let repos;
|
|
30412
30433
|
try {
|
|
30413
|
-
repos =
|
|
30434
|
+
repos = readdirSync9(root);
|
|
30414
30435
|
} catch {
|
|
30415
30436
|
return [];
|
|
30416
30437
|
}
|
|
@@ -30948,6 +30969,7 @@ import { existsSync as existsSync26, rmSync as rmSync13 } from "node:fs";
|
|
|
30948
30969
|
import { readFileSync as readFileSync25, statSync as statSync9 } from "node:fs";
|
|
30949
30970
|
var ACTIVITY_REPORT_MS = 15e3;
|
|
30950
30971
|
var REVIEW_HEARTBEAT_MS = 6e4;
|
|
30972
|
+
var ACTIVITY_REFRESH_MS = 5 * 6e4;
|
|
30951
30973
|
function sessionFileActive(path3) {
|
|
30952
30974
|
try {
|
|
30953
30975
|
return statSync9(path3).size > 0;
|
|
@@ -31023,6 +31045,10 @@ function needsReport(next, sent) {
|
|
|
31023
31045
|
if (!sent || sent.state !== next.state) return true;
|
|
31024
31046
|
return next.model !== void 0 && next.model !== sent.model;
|
|
31025
31047
|
}
|
|
31048
|
+
function reportDue(next, sent, sentAt, now) {
|
|
31049
|
+
if (needsReport(next, sent)) return true;
|
|
31050
|
+
return sentAt === void 0 || now - sentAt >= ACTIVITY_REFRESH_MS;
|
|
31051
|
+
}
|
|
31026
31052
|
|
|
31027
31053
|
// src/node/desired-seats.ts
|
|
31028
31054
|
var seatWorking = (name) => isRunAsSeat(name) ? sessionFileActive(activityPath(name)) : existsSync26(activityPath(name));
|
|
@@ -31239,6 +31265,7 @@ async function reportActivity(creds, body) {
|
|
|
31239
31265
|
function startActivityLoop(agents, sup, ownerPool = false) {
|
|
31240
31266
|
let busy = false;
|
|
31241
31267
|
const sent = /* @__PURE__ */ new Map();
|
|
31268
|
+
const sentAt = /* @__PURE__ */ new Map();
|
|
31242
31269
|
const beatAt = /* @__PURE__ */ new Map();
|
|
31243
31270
|
const sessions = new SessionEndTracker();
|
|
31244
31271
|
const quota = new QuotaWindows();
|
|
@@ -31299,9 +31326,10 @@ function startActivityLoop(agents, sup, ownerPool = false) {
|
|
|
31299
31326
|
});
|
|
31300
31327
|
await heartbeatReviews(creds, name, live, reviewIds.get(creds.agentId) ?? []);
|
|
31301
31328
|
const body = activityBody(state, readLaunchedModel(activityPath(name)));
|
|
31302
|
-
if (!
|
|
31329
|
+
if (!reportDue(body, sent.get(name), sentAt.get(name), Date.now())) continue;
|
|
31303
31330
|
await reportActivity(creds, body);
|
|
31304
31331
|
sent.set(name, body);
|
|
31332
|
+
sentAt.set(name, Date.now());
|
|
31305
31333
|
}
|
|
31306
31334
|
} catch (err) {
|
|
31307
31335
|
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} activity: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -31960,7 +31988,7 @@ function nodeStatusCommand(opts) {
|
|
|
31960
31988
|
|
|
31961
31989
|
// src/commands/node-service.ts
|
|
31962
31990
|
import { accessSync as accessSync2, chmodSync as chmodSync8, constants as constants2, existsSync as existsSync28, mkdirSync as mkdirSync26, readFileSync as readFileSync28, realpathSync as realpathSync15, statSync as statSync10, unlinkSync as unlinkSync5, writeFileSync as writeFileSync21 } from "node:fs";
|
|
31963
|
-
import { homedir as
|
|
31991
|
+
import { homedir as homedir9, userInfo as userInfo2 } from "node:os";
|
|
31964
31992
|
import { dirname as dirname25, join as join45, resolve as resolve17 } from "node:path";
|
|
31965
31993
|
|
|
31966
31994
|
// src/node/service/identity.ts
|
|
@@ -32198,7 +32226,7 @@ var DEFAULT_PATH = "/usr/bin:/bin:/usr/local/bin";
|
|
|
32198
32226
|
function defaultServiceDeps() {
|
|
32199
32227
|
return {
|
|
32200
32228
|
platform: process.platform,
|
|
32201
|
-
home:
|
|
32229
|
+
home: homedir9(),
|
|
32202
32230
|
configDir: configDir(),
|
|
32203
32231
|
uid: process.getuid?.() ?? 0,
|
|
32204
32232
|
username: userInfo2().username,
|
|
@@ -32472,7 +32500,7 @@ function nodeServiceUninstallCommand() {
|
|
|
32472
32500
|
// src/node/janitor/target.ts
|
|
32473
32501
|
import { readFileSync as readFileSync29 } from "node:fs";
|
|
32474
32502
|
import { dirname as dirname26, isAbsolute as isAbsolute7 } from "node:path";
|
|
32475
|
-
import { homedir as
|
|
32503
|
+
import { homedir as homedir10 } from "node:os";
|
|
32476
32504
|
function resolveJanitorTarget(d) {
|
|
32477
32505
|
let state = null;
|
|
32478
32506
|
try {
|
|
@@ -32484,7 +32512,7 @@ function resolveJanitorTarget(d) {
|
|
|
32484
32512
|
if (specPath !== "" && isAbsolute7(specPath) && !specPath.endsWith("(desired state)")) {
|
|
32485
32513
|
let spec;
|
|
32486
32514
|
try {
|
|
32487
|
-
spec = parseSpec(readFileSync29(specPath, "utf-8"), dirname26(specPath), { homeDir: d.homeDir ??
|
|
32515
|
+
spec = parseSpec(readFileSync29(specPath, "utf-8"), dirname26(specPath), { homeDir: d.homeDir ?? homedir10() });
|
|
32488
32516
|
} catch (e) {
|
|
32489
32517
|
return { ok: false, message: `this node runs from ${specPath}, which cannot be used: ${e.message}. Nothing was cleaned.` };
|
|
32490
32518
|
}
|
|
@@ -33219,7 +33247,8 @@ var requiredCheckExistsCheck = {
|
|
|
33219
33247
|
// src/doctor/checks/risk-config.ts
|
|
33220
33248
|
var MAX_BYTES = 64 * 1024;
|
|
33221
33249
|
var MAX_GLOB = 200;
|
|
33222
|
-
var FIX = "fix or delete .
|
|
33250
|
+
var FIX = "fix or delete .shipster/risk.json (an invalid file makes every order tier 2)";
|
|
33251
|
+
var RISK_FILES = [".shipster/risk.json", ".pitboss/risk.json"];
|
|
33223
33252
|
var TOP_KEYS = /* @__PURE__ */ new Set(["version", "extends", "rules", "ignore"]);
|
|
33224
33253
|
var RULE_KEYS = /* @__PURE__ */ new Set(["id", "paths", "tier"]);
|
|
33225
33254
|
var isObject2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
@@ -33268,9 +33297,17 @@ var riskConfigCheck = {
|
|
|
33268
33297
|
name: "Risk config",
|
|
33269
33298
|
async run(env2) {
|
|
33270
33299
|
const base2 = { id: "risk-config", name: "Risk config" };
|
|
33271
|
-
|
|
33300
|
+
let file = RISK_FILES[0];
|
|
33301
|
+
let text = null;
|
|
33302
|
+
for (const candidate of RISK_FILES) {
|
|
33303
|
+
text = env2.readFile(`${env2.cwd}/${candidate}`);
|
|
33304
|
+
if (text !== null) {
|
|
33305
|
+
file = candidate;
|
|
33306
|
+
break;
|
|
33307
|
+
}
|
|
33308
|
+
}
|
|
33272
33309
|
if (text === null) {
|
|
33273
|
-
return { ...base2, status: "ok", reason: "no .
|
|
33310
|
+
return { ...base2, status: "ok", reason: "no .shipster/risk.json: the default risky-path list is in use", fix: "" };
|
|
33274
33311
|
}
|
|
33275
33312
|
const fail2 = (reason) => ({ ...base2, status: "fail", reason, fix: FIX });
|
|
33276
33313
|
if (Buffer.byteLength(text, "utf8") > MAX_BYTES) return fail2("risk.json is larger than 64 KB");
|
|
@@ -33282,7 +33319,7 @@ var riskConfigCheck = {
|
|
|
33282
33319
|
}
|
|
33283
33320
|
const error = riskConfigError(parsed);
|
|
33284
33321
|
if (error) return fail2(error);
|
|
33285
|
-
return { ...base2, status: "ok", reason:
|
|
33322
|
+
return { ...base2, status: "ok", reason: `committed ${file}`, fix: "" };
|
|
33286
33323
|
}
|
|
33287
33324
|
};
|
|
33288
33325
|
|
package/dist/event-worker.js
CHANGED
|
@@ -535,7 +535,7 @@ var GIT_TIMEOUT_MS = 5e3;
|
|
|
535
535
|
var LESSONS_MAX_BUFFER = 64 * 1024;
|
|
536
536
|
var TREE_MAX_BUFFER = 32 * 1024 * 1024;
|
|
537
537
|
var MAX_TREE_ENTRIES = 2e5;
|
|
538
|
-
var
|
|
538
|
+
var LESSONS_PATHS = [".shipster/lessons.md", ".pitboss/lessons.md"];
|
|
539
539
|
var BRANCH_RE = /^[A-Za-z0-9._/-]{1,100}$/;
|
|
540
540
|
var SHA_RE = /^[0-9a-f]{40}$/;
|
|
541
541
|
var BLOB_MODES = /* @__PURE__ */ new Set(["100644", "100755"]);
|
|
@@ -587,25 +587,31 @@ function entryFor(repoPath, sha) {
|
|
|
587
587
|
}
|
|
588
588
|
return entry;
|
|
589
589
|
}
|
|
590
|
-
async function
|
|
591
|
-
const ref = resolved.sha;
|
|
590
|
+
async function blobAt(exec, repoPath, ref, path) {
|
|
592
591
|
let listing;
|
|
593
592
|
try {
|
|
594
|
-
listing = await git(exec, repoPath, ["ls-tree", "-z", ref, "--",
|
|
593
|
+
listing = await git(exec, repoPath, ["ls-tree", "-z", ref, "--", path]);
|
|
595
594
|
} catch {
|
|
596
595
|
return null;
|
|
597
596
|
}
|
|
598
597
|
const row = listing.split("\0").find((r) => r !== "");
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
598
|
+
if (!row) return void 0;
|
|
599
|
+
const match = row.match(/^(\d{6}) (\w+) ([0-9a-f]{40})\t(.+)$/);
|
|
600
|
+
if (!match || match[4] !== path || match[2] !== "blob" || !BLOB_MODES.has(match[1])) return null;
|
|
602
601
|
try {
|
|
603
|
-
|
|
602
|
+
return await git(exec, repoPath, ["cat-file", "blob", match[3]]);
|
|
604
603
|
} catch {
|
|
605
604
|
return null;
|
|
606
605
|
}
|
|
607
|
-
|
|
608
|
-
|
|
606
|
+
}
|
|
607
|
+
async function readLessons(repoPath, exec, resolved) {
|
|
608
|
+
for (const path of LESSONS_PATHS) {
|
|
609
|
+
const text = await blobAt(exec, repoPath, resolved.sha, path);
|
|
610
|
+
if (text === void 0) continue;
|
|
611
|
+
if (text === null || text.includes("\0")) return null;
|
|
612
|
+
return { text, branch: resolved.branch, sha: resolved.sha };
|
|
613
|
+
}
|
|
614
|
+
return null;
|
|
609
615
|
}
|
|
610
616
|
async function loadLessons(repoPath, exec) {
|
|
611
617
|
const resolved = await resolveDefaultBranch(repoPath, exec);
|
package/dist/mcp.js
CHANGED
|
@@ -12909,7 +12909,7 @@ function buildUpdateOrderTool(client) {
|
|
|
12909
12909
|
function buildCheckOrderRiskTool(client) {
|
|
12910
12910
|
return {
|
|
12911
12911
|
name: "check_order_risk",
|
|
12912
|
-
description: "Derive an order's risk tier from the repo paths its plan will touch, using the repo's own .
|
|
12912
|
+
description: "Derive an order's risk tier from the repo paths its plan will touch, using the repo's own .shipster/risk.json (or the default rules). Returns { tier, riskyPaths, reason, acceptanceSource, acceptance, applied }: build the gate tasks that `acceptance` lists. An order filed with explicit acceptance is unaffected. The server raises the tier later if the diff touches a risky path. For the repo orchestrator and the order's planner.",
|
|
12913
12913
|
inputSchema: external_exports.object({
|
|
12914
12914
|
orderId: external_exports.string().describe("The order id (ord_\u2026)."),
|
|
12915
12915
|
paths: external_exports.array(external_exports.string().min(1)).min(1).max(500).describe("Repo-relative paths the plan will touch (1 to 500).")
|