@brainervirus/workit-cli 8.27.0 → 8.28.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/index.js +326 -155
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -9240,7 +9240,7 @@ var package_default;
|
|
|
9240
9240
|
var init_package = __esm(() => {
|
|
9241
9241
|
package_default = {
|
|
9242
9242
|
name: "@brainervirus/workit-cli",
|
|
9243
|
-
version: "8.
|
|
9243
|
+
version: "8.28.0",
|
|
9244
9244
|
private: false,
|
|
9245
9245
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9246
9246
|
keywords: [
|
|
@@ -9278,13 +9278,13 @@ var init_package = __esm(() => {
|
|
|
9278
9278
|
},
|
|
9279
9279
|
dependencies: {
|
|
9280
9280
|
"@babel/parser": "7.29.9",
|
|
9281
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9281
|
+
"@brainervirus/workit-cursor": "^8.28.0",
|
|
9282
9282
|
"@inkjs/ui": "2.0.0",
|
|
9283
9283
|
ink: "7.1.1",
|
|
9284
9284
|
react: "19.2.8"
|
|
9285
9285
|
},
|
|
9286
9286
|
devDependencies: {
|
|
9287
|
-
"@brainervirus/workit-core": "^8.
|
|
9287
|
+
"@brainervirus/workit-core": "^8.28.0"
|
|
9288
9288
|
},
|
|
9289
9289
|
engines: {
|
|
9290
9290
|
node: ">=24"
|
|
@@ -65551,6 +65551,21 @@ var MODEL_ROLES, MODEL_TIERS, HOST_KEYS, BUILT_IN_CLAUDE_CODE, isObject9 = (valu
|
|
|
65551
65551
|
}
|
|
65552
65552
|
}
|
|
65553
65553
|
return issues;
|
|
65554
|
+
}, roleForAgentType = (agentType, prompt) => {
|
|
65555
|
+
switch (agentType) {
|
|
65556
|
+
case "workit:implementer": {
|
|
65557
|
+
const tier = typeof prompt === "string" ? /^[ \t]*TIER:[ \t]*(mundane|standard|hard)\b/im.exec(prompt)?.[1] : undefined;
|
|
65558
|
+
return { role: "implementer", tier: tier?.toLowerCase() ?? "standard" };
|
|
65559
|
+
}
|
|
65560
|
+
case "workit:verifier":
|
|
65561
|
+
return { role: "verifier" };
|
|
65562
|
+
case "workit:reviewer":
|
|
65563
|
+
return { role: "reviewer" };
|
|
65564
|
+
case "Explore":
|
|
65565
|
+
return { role: "explore" };
|
|
65566
|
+
default:
|
|
65567
|
+
return null;
|
|
65568
|
+
}
|
|
65554
65569
|
};
|
|
65555
65570
|
var init_role_models = __esm(() => {
|
|
65556
65571
|
init_workspaces();
|
|
@@ -67025,6 +67040,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67025
67040
|
return null;
|
|
67026
67041
|
dir = parent;
|
|
67027
67042
|
}
|
|
67043
|
+
}, listClaudeProcesses = () => {
|
|
67044
|
+
const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], { encoding: "utf8", timeout: 5000 });
|
|
67045
|
+
if (r.status !== 0 || typeof r.stdout !== "string")
|
|
67046
|
+
return null;
|
|
67047
|
+
const found = [];
|
|
67048
|
+
for (const row of r.stdout.split(`
|
|
67049
|
+
`)) {
|
|
67050
|
+
const m = /^\s*(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(.*)$/.exec(row);
|
|
67051
|
+
if (!m || !/^(\S*\/)?claude(\s|$)/.test(m[3]))
|
|
67052
|
+
continue;
|
|
67053
|
+
const startedMs = Date.parse(m[2]);
|
|
67054
|
+
if (Number.isFinite(startedMs))
|
|
67055
|
+
found.push({ pid: Number(m[1]), startedMs, args: m[3] });
|
|
67056
|
+
}
|
|
67057
|
+
return found;
|
|
67028
67058
|
}, resolve = (options) => {
|
|
67029
67059
|
const env = options.env ?? process.env;
|
|
67030
67060
|
const home = options.home ?? env.HOME ?? os12.homedir();
|
|
@@ -67052,7 +67082,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67052
67082
|
env,
|
|
67053
67083
|
installer: options.installer ?? false,
|
|
67054
67084
|
cliVersion: options.cliVersion ?? null,
|
|
67055
|
-
scopeProbe: options.scopeProbe ?? probeScope
|
|
67085
|
+
scopeProbe: options.scopeProbe ?? probeScope,
|
|
67086
|
+
claudeProcesses: options.claudeProcesses ?? listClaudeProcesses
|
|
67056
67087
|
};
|
|
67057
67088
|
}, readJson = (p) => {
|
|
67058
67089
|
try {
|
|
@@ -68892,6 +68923,68 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68892
68923
|
fix: repair,
|
|
68893
68924
|
registryProbed
|
|
68894
68925
|
};
|
|
68926
|
+
}, checkClaudeSessionPlugin = (res) => {
|
|
68927
|
+
const id = "claude_session_plugin";
|
|
68928
|
+
if (process.platform === "win32")
|
|
68929
|
+
return {
|
|
68930
|
+
id,
|
|
68931
|
+
status: "info",
|
|
68932
|
+
detail: "running Claude Code sessions are not checked on Windows"
|
|
68933
|
+
};
|
|
68934
|
+
const installs = claudeWorkitInstalls(res.home, res.env, res.cwd).filter((install) => install.version);
|
|
68935
|
+
if (installs.length === 0)
|
|
68936
|
+
return {
|
|
68937
|
+
id,
|
|
68938
|
+
status: "info",
|
|
68939
|
+
detail: "no Workit Claude Code plugin install recorded — skipping"
|
|
68940
|
+
};
|
|
68941
|
+
const registry = readJson(path38.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
|
|
68942
|
+
const recorded = (install) => {
|
|
68943
|
+
const entries = registry?.plugins?.[install.id];
|
|
68944
|
+
const entry = Array.isArray(entries) ? entries.find((e) => e?.installPath === install.installPath) : null;
|
|
68945
|
+
for (const stamp of [entry?.lastUpdated, entry?.installedAt]) {
|
|
68946
|
+
const ms = typeof stamp === "string" ? Date.parse(stamp) : NaN;
|
|
68947
|
+
if (Number.isFinite(ms))
|
|
68948
|
+
return ms;
|
|
68949
|
+
}
|
|
68950
|
+
try {
|
|
68951
|
+
return statSync6(install.installPath).mtimeMs;
|
|
68952
|
+
} catch {
|
|
68953
|
+
return null;
|
|
68954
|
+
}
|
|
68955
|
+
};
|
|
68956
|
+
const latest = installs.map((install) => ({ install, at: recorded(install) })).filter((one) => one.at !== null).toSorted((a, b) => b.at - a.at)[0];
|
|
68957
|
+
if (!latest)
|
|
68958
|
+
return {
|
|
68959
|
+
id,
|
|
68960
|
+
status: "info",
|
|
68961
|
+
detail: "no install time recorded for the Workit plugin — skipping"
|
|
68962
|
+
};
|
|
68963
|
+
const running = res.claudeProcesses();
|
|
68964
|
+
if (running === null)
|
|
68965
|
+
return {
|
|
68966
|
+
id,
|
|
68967
|
+
status: "info",
|
|
68968
|
+
detail: "could not list running claude processes (ps) — skipping"
|
|
68969
|
+
};
|
|
68970
|
+
const stale = running.filter((proc) => proc.startedMs < latest.at);
|
|
68971
|
+
if (stale.length === 0)
|
|
68972
|
+
return {
|
|
68973
|
+
id,
|
|
68974
|
+
status: "info",
|
|
68975
|
+
detail: `${running.length} running claude process(es), none started before Workit ${latest.install.version} was installed`
|
|
68976
|
+
};
|
|
68977
|
+
const sessionOf = (args) => /(?:--resume|--session-id|-r)[ =]([0-9a-f]{8}-[0-9a-f-]{27})/i.exec(args)?.[1] ?? null;
|
|
68978
|
+
const rows = stale.map((proc) => {
|
|
68979
|
+
const session = sessionOf(proc.args);
|
|
68980
|
+
return `pid ${proc.pid} started ${new Date(proc.startedMs).toISOString()}${session ? ` (session ${session})` : ""}`;
|
|
68981
|
+
});
|
|
68982
|
+
const first = stale.map((proc) => sessionOf(proc.args)).find((one) => one);
|
|
68983
|
+
return {
|
|
68984
|
+
id,
|
|
68985
|
+
status: "warn",
|
|
68986
|
+
detail: `started before Workit ${latest.install.version} was installed: ${rows.join("; ")}; quit and start \`claude --resume ${first ?? "<session id>"}\` to load it (\`/resume\` keeps the old plugin)`
|
|
68987
|
+
};
|
|
68895
68988
|
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
|
|
68896
68989
|
let files;
|
|
68897
68990
|
try {
|
|
@@ -69093,6 +69186,7 @@ var init_doctor = __esm(() => {
|
|
|
69093
69186
|
checkPiExtension,
|
|
69094
69187
|
checkOpencodeVersion,
|
|
69095
69188
|
checkClaudePlugin,
|
|
69189
|
+
checkClaudeSessionPlugin,
|
|
69096
69190
|
checkHookIssuedSessions,
|
|
69097
69191
|
checkWorkitOnPath,
|
|
69098
69192
|
checkAssets,
|
|
@@ -77403,6 +77497,9 @@ var exports_models = {};
|
|
|
77403
77497
|
__export(exports_models, {
|
|
77404
77498
|
run: () => run13
|
|
77405
77499
|
});
|
|
77500
|
+
import { existsSync as existsSync21, readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync9 } from "node:fs";
|
|
77501
|
+
import os21 from "node:os";
|
|
77502
|
+
import path51 from "node:path";
|
|
77406
77503
|
async function run13(argv, io) {
|
|
77407
77504
|
const [sub, ...args] = argv.filter((arg) => arg !== "--json");
|
|
77408
77505
|
if (sub !== "show")
|
|
@@ -77410,13 +77507,27 @@ async function run13(argv, io) {
|
|
|
77410
77507
|
const role = flag3(args, "--role");
|
|
77411
77508
|
const tier = flag3(args, "--tier");
|
|
77412
77509
|
const hostFlag = flag3(args, "--host");
|
|
77413
|
-
|
|
77510
|
+
const daysFlag = flag3(args, "--days");
|
|
77511
|
+
for (const value of [role, tier, hostFlag, daysFlag])
|
|
77414
77512
|
if (value instanceof Error)
|
|
77415
77513
|
return emit(io, fail2("invalid_input", value.message));
|
|
77416
77514
|
if (role && !MODEL_ROLES.includes(role))
|
|
77417
77515
|
return emit(io, fail2("invalid_input", `unknown role ${role}: ${MODEL_ROLES.join(", ")}`));
|
|
77418
77516
|
if (tier && !MODEL_TIERS.includes(tier))
|
|
77419
77517
|
return emit(io, fail2("invalid_input", `unknown tier ${tier}: ${MODEL_TIERS.join(", ")}`));
|
|
77518
|
+
const days = daysFlag === null ? 7 : Number(daysFlag);
|
|
77519
|
+
if (!Number.isFinite(days) || days <= 0)
|
|
77520
|
+
return emit(io, fail2("invalid_input", "--days needs a positive number"));
|
|
77521
|
+
if (args.includes("--report")) {
|
|
77522
|
+
const report = usageReport(io.cwd, io.env, days);
|
|
77523
|
+
return emit(io, ok2(report), (data) => [
|
|
77524
|
+
`subagent models over the last ${data.days} days (${data.agents} agents)`,
|
|
77525
|
+
...Object.entries(data.types).flatMap(([type, use]) => [
|
|
77526
|
+
` ${type}${use.role ? ` (role ${use.role}, default ${use.defaults.join("/") || "host default"})` : ""}: ${Object.entries(use.models).map(([model, count]) => `${model} x${count}`).join(", ")}`,
|
|
77527
|
+
...use.flagged.map((model) => ` flag: ran on ${model}, not the role default`)
|
|
77528
|
+
])
|
|
77529
|
+
]);
|
|
77530
|
+
}
|
|
77420
77531
|
const envHost = actorFromEnv(io.env).host;
|
|
77421
77532
|
const host = hostFlag ?? (envHost === "cli" ? "claude_code" : envHost);
|
|
77422
77533
|
const row = (selector) => resolveRoleModel(io.cwd, selector, host) ?? { model: null, effort: null, source: "none" };
|
|
@@ -77439,13 +77550,73 @@ async function run13(argv, io) {
|
|
|
77439
77550
|
...(data.issues ?? []).map((issue) => `note: ${issue}`)
|
|
77440
77551
|
]);
|
|
77441
77552
|
}
|
|
77442
|
-
var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--json]", flag3 = (argv, name) => {
|
|
77553
|
+
var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--report [--days <n>]] [--json]", flag3 = (argv, name) => {
|
|
77443
77554
|
const at = argv.findIndex((arg) => arg === name || arg.startsWith(`${name}=`));
|
|
77444
77555
|
if (at < 0)
|
|
77445
77556
|
return null;
|
|
77446
77557
|
const value = argv[at].includes("=") ? argv[at].slice(name.length + 1) : argv[at + 1];
|
|
77447
77558
|
return value && !value.startsWith("--") ? value : new Error(`${name} needs a value`);
|
|
77448
|
-
}, line2 = (label, entry) => ` ${label}: ${entry.model ? `${entry.model}${entry.effort ? ` (effort ${entry.effort})` : ""} [${entry.source}]` : "host default (nothing configured)"}
|
|
77559
|
+
}, line2 = (label, entry) => ` ${label}: ${entry.model ? `${entry.model}${entry.effort ? ` (effort ${entry.effort})` : ""} [${entry.source}]` : "host default (nothing configured)"}`, modelsOf = (file) => {
|
|
77560
|
+
const found = new Set;
|
|
77561
|
+
let text = "";
|
|
77562
|
+
try {
|
|
77563
|
+
text = readFileSync21(file, "utf8");
|
|
77564
|
+
} catch {
|
|
77565
|
+
return found;
|
|
77566
|
+
}
|
|
77567
|
+
for (const row of text.split(`
|
|
77568
|
+
`))
|
|
77569
|
+
if (row.includes('"type":"assistant"'))
|
|
77570
|
+
try {
|
|
77571
|
+
const model = JSON.parse(row).message?.model;
|
|
77572
|
+
if (typeof model === "string" && model && !model.startsWith("<"))
|
|
77573
|
+
found.add(model);
|
|
77574
|
+
} catch {}
|
|
77575
|
+
return found;
|
|
77576
|
+
}, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
|
|
77577
|
+
const projects = path51.join(env.CLAUDE_CONFIG_DIR || path51.join(env.HOME || os21.homedir(), ".claude"), "projects");
|
|
77578
|
+
const since = Date.now() - days * 86400000;
|
|
77579
|
+
const types = {};
|
|
77580
|
+
let agents = 0;
|
|
77581
|
+
const dirs = (dir) => {
|
|
77582
|
+
try {
|
|
77583
|
+
return readdirSync10(dir).map((name) => path51.join(dir, name));
|
|
77584
|
+
} catch {
|
|
77585
|
+
return [];
|
|
77586
|
+
}
|
|
77587
|
+
};
|
|
77588
|
+
for (const project of dirs(projects))
|
|
77589
|
+
for (const session of dirs(project))
|
|
77590
|
+
for (const meta of dirs(path51.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
|
|
77591
|
+
try {
|
|
77592
|
+
if (statSync9(meta).mtimeMs < since)
|
|
77593
|
+
continue;
|
|
77594
|
+
const agentType = JSON.parse(readFileSync21(meta, "utf8")).agentType;
|
|
77595
|
+
const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
|
|
77596
|
+
if (typeof agentType !== "string" || !existsSync21(transcript))
|
|
77597
|
+
continue;
|
|
77598
|
+
const ran = modelsOf(transcript);
|
|
77599
|
+
if (!ran.size)
|
|
77600
|
+
continue;
|
|
77601
|
+
agents += 1;
|
|
77602
|
+
const selector = roleForAgentType(agentType);
|
|
77603
|
+
const entry = types[agentType] ??= {
|
|
77604
|
+
role: selector?.role ?? null,
|
|
77605
|
+
defaults: selector ? [
|
|
77606
|
+
...new Set((selector.role === "implementer" ? MODEL_TIERS.map((tier) => ({ ...selector, tier })) : [selector]).flatMap((one) => resolveRoleModel(cwd, one, "claude_code")?.model ?? []))
|
|
77607
|
+
] : [],
|
|
77608
|
+
models: {},
|
|
77609
|
+
flagged: []
|
|
77610
|
+
};
|
|
77611
|
+
for (const model of ran) {
|
|
77612
|
+
entry.models[model] = (entry.models[model] ?? 0) + 1;
|
|
77613
|
+
if (entry.models[model] === 1 && entry.defaults.length && !entry.defaults.some((d) => matches3(model, d)))
|
|
77614
|
+
entry.flagged.push(model);
|
|
77615
|
+
}
|
|
77616
|
+
} catch {}
|
|
77617
|
+
}
|
|
77618
|
+
return { days, agents, types };
|
|
77619
|
+
};
|
|
77449
77620
|
var init_models = __esm(() => {
|
|
77450
77621
|
init_role_models();
|
|
77451
77622
|
init_ledger();
|
|
@@ -77561,8 +77732,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
77561
77732
|
|
|
77562
77733
|
// packages/workit-core/src/git/ops.ts
|
|
77563
77734
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
77564
|
-
import { existsSync as
|
|
77565
|
-
import
|
|
77735
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
|
|
77736
|
+
import path52 from "node:path";
|
|
77566
77737
|
function operationInProgress(cwd) {
|
|
77567
77738
|
const markers = [
|
|
77568
77739
|
["rebase-merge", "rebase"],
|
|
@@ -77575,18 +77746,18 @@ function operationInProgress(cwd) {
|
|
|
77575
77746
|
if (!run.ok)
|
|
77576
77747
|
return null;
|
|
77577
77748
|
const found = run.stdout.split(`
|
|
77578
|
-
`).map((line) =>
|
|
77749
|
+
`).map((line) => path52.resolve(cwd, line.trim()));
|
|
77579
77750
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
77580
77751
|
for (const [index, [, operation]] of markers.entries()) {
|
|
77581
77752
|
const marker = found[index];
|
|
77582
|
-
if (!marker || !
|
|
77753
|
+
if (!marker || !existsSync22(marker))
|
|
77583
77754
|
continue;
|
|
77584
|
-
if (index === 1 &&
|
|
77755
|
+
if (index === 1 && existsSync22(path52.join(marker, "applying")))
|
|
77585
77756
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
77586
|
-
if (index === 0 &&
|
|
77757
|
+
if (index === 0 && existsSync22(path52.join(marker, "amend")) && !conflicted()) {
|
|
77587
77758
|
let headName = "";
|
|
77588
77759
|
try {
|
|
77589
|
-
headName =
|
|
77760
|
+
headName = readFileSync22(path52.join(marker, "head-name"), "utf8").trim();
|
|
77590
77761
|
} catch {}
|
|
77591
77762
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
77592
77763
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -77914,7 +78085,7 @@ function gitCommit(cwd, input) {
|
|
|
77914
78085
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
77915
78086
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
77916
78087
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
77917
|
-
const addable = paths.filter((value) =>
|
|
78088
|
+
const addable = paths.filter((value) => existsSync22(path52.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
77918
78089
|
if (addable.length) {
|
|
77919
78090
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
77920
78091
|
if (!added.ok)
|
|
@@ -78441,12 +78612,12 @@ var init_ops = __esm(() => {
|
|
|
78441
78612
|
|
|
78442
78613
|
// packages/workit-core/src/verdict-cover.ts
|
|
78443
78614
|
import fs26 from "node:fs";
|
|
78444
|
-
import
|
|
78615
|
+
import path53 from "node:path";
|
|
78445
78616
|
function chainsAbove(cwd, branch) {
|
|
78446
78617
|
const root = storeRoot(cwd);
|
|
78447
78618
|
if (!root.ok)
|
|
78448
78619
|
return [];
|
|
78449
|
-
const dir =
|
|
78620
|
+
const dir = path53.join(root.value.root, "stacks");
|
|
78450
78621
|
let names = [];
|
|
78451
78622
|
try {
|
|
78452
78623
|
names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
@@ -78457,7 +78628,7 @@ function chainsAbove(cwd, branch) {
|
|
|
78457
78628
|
for (const name of names.toSorted()) {
|
|
78458
78629
|
let parsed;
|
|
78459
78630
|
try {
|
|
78460
|
-
parsed = JSON.parse(fs26.readFileSync(
|
|
78631
|
+
parsed = JSON.parse(fs26.readFileSync(path53.join(dir, name), "utf8"));
|
|
78461
78632
|
} catch {
|
|
78462
78633
|
continue;
|
|
78463
78634
|
}
|
|
@@ -78552,10 +78723,10 @@ var init_pr_lane = __esm(() => {
|
|
|
78552
78723
|
|
|
78553
78724
|
// packages/workit-core/src/forge/reruns.ts
|
|
78554
78725
|
import fs27 from "node:fs";
|
|
78555
|
-
import
|
|
78726
|
+
import path54 from "node:path";
|
|
78556
78727
|
function rerunLogPath(cwd) {
|
|
78557
78728
|
const common = gitCommonDir(cwd);
|
|
78558
|
-
return common ?
|
|
78729
|
+
return common ? path54.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
78559
78730
|
}
|
|
78560
78731
|
function rerunCounts(cwd, key) {
|
|
78561
78732
|
const counts = new Map;
|
|
@@ -78590,7 +78761,7 @@ function recordReruns(cwd, rows) {
|
|
|
78590
78761
|
if (!file)
|
|
78591
78762
|
return false;
|
|
78592
78763
|
try {
|
|
78593
|
-
fs27.mkdirSync(
|
|
78764
|
+
fs27.mkdirSync(path54.dirname(file), { recursive: true });
|
|
78594
78765
|
fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
78595
78766
|
`).join(""));
|
|
78596
78767
|
return true;
|
|
@@ -78603,7 +78774,7 @@ function withRerunLock(cwd, fn) {
|
|
|
78603
78774
|
if (!file)
|
|
78604
78775
|
return fn();
|
|
78605
78776
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
78606
|
-
fs27.mkdirSync(
|
|
78777
|
+
fs27.mkdirSync(path54.dirname(lock), { recursive: true });
|
|
78607
78778
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
78608
78779
|
for (;; ) {
|
|
78609
78780
|
try {
|
|
@@ -79518,7 +79689,7 @@ var init_pr_ops = __esm(() => {
|
|
|
79518
79689
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
79519
79690
|
import { createHash as createHash17, randomBytes as randomBytes4 } from "node:crypto";
|
|
79520
79691
|
import fs28 from "node:fs";
|
|
79521
|
-
import
|
|
79692
|
+
import path55 from "node:path";
|
|
79522
79693
|
function worktreeOf(cwd, branch) {
|
|
79523
79694
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
79524
79695
|
if (!list.ok)
|
|
@@ -79562,7 +79733,7 @@ function gitRestack(cwd, input) {
|
|
|
79562
79733
|
if (!scratch)
|
|
79563
79734
|
return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
|
|
79564
79735
|
fs28.mkdirSync(scratch, { recursive: true });
|
|
79565
|
-
dir =
|
|
79736
|
+
dir = path55.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
79566
79737
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
79567
79738
|
if (!added.ok)
|
|
79568
79739
|
return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
|
|
@@ -79603,7 +79774,7 @@ function pruneScratch(cwd) {
|
|
|
79603
79774
|
if (!scratch || !fs28.existsSync(scratch))
|
|
79604
79775
|
return;
|
|
79605
79776
|
for (const name of fs28.readdirSync(scratch)) {
|
|
79606
|
-
const dir =
|
|
79777
|
+
const dir = path55.join(scratch, name);
|
|
79607
79778
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
79608
79779
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
79609
79780
|
}
|
|
@@ -79613,7 +79784,7 @@ function stacksDir(cwd) {
|
|
|
79613
79784
|
const root = storeRoot(cwd);
|
|
79614
79785
|
if (!root.ok)
|
|
79615
79786
|
return stackFail(root.code, root.error, root.unblock);
|
|
79616
|
-
return { ok: true, data:
|
|
79787
|
+
return { ok: true, data: path55.join(root.value.root, "stacks") };
|
|
79617
79788
|
}
|
|
79618
79789
|
function parseStack(raw) {
|
|
79619
79790
|
if (!isRecord12(raw) || !Array.isArray(raw.branches))
|
|
@@ -79665,7 +79836,7 @@ function readStack(cwd, name) {
|
|
|
79665
79836
|
const dir = stacksDir(cwd);
|
|
79666
79837
|
if (!dir.ok)
|
|
79667
79838
|
return dir;
|
|
79668
|
-
const file =
|
|
79839
|
+
const file = path55.join(dir.data, fileFor(name));
|
|
79669
79840
|
let text;
|
|
79670
79841
|
try {
|
|
79671
79842
|
text = fs28.readFileSync(file, "utf8");
|
|
@@ -79686,7 +79857,7 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
79686
79857
|
const dir = stacksDir(cwd);
|
|
79687
79858
|
if (!dir.ok)
|
|
79688
79859
|
return dir;
|
|
79689
|
-
const file =
|
|
79860
|
+
const file = path55.join(dir.data, fileFor(stack.name));
|
|
79690
79861
|
const temp = `${file}.${process.pid}.tmp`;
|
|
79691
79862
|
try {
|
|
79692
79863
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
@@ -79714,7 +79885,7 @@ function listStacks(cwd) {
|
|
|
79714
79885
|
for (const name of names) {
|
|
79715
79886
|
let parsed = null;
|
|
79716
79887
|
try {
|
|
79717
|
-
parsed = parseStack(JSON.parse(fs28.readFileSync(
|
|
79888
|
+
parsed = parseStack(JSON.parse(fs28.readFileSync(path55.join(dir.data, name), "utf8")));
|
|
79718
79889
|
} catch {
|
|
79719
79890
|
parsed = null;
|
|
79720
79891
|
}
|
|
@@ -79773,7 +79944,7 @@ function takeLock(lock) {
|
|
|
79773
79944
|
host: localLockHost(),
|
|
79774
79945
|
nonce: randomBytes4(8).toString("hex")
|
|
79775
79946
|
};
|
|
79776
|
-
fs28.writeFileSync(
|
|
79947
|
+
fs28.writeFileSync(path55.join(lock, OWNER), JSON.stringify(owner));
|
|
79777
79948
|
return owner;
|
|
79778
79949
|
}
|
|
79779
79950
|
function reapLock(lock, observed) {
|
|
@@ -79810,7 +79981,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
79810
79981
|
return dir;
|
|
79811
79982
|
if (!validName(name))
|
|
79812
79983
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
79813
|
-
const lock =
|
|
79984
|
+
const lock = path55.join(dir.data, `${fileFor(name)}.lock`);
|
|
79814
79985
|
try {
|
|
79815
79986
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
79816
79987
|
} catch (error) {
|
|
@@ -79840,7 +80011,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
79840
80011
|
const touch = () => {
|
|
79841
80012
|
try {
|
|
79842
80013
|
const now = new Date;
|
|
79843
|
-
fs28.utimesSync(
|
|
80014
|
+
fs28.utimesSync(path55.join(lock, OWNER), now, now);
|
|
79844
80015
|
} catch {}
|
|
79845
80016
|
};
|
|
79846
80017
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -80691,7 +80862,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
80691
80862
|
return !status.ok || status.stdout.trim() !== "";
|
|
80692
80863
|
}, scratchDir = (cwd) => {
|
|
80693
80864
|
const dir = stacksDir(cwd);
|
|
80694
|
-
return dir.ok ?
|
|
80865
|
+
return dir.ok ? path55.join(dir.data, "worktrees") : null;
|
|
80695
80866
|
}, firstLine = (run) => (`${run.stderr}
|
|
80696
80867
|
${run.stdout}`.split(`
|
|
80697
80868
|
`).find((line) => line.trim()) ?? "git failed").trim().slice(0, 300), stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${createHash17("sha256").update(name).digest("hex").slice(0, 12)}.json`, fileFor, validName = (name) => {
|
|
@@ -80706,12 +80877,12 @@ ${run.stdout}`.split(`
|
|
|
80706
80877
|
}, isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), str3 = (value) => typeof value === "string" && value ? value : null, LOCK_WAIT_MS3 = 2000, HEARTBEAT_MS = 20000, HEARTBEAT_STALE_MS, OWNERLESS_STALE_MS = 30000, OWNER = "owner", readOwner = (lock) => {
|
|
80707
80878
|
let raw = null;
|
|
80708
80879
|
try {
|
|
80709
|
-
raw = fs28.readFileSync(
|
|
80880
|
+
raw = fs28.readFileSync(path55.join(lock, OWNER), "utf8");
|
|
80710
80881
|
} catch {
|
|
80711
80882
|
raw = null;
|
|
80712
80883
|
}
|
|
80713
80884
|
let age = null;
|
|
80714
|
-
for (const target of [
|
|
80885
|
+
for (const target of [path55.join(lock, OWNER), lock])
|
|
80715
80886
|
try {
|
|
80716
80887
|
age = Date.now() - fs28.statSync(target).mtimeMs;
|
|
80717
80888
|
break;
|
|
@@ -80754,7 +80925,7 @@ var init_stack = __esm(() => {
|
|
|
80754
80925
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
80755
80926
|
import { createHash as createHash18 } from "node:crypto";
|
|
80756
80927
|
import fs29 from "node:fs";
|
|
80757
|
-
import
|
|
80928
|
+
import path56 from "node:path";
|
|
80758
80929
|
function expandBraces2(pattern, limit = 64) {
|
|
80759
80930
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
80760
80931
|
if (pattern[index] === "\\") {
|
|
@@ -81000,7 +81171,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
81000
81171
|
id,
|
|
81001
81172
|
branch,
|
|
81002
81173
|
base: optional("base") ?? "",
|
|
81003
|
-
worktree:
|
|
81174
|
+
worktree: path56.resolve(defaults.root, optional("worktree") ?? path56.join(defaults.worktreeRoot, id)),
|
|
81004
81175
|
tier,
|
|
81005
81176
|
reason,
|
|
81006
81177
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
@@ -81231,11 +81402,11 @@ function defaultTrunk(cwd) {
|
|
|
81231
81402
|
}
|
|
81232
81403
|
function mainCheckout(cwd) {
|
|
81233
81404
|
const common = gitCommonDir(cwd);
|
|
81234
|
-
return common &&
|
|
81405
|
+
return common && path56.basename(common) === ".git" ? path56.dirname(common) : path56.resolve(cwd);
|
|
81235
81406
|
}
|
|
81236
81407
|
function worktreeRoot(cwd) {
|
|
81237
81408
|
const main = mainCheckout(cwd);
|
|
81238
|
-
return
|
|
81409
|
+
return path56.join(path56.dirname(main), `${path56.basename(main)}-wt`);
|
|
81239
81410
|
}
|
|
81240
81411
|
function sliceHash(slice) {
|
|
81241
81412
|
const {
|
|
@@ -81255,7 +81426,7 @@ function fanoutsDir(cwd) {
|
|
|
81255
81426
|
const root = storeRoot(cwd);
|
|
81256
81427
|
if (!root.ok)
|
|
81257
81428
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
81258
|
-
return { ok: true, data:
|
|
81429
|
+
return { ok: true, data: path56.join(root.value.root, "fanouts") };
|
|
81259
81430
|
}
|
|
81260
81431
|
function parseStored(raw) {
|
|
81261
81432
|
if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -81323,7 +81494,7 @@ function readFanout(cwd, name) {
|
|
|
81323
81494
|
const dir = fanoutsDir(cwd);
|
|
81324
81495
|
if (!dir.ok)
|
|
81325
81496
|
return dir;
|
|
81326
|
-
const file =
|
|
81497
|
+
const file = path56.join(dir.data, stackFileName(name));
|
|
81327
81498
|
let parsed = null;
|
|
81328
81499
|
try {
|
|
81329
81500
|
parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
|
|
@@ -81348,7 +81519,7 @@ function listFanouts(cwd) {
|
|
|
81348
81519
|
for (const entry of names) {
|
|
81349
81520
|
let parsed = null;
|
|
81350
81521
|
try {
|
|
81351
|
-
parsed = parseStored(JSON.parse(fs29.readFileSync(
|
|
81522
|
+
parsed = parseStored(JSON.parse(fs29.readFileSync(path56.join(dir.data, entry), "utf8")));
|
|
81352
81523
|
} catch {
|
|
81353
81524
|
parsed = null;
|
|
81354
81525
|
}
|
|
@@ -81387,7 +81558,7 @@ function writeFanout(cwd, plan) {
|
|
|
81387
81558
|
const dir = fanoutsDir(cwd);
|
|
81388
81559
|
if (!dir.ok)
|
|
81389
81560
|
return dir;
|
|
81390
|
-
const file =
|
|
81561
|
+
const file = path56.join(dir.data, stackFileName(plan.name));
|
|
81391
81562
|
const temp = `${file}.${process.pid}.tmp`;
|
|
81392
81563
|
try {
|
|
81393
81564
|
fs29.mkdirSync(dir.data, { recursive: true });
|
|
@@ -81594,13 +81765,13 @@ var init_fanout = __esm(() => {
|
|
|
81594
81765
|
// packages/workit-core/src/forge/exec.ts
|
|
81595
81766
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
81596
81767
|
import fs30 from "node:fs";
|
|
81597
|
-
import
|
|
81768
|
+
import path57 from "node:path";
|
|
81598
81769
|
function findExecutable(bin, env) {
|
|
81599
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
81770
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path57.delimiter).filter(Boolean);
|
|
81600
81771
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
81601
81772
|
for (const dir of dirs)
|
|
81602
81773
|
for (const ext of exts) {
|
|
81603
|
-
const candidate =
|
|
81774
|
+
const candidate = path57.join(dir, `${bin}${ext}`);
|
|
81604
81775
|
try {
|
|
81605
81776
|
const stat = fs30.statSync(candidate);
|
|
81606
81777
|
if (stat.isFile())
|
|
@@ -83344,7 +83515,7 @@ var init_duration = __esm(() => {
|
|
|
83344
83515
|
});
|
|
83345
83516
|
|
|
83346
83517
|
// packages/workit-cli/src/verbs/forge-common.ts
|
|
83347
|
-
import { readFileSync as
|
|
83518
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
83348
83519
|
function parseFlags(argv, spec) {
|
|
83349
83520
|
const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
|
|
83350
83521
|
for (let index = 0;index < argv.length; index += 1) {
|
|
@@ -83488,7 +83659,7 @@ var init_forge_common = __esm(() => {
|
|
|
83488
83659
|
forgeDeps = {
|
|
83489
83660
|
runner: undefined,
|
|
83490
83661
|
npm: undefined,
|
|
83491
|
-
readStdin: () =>
|
|
83662
|
+
readStdin: () => readFileSync23(0, "utf8"),
|
|
83492
83663
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
83493
83664
|
now: () => Date.now()
|
|
83494
83665
|
};
|
|
@@ -83499,12 +83670,12 @@ var exports_pr = {};
|
|
|
83499
83670
|
__export(exports_pr, {
|
|
83500
83671
|
run: () => run14
|
|
83501
83672
|
});
|
|
83502
|
-
import { readFileSync as
|
|
83503
|
-
import
|
|
83673
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
83674
|
+
import path58 from "node:path";
|
|
83504
83675
|
function readBodyFile(io, file) {
|
|
83505
83676
|
try {
|
|
83506
83677
|
return {
|
|
83507
|
-
body: file === "-" ? forgeDeps.readStdin() :
|
|
83678
|
+
body: file === "-" ? forgeDeps.readStdin() : readFileSync24(path58.resolve(io.cwd, file), "utf8")
|
|
83508
83679
|
};
|
|
83509
83680
|
} catch {
|
|
83510
83681
|
return `cannot read --body-file ${file}`;
|
|
@@ -84209,8 +84380,8 @@ var exports_git = {};
|
|
|
84209
84380
|
__export(exports_git, {
|
|
84210
84381
|
run: () => run16
|
|
84211
84382
|
});
|
|
84212
|
-
import { readFileSync as
|
|
84213
|
-
import
|
|
84383
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
84384
|
+
import path59 from "node:path";
|
|
84214
84385
|
function kindHint(cwd, kind) {
|
|
84215
84386
|
let kinds = [...BRANCH_KINDS];
|
|
84216
84387
|
try {
|
|
@@ -84314,7 +84485,7 @@ function commitMessage(parsed, io) {
|
|
|
84314
84485
|
|
|
84315
84486
|
`);
|
|
84316
84487
|
try {
|
|
84317
|
-
return file === "-" ?
|
|
84488
|
+
return file === "-" ? readFileSync25(0, "utf8") : readFileSync25(path59.resolve(io.cwd, file), "utf8");
|
|
84318
84489
|
} catch (error) {
|
|
84319
84490
|
return {
|
|
84320
84491
|
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -85735,7 +85906,7 @@ var init_live_session = __esm(() => {
|
|
|
85735
85906
|
});
|
|
85736
85907
|
|
|
85737
85908
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
85738
|
-
import
|
|
85909
|
+
import path60 from "node:path";
|
|
85739
85910
|
var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
|
|
85740
85911
|
var init_write_gate = __esm(() => {
|
|
85741
85912
|
init_task_store();
|
|
@@ -85775,7 +85946,7 @@ var init_write_gate = __esm(() => {
|
|
|
85775
85946
|
CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
85776
85947
|
PUSHD2 = new Set(["pushd", "push-location"]);
|
|
85777
85948
|
POPD2 = new Set(["popd", "pop-location"]);
|
|
85778
|
-
UNKNOWN_DIR =
|
|
85949
|
+
UNKNOWN_DIR = path60.resolve(path60.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
85779
85950
|
});
|
|
85780
85951
|
|
|
85781
85952
|
// packages/workit-core/src/hooks/worktree-confine.ts
|
|
@@ -85800,20 +85971,20 @@ var init_worktree_confine = __esm(() => {
|
|
|
85800
85971
|
|
|
85801
85972
|
// packages/workit-core/src/worktree-deps.ts
|
|
85802
85973
|
import fs32 from "node:fs";
|
|
85803
|
-
import
|
|
85974
|
+
import path61 from "node:path";
|
|
85804
85975
|
function moduleDirs(main) {
|
|
85805
85976
|
const out = [];
|
|
85806
85977
|
const walk = (relative, depth) => {
|
|
85807
85978
|
let entries;
|
|
85808
85979
|
try {
|
|
85809
|
-
entries = fs32.readdirSync(
|
|
85980
|
+
entries = fs32.readdirSync(path61.join(main, relative), { withFileTypes: true });
|
|
85810
85981
|
} catch {
|
|
85811
85982
|
return;
|
|
85812
85983
|
}
|
|
85813
85984
|
for (const entry of entries) {
|
|
85814
85985
|
if (!entry.isDirectory())
|
|
85815
85986
|
continue;
|
|
85816
|
-
const child =
|
|
85987
|
+
const child = path61.join(relative, entry.name);
|
|
85817
85988
|
if (entry.name === MODULES)
|
|
85818
85989
|
out.push(child);
|
|
85819
85990
|
else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
|
|
@@ -85827,8 +85998,8 @@ function linkEntry(main, worktree, source, target) {
|
|
|
85827
85998
|
const stat = fs32.lstatSync(source);
|
|
85828
85999
|
if (stat.isSymbolicLink()) {
|
|
85829
86000
|
const link = fs32.readlinkSync(source);
|
|
85830
|
-
const outside =
|
|
85831
|
-
const to = outside ?
|
|
86001
|
+
const outside = path61.isAbsolute(link) && within(link, main) && !path61.relative(main, link).split(path61.sep).includes(MODULES);
|
|
86002
|
+
const to = outside ? path61.join(worktree, path61.relative(main, link)) : link;
|
|
85832
86003
|
fs32.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
|
|
85833
86004
|
return;
|
|
85834
86005
|
}
|
|
@@ -85838,8 +86009,8 @@ function mirror(main, worktree, source, target, top) {
|
|
|
85838
86009
|
fs32.mkdirSync(target);
|
|
85839
86010
|
let count = 0;
|
|
85840
86011
|
for (const entry of fs32.readdirSync(source, { withFileTypes: true })) {
|
|
85841
|
-
const from =
|
|
85842
|
-
const to =
|
|
86012
|
+
const from = path61.join(source, entry.name);
|
|
86013
|
+
const to = path61.join(target, entry.name);
|
|
85843
86014
|
if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
|
|
85844
86015
|
count += mirror(main, worktree, from, to, false);
|
|
85845
86016
|
else {
|
|
@@ -85855,16 +86026,16 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
85855
86026
|
const dirs = [];
|
|
85856
86027
|
let entries = 0;
|
|
85857
86028
|
for (const relative of moduleDirs(main)) {
|
|
85858
|
-
const target =
|
|
85859
|
-
if (!fs32.existsSync(
|
|
86029
|
+
const target = path61.join(worktree, relative);
|
|
86030
|
+
if (!fs32.existsSync(path61.dirname(target)) || fs32.existsSync(target))
|
|
85860
86031
|
continue;
|
|
85861
|
-
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(
|
|
85862
|
-
notes.push(`${relative.split(
|
|
86032
|
+
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path61.sep).join("/")}/`]).ok) {
|
|
86033
|
+
notes.push(`${relative.split(path61.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
|
|
85863
86034
|
continue;
|
|
85864
86035
|
}
|
|
85865
86036
|
try {
|
|
85866
|
-
entries += mirror(main, worktree,
|
|
85867
|
-
dirs.push(relative.split(
|
|
86037
|
+
entries += mirror(main, worktree, path61.join(main, relative), target, true);
|
|
86038
|
+
dirs.push(relative.split(path61.sep).join("/"));
|
|
85868
86039
|
} catch (error) {
|
|
85869
86040
|
fs32.rmSync(target, { recursive: true, force: true });
|
|
85870
86041
|
notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
|
|
@@ -85877,8 +86048,8 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
85877
86048
|
return { linked: { from: main, dirs, entries, ms }, notes };
|
|
85878
86049
|
}
|
|
85879
86050
|
var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
|
|
85880
|
-
const relative =
|
|
85881
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86051
|
+
const relative = path61.relative(parent, child);
|
|
86052
|
+
return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
|
|
85882
86053
|
};
|
|
85883
86054
|
var init_worktree_deps = __esm(() => {
|
|
85884
86055
|
init_fanout();
|
|
@@ -85887,7 +86058,7 @@ var init_worktree_deps = __esm(() => {
|
|
|
85887
86058
|
// packages/workit-core/src/fanout-worktree.ts
|
|
85888
86059
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
85889
86060
|
import fs33 from "node:fs";
|
|
85890
|
-
import
|
|
86061
|
+
import path62 from "node:path";
|
|
85891
86062
|
function rowSample(lines) {
|
|
85892
86063
|
const out = [];
|
|
85893
86064
|
let bytes = 0;
|
|
@@ -85947,7 +86118,7 @@ function adminDir(worktree) {
|
|
|
85947
86118
|
const file = dir.stdout.trim();
|
|
85948
86119
|
let token = null;
|
|
85949
86120
|
try {
|
|
85950
|
-
token = fs33.readFileSync(
|
|
86121
|
+
token = fs33.readFileSync(path62.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
|
|
85951
86122
|
} catch {
|
|
85952
86123
|
token = null;
|
|
85953
86124
|
}
|
|
@@ -85955,7 +86126,7 @@ function adminDir(worktree) {
|
|
|
85955
86126
|
const stat = worktreeDeps.stat(file);
|
|
85956
86127
|
return {
|
|
85957
86128
|
path: file,
|
|
85958
|
-
id:
|
|
86129
|
+
id: path62.basename(file),
|
|
85959
86130
|
ino: stat.ino.toString(),
|
|
85960
86131
|
token,
|
|
85961
86132
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -85971,7 +86142,7 @@ function markAdminDir(worktree) {
|
|
|
85971
86142
|
return null;
|
|
85972
86143
|
const token = randomBytes5(16).toString("hex");
|
|
85973
86144
|
try {
|
|
85974
|
-
fs33.writeFileSync(
|
|
86145
|
+
fs33.writeFileSync(path62.join(admin.path, FANOUT_TOKEN_FILE), `${token}
|
|
85975
86146
|
`);
|
|
85976
86147
|
} catch {
|
|
85977
86148
|
return null;
|
|
@@ -85986,7 +86157,7 @@ function excludeScratch(cwd) {
|
|
|
85986
86157
|
const common = gitCommonDir(cwd);
|
|
85987
86158
|
if (!common)
|
|
85988
86159
|
return;
|
|
85989
|
-
const file =
|
|
86160
|
+
const file = path62.join(common, "info", "exclude");
|
|
85990
86161
|
let text = "";
|
|
85991
86162
|
try {
|
|
85992
86163
|
text = fs33.readFileSync(file, "utf8");
|
|
@@ -85995,7 +86166,7 @@ function excludeScratch(cwd) {
|
|
|
85995
86166
|
}
|
|
85996
86167
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
85997
86168
|
return;
|
|
85998
|
-
fs33.mkdirSync(
|
|
86169
|
+
fs33.mkdirSync(path62.dirname(file), { recursive: true });
|
|
85999
86170
|
fs33.appendFileSync(file, `${text && !text.endsWith(`
|
|
86000
86171
|
`) ? `
|
|
86001
86172
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
@@ -86003,7 +86174,7 @@ ${EXCLUDE_LINE}
|
|
|
86003
86174
|
`);
|
|
86004
86175
|
}
|
|
86005
86176
|
function ensureScratch(worktree) {
|
|
86006
|
-
const scratch =
|
|
86177
|
+
const scratch = path62.join(worktree, SCRATCH_DIR);
|
|
86007
86178
|
fs33.mkdirSync(scratch, { recursive: true });
|
|
86008
86179
|
return scratch;
|
|
86009
86180
|
}
|
|
@@ -86231,7 +86402,7 @@ function unpushedCount(cwd, branch) {
|
|
|
86231
86402
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
86232
86403
|
}
|
|
86233
86404
|
function removeScratch(worktree) {
|
|
86234
|
-
const scratch =
|
|
86405
|
+
const scratch = path62.join(worktree, SCRATCH_DIR);
|
|
86235
86406
|
let stat;
|
|
86236
86407
|
try {
|
|
86237
86408
|
stat = fs33.lstatSync(scratch);
|
|
@@ -86247,16 +86418,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
|
|
|
86247
86418
|
try {
|
|
86248
86419
|
return fs33.realpathSync.native(target);
|
|
86249
86420
|
} catch {
|
|
86250
|
-
return
|
|
86421
|
+
return path62.resolve(target);
|
|
86251
86422
|
}
|
|
86252
86423
|
}, samePath = (a, b) => {
|
|
86253
86424
|
const left = canonical2(a);
|
|
86254
86425
|
const right = canonical2(b);
|
|
86255
86426
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
86256
86427
|
}, inside3 = (child, parent) => {
|
|
86257
|
-
const relative =
|
|
86258
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86259
|
-
}, slicePath = (cwd, slice) =>
|
|
86428
|
+
const relative = path62.relative(canonical2(parent), canonical2(child));
|
|
86429
|
+
return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
|
|
86430
|
+
}, slicePath = (cwd, slice) => path62.isAbsolute(slice.worktree) ? slice.worktree : path62.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
|
|
86260
86431
|
`)[0] || "unknown error"}`);
|
|
86261
86432
|
var init_fanout_worktree = __esm(() => {
|
|
86262
86433
|
init_ops();
|
|
@@ -87092,7 +87263,7 @@ __export(exports_fanout, {
|
|
|
87092
87263
|
run: () => run20
|
|
87093
87264
|
});
|
|
87094
87265
|
import fs34 from "node:fs";
|
|
87095
|
-
import
|
|
87266
|
+
import path63 from "node:path";
|
|
87096
87267
|
function forgeFor(io, offline) {
|
|
87097
87268
|
if (offline)
|
|
87098
87269
|
return { forge: null, error: "--offline" };
|
|
@@ -87153,7 +87324,7 @@ function plan2(argv, io) {
|
|
|
87153
87324
|
return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
87154
87325
|
if (flags.positionals.length !== 1)
|
|
87155
87326
|
return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
87156
|
-
const file =
|
|
87327
|
+
const file = path63.resolve(io.cwd, flags.positionals[0]);
|
|
87157
87328
|
let raw;
|
|
87158
87329
|
try {
|
|
87159
87330
|
raw = JSON.parse(fs34.readFileSync(file, "utf8"));
|
|
@@ -102692,7 +102863,7 @@ var init_ast = __esm(() => {
|
|
|
102692
102863
|
|
|
102693
102864
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
102694
102865
|
import { builtinModules } from "node:module";
|
|
102695
|
-
import
|
|
102866
|
+
import path64 from "node:path";
|
|
102696
102867
|
function testCallee(call) {
|
|
102697
102868
|
let callee = call.callee;
|
|
102698
102869
|
if (callee.type === "CallExpression")
|
|
@@ -103185,12 +103356,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
103185
103356
|
}
|
|
103186
103357
|
function checkOverMocking(ctx, emit) {
|
|
103187
103358
|
const { program } = ctx.parsed;
|
|
103188
|
-
const unit =
|
|
103359
|
+
const unit = path64.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
103189
103360
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
103190
103361
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
103191
103362
|
for (const call of mocked) {
|
|
103192
103363
|
const spec = call.arguments[0].value;
|
|
103193
|
-
const base =
|
|
103364
|
+
const base = path64.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
103194
103365
|
if (base === unit)
|
|
103195
103366
|
emit({
|
|
103196
103367
|
rule: "over-mocking",
|
|
@@ -103579,8 +103750,8 @@ var init_rules = __esm(() => {
|
|
|
103579
103750
|
|
|
103580
103751
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
103581
103752
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
103582
|
-
import { existsSync as
|
|
103583
|
-
import
|
|
103753
|
+
import { existsSync as existsSync23, readdirSync as readdirSync11, readFileSync as readFileSync26, statSync as statSync10 } from "node:fs";
|
|
103754
|
+
import path65 from "node:path";
|
|
103584
103755
|
function git7(cwd, args) {
|
|
103585
103756
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
103586
103757
|
cwd,
|
|
@@ -103590,10 +103761,10 @@ function git7(cwd, args) {
|
|
|
103590
103761
|
return { ok: run.status === 0, stdout: run.stdout ?? "" };
|
|
103591
103762
|
}
|
|
103592
103763
|
function walkTests(dir, out) {
|
|
103593
|
-
for (const entry of
|
|
103764
|
+
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
103594
103765
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
103595
103766
|
continue;
|
|
103596
|
-
const full =
|
|
103767
|
+
const full = path65.join(dir, entry.name);
|
|
103597
103768
|
if (entry.isDirectory()) {
|
|
103598
103769
|
if (!SKIP_DIRS.has(entry.name))
|
|
103599
103770
|
walkTests(full, out);
|
|
@@ -103605,10 +103776,10 @@ function expandPaths(cwd, inputs) {
|
|
|
103605
103776
|
const files = [];
|
|
103606
103777
|
const missing = [];
|
|
103607
103778
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
103608
|
-
const full =
|
|
103609
|
-
if (!
|
|
103779
|
+
const full = path65.resolve(cwd, input);
|
|
103780
|
+
if (!existsSync23(full))
|
|
103610
103781
|
missing.push(input);
|
|
103611
|
-
else if (
|
|
103782
|
+
else if (statSync10(full).isDirectory())
|
|
103612
103783
|
walkTests(full, files);
|
|
103613
103784
|
else
|
|
103614
103785
|
files.push(full);
|
|
@@ -103642,11 +103813,11 @@ function changedLines(cwd, base) {
|
|
|
103642
103813
|
for (let offset = 0;offset < count; offset += 1)
|
|
103643
103814
|
lines.add(start + offset);
|
|
103644
103815
|
}
|
|
103645
|
-
changed.set(
|
|
103816
|
+
changed.set(path65.join(root, file), lines);
|
|
103646
103817
|
}
|
|
103647
103818
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
103648
103819
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
103649
|
-
changed.set(
|
|
103820
|
+
changed.set(path65.join(root, file), "all");
|
|
103650
103821
|
return changed;
|
|
103651
103822
|
}
|
|
103652
103823
|
function auditFiles(files, display) {
|
|
@@ -103659,7 +103830,7 @@ function auditFiles(files, display) {
|
|
|
103659
103830
|
const shown = display(file);
|
|
103660
103831
|
let parsed;
|
|
103661
103832
|
try {
|
|
103662
|
-
parsed = parseSource(
|
|
103833
|
+
parsed = parseSource(readFileSync26(file, "utf8"), file);
|
|
103663
103834
|
} catch (error) {
|
|
103664
103835
|
parseErrors.push({
|
|
103665
103836
|
file: shown,
|
|
@@ -103708,7 +103879,7 @@ function auditFiles(files, display) {
|
|
|
103708
103879
|
durationMs: Math.round(performance.now() - started)
|
|
103709
103880
|
};
|
|
103710
103881
|
}
|
|
103711
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
103882
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path65.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
103712
103883
|
var init_audit = __esm(() => {
|
|
103713
103884
|
init_ast();
|
|
103714
103885
|
init_rules();
|
|
@@ -103722,23 +103893,23 @@ var init_audit = __esm(() => {
|
|
|
103722
103893
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
103723
103894
|
import { spawn as spawn2 } from "node:child_process";
|
|
103724
103895
|
import {
|
|
103725
|
-
existsSync as
|
|
103896
|
+
existsSync as existsSync24,
|
|
103726
103897
|
lstatSync as lstatSync8,
|
|
103727
103898
|
mkdirSync as mkdirSync11,
|
|
103728
103899
|
mkdtempSync as mkdtempSync4,
|
|
103729
|
-
readdirSync as
|
|
103730
|
-
readFileSync as
|
|
103900
|
+
readdirSync as readdirSync12,
|
|
103901
|
+
readFileSync as readFileSync27,
|
|
103731
103902
|
readlinkSync as readlinkSync3,
|
|
103732
103903
|
realpathSync as realpathSync10,
|
|
103733
103904
|
renameSync as renameSync7,
|
|
103734
103905
|
rmSync as rmSync9,
|
|
103735
|
-
statSync as
|
|
103906
|
+
statSync as statSync11,
|
|
103736
103907
|
symlinkSync,
|
|
103737
103908
|
writeFileSync as writeFileSync11,
|
|
103738
103909
|
copyFileSync as copyFileSync7
|
|
103739
103910
|
} from "node:fs";
|
|
103740
|
-
import
|
|
103741
|
-
import
|
|
103911
|
+
import os22 from "node:os";
|
|
103912
|
+
import path66 from "node:path";
|
|
103742
103913
|
function mutantsFor(source, file, lines) {
|
|
103743
103914
|
const parsed = parseSource(source, file);
|
|
103744
103915
|
const out = [];
|
|
@@ -103811,7 +103982,7 @@ function relatedTests(source, testFiles) {
|
|
|
103811
103982
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
103812
103983
|
const spec = match[1];
|
|
103813
103984
|
if (spec.startsWith(".")) {
|
|
103814
|
-
if (stripExt(
|
|
103985
|
+
if (stripExt(path66.posix.join(path66.posix.dirname(file), spec)) === target)
|
|
103815
103986
|
return true;
|
|
103816
103987
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
103817
103988
|
return true;
|
|
@@ -103819,11 +103990,11 @@ function relatedTests(source, testFiles) {
|
|
|
103819
103990
|
return false;
|
|
103820
103991
|
}).map((entry) => entry.file);
|
|
103821
103992
|
}
|
|
103822
|
-
function removeStaleCopies(tmp =
|
|
103993
|
+
function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
103823
103994
|
let removed = 0;
|
|
103824
103995
|
let names = [];
|
|
103825
103996
|
try {
|
|
103826
|
-
names =
|
|
103997
|
+
names = readdirSync12(tmp);
|
|
103827
103998
|
} catch {
|
|
103828
103999
|
return 0;
|
|
103829
104000
|
}
|
|
@@ -103831,12 +104002,12 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
|
|
|
103831
104002
|
for (const name of names) {
|
|
103832
104003
|
if (!name.startsWith(TEMP_PREFIX))
|
|
103833
104004
|
continue;
|
|
103834
|
-
const dir =
|
|
104005
|
+
const dir = path66.join(tmp, name);
|
|
103835
104006
|
try {
|
|
103836
104007
|
const stat = lstatSync8(dir);
|
|
103837
104008
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
103838
104009
|
continue;
|
|
103839
|
-
const pid = Number(
|
|
104010
|
+
const pid = Number(readFileSync27(path66.join(dir, PID_FILE), "utf8"));
|
|
103840
104011
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
103841
104012
|
continue;
|
|
103842
104013
|
} catch (error) {
|
|
@@ -103852,9 +104023,9 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
|
|
|
103852
104023
|
}
|
|
103853
104024
|
function linkNodeModules(origin, target, repo, copy) {
|
|
103854
104025
|
mkdirSync11(target, { recursive: true });
|
|
103855
|
-
for (const entry of
|
|
103856
|
-
const from =
|
|
103857
|
-
const to =
|
|
104026
|
+
for (const entry of readdirSync12(origin, { withFileTypes: true })) {
|
|
104027
|
+
const from = path66.join(origin, entry.name);
|
|
104028
|
+
const to = path66.join(target, entry.name);
|
|
103858
104029
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
103859
104030
|
linkNodeModules(from, to, repo, copy);
|
|
103860
104031
|
continue;
|
|
@@ -103870,9 +104041,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
103870
104041
|
} catch {
|
|
103871
104042
|
continue;
|
|
103872
104043
|
}
|
|
103873
|
-
const relative =
|
|
103874
|
-
if (!relative.startsWith("..") && !
|
|
103875
|
-
symlinkSync(
|
|
104044
|
+
const relative = path66.relative(repo, real);
|
|
104045
|
+
if (!relative.startsWith("..") && !path66.isAbsolute(relative) && !relative.split(path66.sep).includes("node_modules")) {
|
|
104046
|
+
symlinkSync(path66.join(copy, relative), to, "junction");
|
|
103876
104047
|
continue;
|
|
103877
104048
|
}
|
|
103878
104049
|
}
|
|
@@ -103888,19 +104059,19 @@ function copySymlink(repo, tree, from, to) {
|
|
|
103888
104059
|
}
|
|
103889
104060
|
const realRepo = realpathSync10(repo);
|
|
103890
104061
|
if (real && inside4(realRepo, real)) {
|
|
103891
|
-
symlinkSync(
|
|
104062
|
+
symlinkSync(path66.relative(path66.dirname(to), path66.join(tree, path66.relative(realRepo, real))), to);
|
|
103892
104063
|
return;
|
|
103893
104064
|
}
|
|
103894
|
-
if (real &&
|
|
104065
|
+
if (real && statSync11(real).isFile())
|
|
103895
104066
|
copyFileSync7(real, to);
|
|
103896
104067
|
else
|
|
103897
104068
|
symlinkSync(readlinkSync3(from), to);
|
|
103898
104069
|
}
|
|
103899
104070
|
function writeInside(copy, file, content) {
|
|
103900
|
-
const target =
|
|
104071
|
+
const target = path66.join(copy, file);
|
|
103901
104072
|
try {
|
|
103902
104073
|
const stat = lstatSync8(target);
|
|
103903
|
-
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(
|
|
104074
|
+
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(path66.dirname(target))))
|
|
103904
104075
|
return false;
|
|
103905
104076
|
} catch {
|
|
103906
104077
|
return false;
|
|
@@ -103911,9 +104082,9 @@ function writeInside(copy, file, content) {
|
|
|
103911
104082
|
return true;
|
|
103912
104083
|
}
|
|
103913
104084
|
function copyWorkingTree(repo) {
|
|
103914
|
-
const dir = mkdtempSync4(
|
|
103915
|
-
writeFileSync11(
|
|
103916
|
-
const tree =
|
|
104085
|
+
const dir = mkdtempSync4(path66.join(os22.tmpdir(), TEMP_PREFIX));
|
|
104086
|
+
writeFileSync11(path66.join(dir, PID_FILE), String(process.pid));
|
|
104087
|
+
const tree = path66.join(dir, "tree");
|
|
103917
104088
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
103918
104089
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
103919
104090
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -103930,29 +104101,29 @@ function copyWorkingTree(repo) {
|
|
|
103930
104101
|
for (const relative of listed) {
|
|
103931
104102
|
if (!relative)
|
|
103932
104103
|
continue;
|
|
103933
|
-
const from =
|
|
104104
|
+
const from = path66.join(repo, relative);
|
|
103934
104105
|
let stat;
|
|
103935
104106
|
try {
|
|
103936
104107
|
stat = lstatSync8(from);
|
|
103937
104108
|
} catch {
|
|
103938
104109
|
continue;
|
|
103939
104110
|
}
|
|
103940
|
-
const to =
|
|
103941
|
-
mkdirSync11(
|
|
104111
|
+
const to = path66.join(tree, relative);
|
|
104112
|
+
mkdirSync11(path66.dirname(to), { recursive: true });
|
|
103942
104113
|
if (stat.isSymbolicLink())
|
|
103943
104114
|
copySymlink(repo, tree, from, to);
|
|
103944
104115
|
else if (stat.isFile())
|
|
103945
104116
|
copyFileSync7(from, to);
|
|
103946
|
-
let parent =
|
|
104117
|
+
let parent = path66.dirname(relative);
|
|
103947
104118
|
while (parent !== "." && !dirs.has(parent)) {
|
|
103948
104119
|
dirs.add(parent);
|
|
103949
|
-
parent =
|
|
104120
|
+
parent = path66.dirname(parent);
|
|
103950
104121
|
}
|
|
103951
104122
|
}
|
|
103952
104123
|
for (const parent of dirs) {
|
|
103953
|
-
const modules =
|
|
103954
|
-
if (
|
|
103955
|
-
linkNodeModules(modules,
|
|
104124
|
+
const modules = path66.join(repo, parent, "node_modules");
|
|
104125
|
+
if (existsSync24(modules) && !existsSync24(path66.join(tree, parent, "node_modules")))
|
|
104126
|
+
linkNodeModules(modules, path66.join(tree, parent, "node_modules"), repo, tree);
|
|
103956
104127
|
}
|
|
103957
104128
|
return { dir, tree };
|
|
103958
104129
|
}
|
|
@@ -103991,20 +104162,20 @@ async function runMutation(options) {
|
|
|
103991
104162
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
103992
104163
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
103993
104164
|
try {
|
|
103994
|
-
return { file, text:
|
|
104165
|
+
return { file, text: readFileSync27(path66.join(repo, file), "utf8") };
|
|
103995
104166
|
} catch {
|
|
103996
104167
|
return { file, text: "" };
|
|
103997
104168
|
}
|
|
103998
104169
|
});
|
|
103999
104170
|
const candidates = [];
|
|
104000
104171
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
104001
|
-
const relative = toPosix(
|
|
104172
|
+
const relative = toPosix(path66.relative(repo, absolute));
|
|
104002
104173
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
104003
104174
|
continue;
|
|
104004
|
-
if (NOT_SOURCE.test(relative) || !
|
|
104175
|
+
if (NOT_SOURCE.test(relative) || !existsSync24(absolute))
|
|
104005
104176
|
continue;
|
|
104006
104177
|
try {
|
|
104007
|
-
candidates.push(...mutantsFor(
|
|
104178
|
+
candidates.push(...mutantsFor(readFileSync27(absolute, "utf8"), relative, lines));
|
|
104008
104179
|
} catch {}
|
|
104009
104180
|
}
|
|
104010
104181
|
const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
|
|
@@ -104012,9 +104183,9 @@ async function runMutation(options) {
|
|
|
104012
104183
|
for (const mutant of mutants)
|
|
104013
104184
|
if (!related.has(mutant.file))
|
|
104014
104185
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
104015
|
-
const cwdRelative =
|
|
104186
|
+
const cwdRelative = path66.relative(repo, options.cwd);
|
|
104016
104187
|
const asArg = (file) => {
|
|
104017
|
-
const relative = toPosix(
|
|
104188
|
+
const relative = toPosix(path66.relative(cwdRelative, file));
|
|
104018
104189
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
104019
104190
|
};
|
|
104020
104191
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -104050,7 +104221,7 @@ async function runMutation(options) {
|
|
|
104050
104221
|
return finish3(options, 0, results, counts, started);
|
|
104051
104222
|
removeStaleCopies();
|
|
104052
104223
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
104053
|
-
const copyCwd =
|
|
104224
|
+
const copyCwd = path66.join(copy, cwdRelative);
|
|
104054
104225
|
let current = null;
|
|
104055
104226
|
const restore = () => {
|
|
104056
104227
|
if (current)
|
|
@@ -104085,7 +104256,7 @@ async function runMutation(options) {
|
|
|
104085
104256
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
104086
104257
|
continue;
|
|
104087
104258
|
}
|
|
104088
|
-
const original =
|
|
104259
|
+
const original = readFileSync27(path66.join(copy, mutant.file), "utf8");
|
|
104089
104260
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
104090
104261
|
current = { file: mutant.file, original };
|
|
104091
104262
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -104142,8 +104313,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
104142
104313
|
return error.code === "EPERM";
|
|
104143
104314
|
}
|
|
104144
104315
|
}, inside4 = (root, file) => {
|
|
104145
|
-
const relative =
|
|
104146
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
104316
|
+
const relative = path66.relative(root, file);
|
|
104317
|
+
return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
|
|
104147
104318
|
}, active, killTree = (child) => {
|
|
104148
104319
|
try {
|
|
104149
104320
|
if (child.pid && process.platform !== "win32")
|
|
@@ -104191,8 +104362,8 @@ var exports_test_audit = {};
|
|
|
104191
104362
|
__export(exports_test_audit, {
|
|
104192
104363
|
run: () => run22
|
|
104193
104364
|
});
|
|
104194
|
-
import { existsSync as
|
|
104195
|
-
import
|
|
104365
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
104366
|
+
import path67 from "node:path";
|
|
104196
104367
|
function parse8(argv) {
|
|
104197
104368
|
const options = {
|
|
104198
104369
|
paths: [],
|
|
@@ -104297,8 +104468,8 @@ async function run22(argv, io) {
|
|
|
104297
104468
|
return emit(io, fail2("invalid_input", `${options}
|
|
104298
104469
|
usage: ${USAGE14}`));
|
|
104299
104470
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
104300
|
-
const repo = top.ok ?
|
|
104301
|
-
const display = (file) => toPosix(
|
|
104471
|
+
const repo = top.ok ? path67.resolve(top.stdout.trim()) : null;
|
|
104472
|
+
const display = (file) => toPosix(path67.relative(io.cwd, file) || file);
|
|
104302
104473
|
let base = null;
|
|
104303
104474
|
let changed = null;
|
|
104304
104475
|
if (options.diff || options.mutate) {
|
|
@@ -104315,7 +104486,7 @@ usage: ${USAGE14}`));
|
|
|
104315
104486
|
}
|
|
104316
104487
|
let files;
|
|
104317
104488
|
if (options.diff && changed)
|
|
104318
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
104489
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync25(file)).toSorted();
|
|
104319
104490
|
else {
|
|
104320
104491
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
104321
104492
|
if (expanded.missing.length > 0)
|
|
@@ -104436,8 +104607,8 @@ var exports_youtrack = {};
|
|
|
104436
104607
|
__export(exports_youtrack, {
|
|
104437
104608
|
run: () => run24
|
|
104438
104609
|
});
|
|
104439
|
-
import { readFileSync as
|
|
104440
|
-
import
|
|
104610
|
+
import { readFileSync as readFileSync28 } from "node:fs";
|
|
104611
|
+
import path68 from "node:path";
|
|
104441
104612
|
async function run24(argv, io) {
|
|
104442
104613
|
const [sub, ...rest] = argv;
|
|
104443
104614
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -104483,7 +104654,7 @@ async function run24(argv, io) {
|
|
|
104483
104654
|
let markdown = flags.values.markdown ?? "";
|
|
104484
104655
|
if (flags.values.file)
|
|
104485
104656
|
try {
|
|
104486
|
-
markdown =
|
|
104657
|
+
markdown = readFileSync28(path68.resolve(io.cwd, flags.values.file), "utf8");
|
|
104487
104658
|
} catch (error) {
|
|
104488
104659
|
return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE16);
|
|
104489
104660
|
}
|
|
@@ -104551,8 +104722,8 @@ var exports_changelog = {};
|
|
|
104551
104722
|
__export(exports_changelog, {
|
|
104552
104723
|
run: () => run25
|
|
104553
104724
|
});
|
|
104554
|
-
import { readFileSync as
|
|
104555
|
-
import
|
|
104725
|
+
import { readFileSync as readFileSync29 } from "node:fs";
|
|
104726
|
+
import path69 from "node:path";
|
|
104556
104727
|
async function run25(argv, io) {
|
|
104557
104728
|
const [sub, ...rest] = argv;
|
|
104558
104729
|
if (sub !== "apply")
|
|
@@ -104598,7 +104769,7 @@ async function run25(argv, io) {
|
|
|
104598
104769
|
]);
|
|
104599
104770
|
}
|
|
104600
104771
|
var USAGE17 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
104601
|
-
const text = raw === "-" ?
|
|
104772
|
+
const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(path69.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
104602
104773
|
return JSON.parse(text);
|
|
104603
104774
|
};
|
|
104604
104775
|
var init_changelog2 = __esm(() => {
|
|
@@ -104695,7 +104866,7 @@ var init_handoff = __esm(() => {
|
|
|
104695
104866
|
// packages/workit-cli/src/main.ts
|
|
104696
104867
|
init_host_session();
|
|
104697
104868
|
init_package();
|
|
104698
|
-
import
|
|
104869
|
+
import path70 from "node:path";
|
|
104699
104870
|
|
|
104700
104871
|
// packages/workit-cli/src/verbs/registry.ts
|
|
104701
104872
|
var TASK_FAMILY_NAMES = [
|
|
@@ -104940,7 +105111,7 @@ var VERBS = [
|
|
|
104940
105111
|
subcommands: [
|
|
104941
105112
|
{
|
|
104942
105113
|
name: "show",
|
|
104943
|
-
usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--json]",
|
|
105114
|
+
usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--report [--days <n>]] [--json]",
|
|
104944
105115
|
summary: "Print the resolved model and effort per role for a host (default: the lead's host, else claude_code) and where each came from"
|
|
104945
105116
|
}
|
|
104946
105117
|
],
|
|
@@ -105557,7 +105728,7 @@ var defaultIo = (json) => ({
|
|
|
105557
105728
|
});
|
|
105558
105729
|
async function main(argv, overrides = {}, options = {}) {
|
|
105559
105730
|
const parsed = parseGlobals(argv);
|
|
105560
|
-
const cwd =
|
|
105731
|
+
const cwd = path70.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
105561
105732
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
105562
105733
|
if (parsed.error)
|
|
105563
105734
|
return emit(io, fail2("invalid_input", parsed.error));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.28.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
6
6
|
"keywords": [
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@babel/parser": "7.29.9",
|
|
41
|
-
"@brainervirus/workit-cursor": "^8.
|
|
41
|
+
"@brainervirus/workit-cursor": "^8.28.0",
|
|
42
42
|
"@inkjs/ui": "2.0.0",
|
|
43
43
|
"ink": "7.1.1",
|
|
44
44
|
"react": "19.2.8"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@brainervirus/workit-core": "^8.
|
|
47
|
+
"@brainervirus/workit-core": "^8.28.0"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|