@brainervirus/workit-cli 8.27.0 → 8.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +333 -156
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -8412,11 +8412,15 @@ var withReleaseTracks = (workspaceRoot, policy) => {
|
|
|
8412
8412
|
correction,
|
|
8413
8413
|
error: `commit_style: commit subject ${JSON.stringify(attempted)} violates ${source} ${policy.preset} policy; ${correction}`
|
|
8414
8414
|
};
|
|
8415
|
+
}, rethrowRuntimeBug = (error) => {
|
|
8416
|
+
if (error instanceof TypeError || error instanceof ReferenceError)
|
|
8417
|
+
throw error;
|
|
8415
8418
|
}, validateBranchNameFor = (workspaceRoot, name) => {
|
|
8416
8419
|
try {
|
|
8417
8420
|
const resolved = branchPolicySnapshotFor(workspaceRoot);
|
|
8418
8421
|
return validateBranchNamePolicy(name, resolved.namePolicy, resolved.source);
|
|
8419
8422
|
} catch (error) {
|
|
8423
|
+
rethrowRuntimeBug(error);
|
|
8420
8424
|
const correction = "repair or select a valid workspace policy before creating a branch";
|
|
8421
8425
|
return {
|
|
8422
8426
|
ok: false,
|
|
@@ -8434,6 +8438,7 @@ var withReleaseTracks = (workspaceRoot, policy) => {
|
|
|
8434
8438
|
const resolved = commitPolicySnapshotFor(workspaceRoot);
|
|
8435
8439
|
return validateCommitMessagePolicy(message, resolved.policy, resolved.source);
|
|
8436
8440
|
} catch (error) {
|
|
8441
|
+
rethrowRuntimeBug(error);
|
|
8437
8442
|
const correction = "repair or select a valid workspace policy before committing";
|
|
8438
8443
|
return {
|
|
8439
8444
|
ok: false,
|
|
@@ -9240,7 +9245,7 @@ var package_default;
|
|
|
9240
9245
|
var init_package = __esm(() => {
|
|
9241
9246
|
package_default = {
|
|
9242
9247
|
name: "@brainervirus/workit-cli",
|
|
9243
|
-
version: "8.
|
|
9248
|
+
version: "8.28.1",
|
|
9244
9249
|
private: false,
|
|
9245
9250
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9246
9251
|
keywords: [
|
|
@@ -9278,13 +9283,13 @@ var init_package = __esm(() => {
|
|
|
9278
9283
|
},
|
|
9279
9284
|
dependencies: {
|
|
9280
9285
|
"@babel/parser": "7.29.9",
|
|
9281
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9286
|
+
"@brainervirus/workit-cursor": "^8.28.1",
|
|
9282
9287
|
"@inkjs/ui": "2.0.0",
|
|
9283
9288
|
ink: "7.1.1",
|
|
9284
9289
|
react: "19.2.8"
|
|
9285
9290
|
},
|
|
9286
9291
|
devDependencies: {
|
|
9287
|
-
"@brainervirus/workit-core": "^8.
|
|
9292
|
+
"@brainervirus/workit-core": "^8.28.1"
|
|
9288
9293
|
},
|
|
9289
9294
|
engines: {
|
|
9290
9295
|
node: ">=24"
|
|
@@ -16358,7 +16363,7 @@ var str2 = (d, values) => ({
|
|
|
16358
16363
|
description: typeof description === "string" ? description : "",
|
|
16359
16364
|
paths: ["."],
|
|
16360
16365
|
exclusions: []
|
|
16361
|
-
}), LISTS, ENVELOPE;
|
|
16366
|
+
}), LISTS, ENVELOPE, NOT_FLAT;
|
|
16362
16367
|
var init_operation_input = __esm(() => {
|
|
16363
16368
|
init_task_contract();
|
|
16364
16369
|
scopeFields = {
|
|
@@ -16480,6 +16485,7 @@ var init_operation_input = __esm(() => {
|
|
|
16480
16485
|
"expectedWorkspaceRevision",
|
|
16481
16486
|
"judgment"
|
|
16482
16487
|
]);
|
|
16488
|
+
NOT_FLAT = new Set(["schemaVersion", "action", "workspaceId"]);
|
|
16483
16489
|
});
|
|
16484
16490
|
|
|
16485
16491
|
// packages/workit-core/src/core/policy/judgment.ts
|
|
@@ -65551,6 +65557,21 @@ var MODEL_ROLES, MODEL_TIERS, HOST_KEYS, BUILT_IN_CLAUDE_CODE, isObject9 = (valu
|
|
|
65551
65557
|
}
|
|
65552
65558
|
}
|
|
65553
65559
|
return issues;
|
|
65560
|
+
}, roleForAgentType = (agentType, prompt) => {
|
|
65561
|
+
switch (agentType) {
|
|
65562
|
+
case "workit:implementer": {
|
|
65563
|
+
const tier = typeof prompt === "string" ? /^[ \t]*TIER:[ \t]*(mundane|standard|hard)\b/im.exec(prompt)?.[1] : undefined;
|
|
65564
|
+
return { role: "implementer", tier: tier?.toLowerCase() ?? "standard" };
|
|
65565
|
+
}
|
|
65566
|
+
case "workit:verifier":
|
|
65567
|
+
return { role: "verifier" };
|
|
65568
|
+
case "workit:reviewer":
|
|
65569
|
+
return { role: "reviewer" };
|
|
65570
|
+
case "Explore":
|
|
65571
|
+
return { role: "explore" };
|
|
65572
|
+
default:
|
|
65573
|
+
return null;
|
|
65574
|
+
}
|
|
65554
65575
|
};
|
|
65555
65576
|
var init_role_models = __esm(() => {
|
|
65556
65577
|
init_workspaces();
|
|
@@ -67025,6 +67046,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67025
67046
|
return null;
|
|
67026
67047
|
dir = parent;
|
|
67027
67048
|
}
|
|
67049
|
+
}, listClaudeProcesses = () => {
|
|
67050
|
+
const r = spawnSync16("ps", ["-eo", "pid=,lstart=,args="], { encoding: "utf8", timeout: 5000 });
|
|
67051
|
+
if (r.status !== 0 || typeof r.stdout !== "string")
|
|
67052
|
+
return null;
|
|
67053
|
+
const found = [];
|
|
67054
|
+
for (const row of r.stdout.split(`
|
|
67055
|
+
`)) {
|
|
67056
|
+
const m = /^\s*(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+[\d:]+\s+\d{4})\s+(.*)$/.exec(row);
|
|
67057
|
+
if (!m || !/^(\S*\/)?claude(\s|$)/.test(m[3]))
|
|
67058
|
+
continue;
|
|
67059
|
+
const startedMs = Date.parse(m[2]);
|
|
67060
|
+
if (Number.isFinite(startedMs))
|
|
67061
|
+
found.push({ pid: Number(m[1]), startedMs, args: m[3] });
|
|
67062
|
+
}
|
|
67063
|
+
return found;
|
|
67028
67064
|
}, resolve = (options) => {
|
|
67029
67065
|
const env = options.env ?? process.env;
|
|
67030
67066
|
const home = options.home ?? env.HOME ?? os12.homedir();
|
|
@@ -67052,7 +67088,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67052
67088
|
env,
|
|
67053
67089
|
installer: options.installer ?? false,
|
|
67054
67090
|
cliVersion: options.cliVersion ?? null,
|
|
67055
|
-
scopeProbe: options.scopeProbe ?? probeScope
|
|
67091
|
+
scopeProbe: options.scopeProbe ?? probeScope,
|
|
67092
|
+
claudeProcesses: options.claudeProcesses ?? listClaudeProcesses
|
|
67056
67093
|
};
|
|
67057
67094
|
}, readJson = (p) => {
|
|
67058
67095
|
try {
|
|
@@ -68892,6 +68929,68 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68892
68929
|
fix: repair,
|
|
68893
68930
|
registryProbed
|
|
68894
68931
|
};
|
|
68932
|
+
}, checkClaudeSessionPlugin = (res) => {
|
|
68933
|
+
const id = "claude_session_plugin";
|
|
68934
|
+
if (process.platform === "win32")
|
|
68935
|
+
return {
|
|
68936
|
+
id,
|
|
68937
|
+
status: "info",
|
|
68938
|
+
detail: "running Claude Code sessions are not checked on Windows"
|
|
68939
|
+
};
|
|
68940
|
+
const installs = claudeWorkitInstalls(res.home, res.env, res.cwd).filter((install) => install.version);
|
|
68941
|
+
if (installs.length === 0)
|
|
68942
|
+
return {
|
|
68943
|
+
id,
|
|
68944
|
+
status: "info",
|
|
68945
|
+
detail: "no Workit Claude Code plugin install recorded — skipping"
|
|
68946
|
+
};
|
|
68947
|
+
const registry = readJson(path38.join(claudeConfigDir(res.home, res.env), "plugins", "installed_plugins.json"));
|
|
68948
|
+
const recorded = (install) => {
|
|
68949
|
+
const entries = registry?.plugins?.[install.id];
|
|
68950
|
+
const entry = Array.isArray(entries) ? entries.find((e) => e?.installPath === install.installPath) : null;
|
|
68951
|
+
for (const stamp of [entry?.lastUpdated, entry?.installedAt]) {
|
|
68952
|
+
const ms = typeof stamp === "string" ? Date.parse(stamp) : NaN;
|
|
68953
|
+
if (Number.isFinite(ms))
|
|
68954
|
+
return ms;
|
|
68955
|
+
}
|
|
68956
|
+
try {
|
|
68957
|
+
return statSync6(install.installPath).mtimeMs;
|
|
68958
|
+
} catch {
|
|
68959
|
+
return null;
|
|
68960
|
+
}
|
|
68961
|
+
};
|
|
68962
|
+
const latest = installs.map((install) => ({ install, at: recorded(install) })).filter((one) => one.at !== null).toSorted((a, b) => b.at - a.at)[0];
|
|
68963
|
+
if (!latest)
|
|
68964
|
+
return {
|
|
68965
|
+
id,
|
|
68966
|
+
status: "info",
|
|
68967
|
+
detail: "no install time recorded for the Workit plugin — skipping"
|
|
68968
|
+
};
|
|
68969
|
+
const running = res.claudeProcesses();
|
|
68970
|
+
if (running === null)
|
|
68971
|
+
return {
|
|
68972
|
+
id,
|
|
68973
|
+
status: "info",
|
|
68974
|
+
detail: "could not list running claude processes (ps) — skipping"
|
|
68975
|
+
};
|
|
68976
|
+
const stale = running.filter((proc) => proc.startedMs < latest.at);
|
|
68977
|
+
if (stale.length === 0)
|
|
68978
|
+
return {
|
|
68979
|
+
id,
|
|
68980
|
+
status: "info",
|
|
68981
|
+
detail: `${running.length} running claude process(es), none started before Workit ${latest.install.version} was installed`
|
|
68982
|
+
};
|
|
68983
|
+
const sessionOf = (args) => /(?:--resume|--session-id|-r)[ =]([0-9a-f]{8}-[0-9a-f-]{27})/i.exec(args)?.[1] ?? null;
|
|
68984
|
+
const rows = stale.map((proc) => {
|
|
68985
|
+
const session = sessionOf(proc.args);
|
|
68986
|
+
return `pid ${proc.pid} started ${new Date(proc.startedMs).toISOString()}${session ? ` (session ${session})` : ""}`;
|
|
68987
|
+
});
|
|
68988
|
+
const first = stale.map((proc) => sessionOf(proc.args)).find((one) => one);
|
|
68989
|
+
return {
|
|
68990
|
+
id,
|
|
68991
|
+
status: "warn",
|
|
68992
|
+
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)`
|
|
68993
|
+
};
|
|
68895
68994
|
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
|
|
68896
68995
|
let files;
|
|
68897
68996
|
try {
|
|
@@ -69093,6 +69192,7 @@ var init_doctor = __esm(() => {
|
|
|
69093
69192
|
checkPiExtension,
|
|
69094
69193
|
checkOpencodeVersion,
|
|
69095
69194
|
checkClaudePlugin,
|
|
69195
|
+
checkClaudeSessionPlugin,
|
|
69096
69196
|
checkHookIssuedSessions,
|
|
69097
69197
|
checkWorkitOnPath,
|
|
69098
69198
|
checkAssets,
|
|
@@ -77403,6 +77503,9 @@ var exports_models = {};
|
|
|
77403
77503
|
__export(exports_models, {
|
|
77404
77504
|
run: () => run13
|
|
77405
77505
|
});
|
|
77506
|
+
import { existsSync as existsSync21, readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync9 } from "node:fs";
|
|
77507
|
+
import os21 from "node:os";
|
|
77508
|
+
import path51 from "node:path";
|
|
77406
77509
|
async function run13(argv, io) {
|
|
77407
77510
|
const [sub, ...args] = argv.filter((arg) => arg !== "--json");
|
|
77408
77511
|
if (sub !== "show")
|
|
@@ -77410,13 +77513,27 @@ async function run13(argv, io) {
|
|
|
77410
77513
|
const role = flag3(args, "--role");
|
|
77411
77514
|
const tier = flag3(args, "--tier");
|
|
77412
77515
|
const hostFlag = flag3(args, "--host");
|
|
77413
|
-
|
|
77516
|
+
const daysFlag = flag3(args, "--days");
|
|
77517
|
+
for (const value of [role, tier, hostFlag, daysFlag])
|
|
77414
77518
|
if (value instanceof Error)
|
|
77415
77519
|
return emit(io, fail2("invalid_input", value.message));
|
|
77416
77520
|
if (role && !MODEL_ROLES.includes(role))
|
|
77417
77521
|
return emit(io, fail2("invalid_input", `unknown role ${role}: ${MODEL_ROLES.join(", ")}`));
|
|
77418
77522
|
if (tier && !MODEL_TIERS.includes(tier))
|
|
77419
77523
|
return emit(io, fail2("invalid_input", `unknown tier ${tier}: ${MODEL_TIERS.join(", ")}`));
|
|
77524
|
+
const days = daysFlag === null ? 7 : Number(daysFlag);
|
|
77525
|
+
if (!Number.isFinite(days) || days <= 0)
|
|
77526
|
+
return emit(io, fail2("invalid_input", "--days needs a positive number"));
|
|
77527
|
+
if (args.includes("--report")) {
|
|
77528
|
+
const report = usageReport(io.cwd, io.env, days);
|
|
77529
|
+
return emit(io, ok2(report), (data) => [
|
|
77530
|
+
`subagent models over the last ${data.days} days (${data.agents} agents)`,
|
|
77531
|
+
...Object.entries(data.types).flatMap(([type, use]) => [
|
|
77532
|
+
` ${type}${use.role ? ` (role ${use.role}, default ${use.defaults.join("/") || "host default"})` : ""}: ${Object.entries(use.models).map(([model, count]) => `${model} x${count}`).join(", ")}`,
|
|
77533
|
+
...use.flagged.map((model) => ` flag: ran on ${model}, not the role default`)
|
|
77534
|
+
])
|
|
77535
|
+
]);
|
|
77536
|
+
}
|
|
77420
77537
|
const envHost = actorFromEnv(io.env).host;
|
|
77421
77538
|
const host = hostFlag ?? (envHost === "cli" ? "claude_code" : envHost);
|
|
77422
77539
|
const row = (selector) => resolveRoleModel(io.cwd, selector, host) ?? { model: null, effort: null, source: "none" };
|
|
@@ -77439,13 +77556,73 @@ async function run13(argv, io) {
|
|
|
77439
77556
|
...(data.issues ?? []).map((issue) => `note: ${issue}`)
|
|
77440
77557
|
]);
|
|
77441
77558
|
}
|
|
77442
|
-
var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--json]", flag3 = (argv, name) => {
|
|
77559
|
+
var USAGE6 = "workit models show [--role <role>] [--tier <tier>] [--host <host>] [--report [--days <n>]] [--json]", flag3 = (argv, name) => {
|
|
77443
77560
|
const at = argv.findIndex((arg) => arg === name || arg.startsWith(`${name}=`));
|
|
77444
77561
|
if (at < 0)
|
|
77445
77562
|
return null;
|
|
77446
77563
|
const value = argv[at].includes("=") ? argv[at].slice(name.length + 1) : argv[at + 1];
|
|
77447
77564
|
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)"}
|
|
77565
|
+
}, line2 = (label, entry) => ` ${label}: ${entry.model ? `${entry.model}${entry.effort ? ` (effort ${entry.effort})` : ""} [${entry.source}]` : "host default (nothing configured)"}`, modelsOf = (file) => {
|
|
77566
|
+
const found = new Set;
|
|
77567
|
+
let text = "";
|
|
77568
|
+
try {
|
|
77569
|
+
text = readFileSync21(file, "utf8");
|
|
77570
|
+
} catch {
|
|
77571
|
+
return found;
|
|
77572
|
+
}
|
|
77573
|
+
for (const row of text.split(`
|
|
77574
|
+
`))
|
|
77575
|
+
if (row.includes('"type":"assistant"'))
|
|
77576
|
+
try {
|
|
77577
|
+
const model = JSON.parse(row).message?.model;
|
|
77578
|
+
if (typeof model === "string" && model && !model.startsWith("<"))
|
|
77579
|
+
found.add(model);
|
|
77580
|
+
} catch {}
|
|
77581
|
+
return found;
|
|
77582
|
+
}, matches3 = (ran, configured) => ran.toLowerCase().includes(configured.toLowerCase()), usageReport = (cwd, env, days) => {
|
|
77583
|
+
const projects = path51.join(env.CLAUDE_CONFIG_DIR || path51.join(env.HOME || os21.homedir(), ".claude"), "projects");
|
|
77584
|
+
const since = Date.now() - days * 86400000;
|
|
77585
|
+
const types = {};
|
|
77586
|
+
let agents = 0;
|
|
77587
|
+
const dirs = (dir) => {
|
|
77588
|
+
try {
|
|
77589
|
+
return readdirSync10(dir).map((name) => path51.join(dir, name));
|
|
77590
|
+
} catch {
|
|
77591
|
+
return [];
|
|
77592
|
+
}
|
|
77593
|
+
};
|
|
77594
|
+
for (const project of dirs(projects))
|
|
77595
|
+
for (const session of dirs(project))
|
|
77596
|
+
for (const meta of dirs(path51.join(session, "subagents")).filter((f) => f.endsWith(".meta.json"))) {
|
|
77597
|
+
try {
|
|
77598
|
+
if (statSync9(meta).mtimeMs < since)
|
|
77599
|
+
continue;
|
|
77600
|
+
const agentType = JSON.parse(readFileSync21(meta, "utf8")).agentType;
|
|
77601
|
+
const transcript = meta.replace(/\.meta\.json$/, ".jsonl");
|
|
77602
|
+
if (typeof agentType !== "string" || !existsSync21(transcript))
|
|
77603
|
+
continue;
|
|
77604
|
+
const ran = modelsOf(transcript);
|
|
77605
|
+
if (!ran.size)
|
|
77606
|
+
continue;
|
|
77607
|
+
agents += 1;
|
|
77608
|
+
const selector = roleForAgentType(agentType);
|
|
77609
|
+
const entry = types[agentType] ??= {
|
|
77610
|
+
role: selector?.role ?? null,
|
|
77611
|
+
defaults: selector ? [
|
|
77612
|
+
...new Set((selector.role === "implementer" ? MODEL_TIERS.map((tier) => ({ ...selector, tier })) : [selector]).flatMap((one) => resolveRoleModel(cwd, one, "claude_code")?.model ?? []))
|
|
77613
|
+
] : [],
|
|
77614
|
+
models: {},
|
|
77615
|
+
flagged: []
|
|
77616
|
+
};
|
|
77617
|
+
for (const model of ran) {
|
|
77618
|
+
entry.models[model] = (entry.models[model] ?? 0) + 1;
|
|
77619
|
+
if (entry.models[model] === 1 && entry.defaults.length && !entry.defaults.some((d) => matches3(model, d)))
|
|
77620
|
+
entry.flagged.push(model);
|
|
77621
|
+
}
|
|
77622
|
+
} catch {}
|
|
77623
|
+
}
|
|
77624
|
+
return { days, agents, types };
|
|
77625
|
+
};
|
|
77449
77626
|
var init_models = __esm(() => {
|
|
77450
77627
|
init_role_models();
|
|
77451
77628
|
init_ledger();
|
|
@@ -77561,8 +77738,8 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
77561
77738
|
|
|
77562
77739
|
// packages/workit-core/src/git/ops.ts
|
|
77563
77740
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
77564
|
-
import { existsSync as
|
|
77565
|
-
import
|
|
77741
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
|
|
77742
|
+
import path52 from "node:path";
|
|
77566
77743
|
function operationInProgress(cwd) {
|
|
77567
77744
|
const markers = [
|
|
77568
77745
|
["rebase-merge", "rebase"],
|
|
@@ -77575,18 +77752,18 @@ function operationInProgress(cwd) {
|
|
|
77575
77752
|
if (!run.ok)
|
|
77576
77753
|
return null;
|
|
77577
77754
|
const found = run.stdout.split(`
|
|
77578
|
-
`).map((line) =>
|
|
77755
|
+
`).map((line) => path52.resolve(cwd, line.trim()));
|
|
77579
77756
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
77580
77757
|
for (const [index, [, operation]] of markers.entries()) {
|
|
77581
77758
|
const marker = found[index];
|
|
77582
|
-
if (!marker || !
|
|
77759
|
+
if (!marker || !existsSync22(marker))
|
|
77583
77760
|
continue;
|
|
77584
|
-
if (index === 1 &&
|
|
77761
|
+
if (index === 1 && existsSync22(path52.join(marker, "applying")))
|
|
77585
77762
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
77586
|
-
if (index === 0 &&
|
|
77763
|
+
if (index === 0 && existsSync22(path52.join(marker, "amend")) && !conflicted()) {
|
|
77587
77764
|
let headName = "";
|
|
77588
77765
|
try {
|
|
77589
|
-
headName =
|
|
77766
|
+
headName = readFileSync22(path52.join(marker, "head-name"), "utf8").trim();
|
|
77590
77767
|
} catch {}
|
|
77591
77768
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
77592
77769
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -77914,7 +78091,7 @@ function gitCommit(cwd, input) {
|
|
|
77914
78091
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
77915
78092
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
77916
78093
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
77917
|
-
const addable = paths.filter((value) =>
|
|
78094
|
+
const addable = paths.filter((value) => existsSync22(path52.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
77918
78095
|
if (addable.length) {
|
|
77919
78096
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
77920
78097
|
if (!added.ok)
|
|
@@ -78441,12 +78618,12 @@ var init_ops = __esm(() => {
|
|
|
78441
78618
|
|
|
78442
78619
|
// packages/workit-core/src/verdict-cover.ts
|
|
78443
78620
|
import fs26 from "node:fs";
|
|
78444
|
-
import
|
|
78621
|
+
import path53 from "node:path";
|
|
78445
78622
|
function chainsAbove(cwd, branch) {
|
|
78446
78623
|
const root = storeRoot(cwd);
|
|
78447
78624
|
if (!root.ok)
|
|
78448
78625
|
return [];
|
|
78449
|
-
const dir =
|
|
78626
|
+
const dir = path53.join(root.value.root, "stacks");
|
|
78450
78627
|
let names = [];
|
|
78451
78628
|
try {
|
|
78452
78629
|
names = fs26.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
@@ -78457,7 +78634,7 @@ function chainsAbove(cwd, branch) {
|
|
|
78457
78634
|
for (const name of names.toSorted()) {
|
|
78458
78635
|
let parsed;
|
|
78459
78636
|
try {
|
|
78460
|
-
parsed = JSON.parse(fs26.readFileSync(
|
|
78637
|
+
parsed = JSON.parse(fs26.readFileSync(path53.join(dir, name), "utf8"));
|
|
78461
78638
|
} catch {
|
|
78462
78639
|
continue;
|
|
78463
78640
|
}
|
|
@@ -78552,10 +78729,10 @@ var init_pr_lane = __esm(() => {
|
|
|
78552
78729
|
|
|
78553
78730
|
// packages/workit-core/src/forge/reruns.ts
|
|
78554
78731
|
import fs27 from "node:fs";
|
|
78555
|
-
import
|
|
78732
|
+
import path54 from "node:path";
|
|
78556
78733
|
function rerunLogPath(cwd) {
|
|
78557
78734
|
const common = gitCommonDir(cwd);
|
|
78558
|
-
return common ?
|
|
78735
|
+
return common ? path54.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
78559
78736
|
}
|
|
78560
78737
|
function rerunCounts(cwd, key) {
|
|
78561
78738
|
const counts = new Map;
|
|
@@ -78590,7 +78767,7 @@ function recordReruns(cwd, rows) {
|
|
|
78590
78767
|
if (!file)
|
|
78591
78768
|
return false;
|
|
78592
78769
|
try {
|
|
78593
|
-
fs27.mkdirSync(
|
|
78770
|
+
fs27.mkdirSync(path54.dirname(file), { recursive: true });
|
|
78594
78771
|
fs27.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
78595
78772
|
`).join(""));
|
|
78596
78773
|
return true;
|
|
@@ -78603,7 +78780,7 @@ function withRerunLock(cwd, fn) {
|
|
|
78603
78780
|
if (!file)
|
|
78604
78781
|
return fn();
|
|
78605
78782
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
78606
|
-
fs27.mkdirSync(
|
|
78783
|
+
fs27.mkdirSync(path54.dirname(lock), { recursive: true });
|
|
78607
78784
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
78608
78785
|
for (;; ) {
|
|
78609
78786
|
try {
|
|
@@ -79518,7 +79695,7 @@ var init_pr_ops = __esm(() => {
|
|
|
79518
79695
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
79519
79696
|
import { createHash as createHash17, randomBytes as randomBytes4 } from "node:crypto";
|
|
79520
79697
|
import fs28 from "node:fs";
|
|
79521
|
-
import
|
|
79698
|
+
import path55 from "node:path";
|
|
79522
79699
|
function worktreeOf(cwd, branch) {
|
|
79523
79700
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
79524
79701
|
if (!list.ok)
|
|
@@ -79562,7 +79739,7 @@ function gitRestack(cwd, input) {
|
|
|
79562
79739
|
if (!scratch)
|
|
79563
79740
|
return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
|
|
79564
79741
|
fs28.mkdirSync(scratch, { recursive: true });
|
|
79565
|
-
dir =
|
|
79742
|
+
dir = path55.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
79566
79743
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
79567
79744
|
if (!added.ok)
|
|
79568
79745
|
return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
|
|
@@ -79603,7 +79780,7 @@ function pruneScratch(cwd) {
|
|
|
79603
79780
|
if (!scratch || !fs28.existsSync(scratch))
|
|
79604
79781
|
return;
|
|
79605
79782
|
for (const name of fs28.readdirSync(scratch)) {
|
|
79606
|
-
const dir =
|
|
79783
|
+
const dir = path55.join(scratch, name);
|
|
79607
79784
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
79608
79785
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
79609
79786
|
}
|
|
@@ -79613,7 +79790,7 @@ function stacksDir(cwd) {
|
|
|
79613
79790
|
const root = storeRoot(cwd);
|
|
79614
79791
|
if (!root.ok)
|
|
79615
79792
|
return stackFail(root.code, root.error, root.unblock);
|
|
79616
|
-
return { ok: true, data:
|
|
79793
|
+
return { ok: true, data: path55.join(root.value.root, "stacks") };
|
|
79617
79794
|
}
|
|
79618
79795
|
function parseStack(raw) {
|
|
79619
79796
|
if (!isRecord12(raw) || !Array.isArray(raw.branches))
|
|
@@ -79665,7 +79842,7 @@ function readStack(cwd, name) {
|
|
|
79665
79842
|
const dir = stacksDir(cwd);
|
|
79666
79843
|
if (!dir.ok)
|
|
79667
79844
|
return dir;
|
|
79668
|
-
const file =
|
|
79845
|
+
const file = path55.join(dir.data, fileFor(name));
|
|
79669
79846
|
let text;
|
|
79670
79847
|
try {
|
|
79671
79848
|
text = fs28.readFileSync(file, "utf8");
|
|
@@ -79686,7 +79863,7 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
79686
79863
|
const dir = stacksDir(cwd);
|
|
79687
79864
|
if (!dir.ok)
|
|
79688
79865
|
return dir;
|
|
79689
|
-
const file =
|
|
79866
|
+
const file = path55.join(dir.data, fileFor(stack.name));
|
|
79690
79867
|
const temp = `${file}.${process.pid}.tmp`;
|
|
79691
79868
|
try {
|
|
79692
79869
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
@@ -79714,7 +79891,7 @@ function listStacks(cwd) {
|
|
|
79714
79891
|
for (const name of names) {
|
|
79715
79892
|
let parsed = null;
|
|
79716
79893
|
try {
|
|
79717
|
-
parsed = parseStack(JSON.parse(fs28.readFileSync(
|
|
79894
|
+
parsed = parseStack(JSON.parse(fs28.readFileSync(path55.join(dir.data, name), "utf8")));
|
|
79718
79895
|
} catch {
|
|
79719
79896
|
parsed = null;
|
|
79720
79897
|
}
|
|
@@ -79773,7 +79950,7 @@ function takeLock(lock) {
|
|
|
79773
79950
|
host: localLockHost(),
|
|
79774
79951
|
nonce: randomBytes4(8).toString("hex")
|
|
79775
79952
|
};
|
|
79776
|
-
fs28.writeFileSync(
|
|
79953
|
+
fs28.writeFileSync(path55.join(lock, OWNER), JSON.stringify(owner));
|
|
79777
79954
|
return owner;
|
|
79778
79955
|
}
|
|
79779
79956
|
function reapLock(lock, observed) {
|
|
@@ -79810,7 +79987,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
79810
79987
|
return dir;
|
|
79811
79988
|
if (!validName(name))
|
|
79812
79989
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
79813
|
-
const lock =
|
|
79990
|
+
const lock = path55.join(dir.data, `${fileFor(name)}.lock`);
|
|
79814
79991
|
try {
|
|
79815
79992
|
fs28.mkdirSync(dir.data, { recursive: true });
|
|
79816
79993
|
} catch (error) {
|
|
@@ -79840,7 +80017,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
79840
80017
|
const touch = () => {
|
|
79841
80018
|
try {
|
|
79842
80019
|
const now = new Date;
|
|
79843
|
-
fs28.utimesSync(
|
|
80020
|
+
fs28.utimesSync(path55.join(lock, OWNER), now, now);
|
|
79844
80021
|
} catch {}
|
|
79845
80022
|
};
|
|
79846
80023
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -80691,7 +80868,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
80691
80868
|
return !status.ok || status.stdout.trim() !== "";
|
|
80692
80869
|
}, scratchDir = (cwd) => {
|
|
80693
80870
|
const dir = stacksDir(cwd);
|
|
80694
|
-
return dir.ok ?
|
|
80871
|
+
return dir.ok ? path55.join(dir.data, "worktrees") : null;
|
|
80695
80872
|
}, firstLine = (run) => (`${run.stderr}
|
|
80696
80873
|
${run.stdout}`.split(`
|
|
80697
80874
|
`).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 +80883,12 @@ ${run.stdout}`.split(`
|
|
|
80706
80883
|
}, 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
80884
|
let raw = null;
|
|
80708
80885
|
try {
|
|
80709
|
-
raw = fs28.readFileSync(
|
|
80886
|
+
raw = fs28.readFileSync(path55.join(lock, OWNER), "utf8");
|
|
80710
80887
|
} catch {
|
|
80711
80888
|
raw = null;
|
|
80712
80889
|
}
|
|
80713
80890
|
let age = null;
|
|
80714
|
-
for (const target of [
|
|
80891
|
+
for (const target of [path55.join(lock, OWNER), lock])
|
|
80715
80892
|
try {
|
|
80716
80893
|
age = Date.now() - fs28.statSync(target).mtimeMs;
|
|
80717
80894
|
break;
|
|
@@ -80754,7 +80931,7 @@ var init_stack = __esm(() => {
|
|
|
80754
80931
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
80755
80932
|
import { createHash as createHash18 } from "node:crypto";
|
|
80756
80933
|
import fs29 from "node:fs";
|
|
80757
|
-
import
|
|
80934
|
+
import path56 from "node:path";
|
|
80758
80935
|
function expandBraces2(pattern, limit = 64) {
|
|
80759
80936
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
80760
80937
|
if (pattern[index] === "\\") {
|
|
@@ -81000,7 +81177,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
81000
81177
|
id,
|
|
81001
81178
|
branch,
|
|
81002
81179
|
base: optional("base") ?? "",
|
|
81003
|
-
worktree:
|
|
81180
|
+
worktree: path56.resolve(defaults.root, optional("worktree") ?? path56.join(defaults.worktreeRoot, id)),
|
|
81004
81181
|
tier,
|
|
81005
81182
|
reason,
|
|
81006
81183
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
@@ -81231,11 +81408,11 @@ function defaultTrunk(cwd) {
|
|
|
81231
81408
|
}
|
|
81232
81409
|
function mainCheckout(cwd) {
|
|
81233
81410
|
const common = gitCommonDir(cwd);
|
|
81234
|
-
return common &&
|
|
81411
|
+
return common && path56.basename(common) === ".git" ? path56.dirname(common) : path56.resolve(cwd);
|
|
81235
81412
|
}
|
|
81236
81413
|
function worktreeRoot(cwd) {
|
|
81237
81414
|
const main = mainCheckout(cwd);
|
|
81238
|
-
return
|
|
81415
|
+
return path56.join(path56.dirname(main), `${path56.basename(main)}-wt`);
|
|
81239
81416
|
}
|
|
81240
81417
|
function sliceHash(slice) {
|
|
81241
81418
|
const {
|
|
@@ -81255,7 +81432,7 @@ function fanoutsDir(cwd) {
|
|
|
81255
81432
|
const root = storeRoot(cwd);
|
|
81256
81433
|
if (!root.ok)
|
|
81257
81434
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
81258
|
-
return { ok: true, data:
|
|
81435
|
+
return { ok: true, data: path56.join(root.value.root, "fanouts") };
|
|
81259
81436
|
}
|
|
81260
81437
|
function parseStored(raw) {
|
|
81261
81438
|
if (!isRecord13(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -81323,7 +81500,7 @@ function readFanout(cwd, name) {
|
|
|
81323
81500
|
const dir = fanoutsDir(cwd);
|
|
81324
81501
|
if (!dir.ok)
|
|
81325
81502
|
return dir;
|
|
81326
|
-
const file =
|
|
81503
|
+
const file = path56.join(dir.data, stackFileName(name));
|
|
81327
81504
|
let parsed = null;
|
|
81328
81505
|
try {
|
|
81329
81506
|
parsed = parseStored(JSON.parse(fs29.readFileSync(file, "utf8")));
|
|
@@ -81348,7 +81525,7 @@ function listFanouts(cwd) {
|
|
|
81348
81525
|
for (const entry of names) {
|
|
81349
81526
|
let parsed = null;
|
|
81350
81527
|
try {
|
|
81351
|
-
parsed = parseStored(JSON.parse(fs29.readFileSync(
|
|
81528
|
+
parsed = parseStored(JSON.parse(fs29.readFileSync(path56.join(dir.data, entry), "utf8")));
|
|
81352
81529
|
} catch {
|
|
81353
81530
|
parsed = null;
|
|
81354
81531
|
}
|
|
@@ -81387,7 +81564,7 @@ function writeFanout(cwd, plan) {
|
|
|
81387
81564
|
const dir = fanoutsDir(cwd);
|
|
81388
81565
|
if (!dir.ok)
|
|
81389
81566
|
return dir;
|
|
81390
|
-
const file =
|
|
81567
|
+
const file = path56.join(dir.data, stackFileName(plan.name));
|
|
81391
81568
|
const temp = `${file}.${process.pid}.tmp`;
|
|
81392
81569
|
try {
|
|
81393
81570
|
fs29.mkdirSync(dir.data, { recursive: true });
|
|
@@ -81594,13 +81771,13 @@ var init_fanout = __esm(() => {
|
|
|
81594
81771
|
// packages/workit-core/src/forge/exec.ts
|
|
81595
81772
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
81596
81773
|
import fs30 from "node:fs";
|
|
81597
|
-
import
|
|
81774
|
+
import path57 from "node:path";
|
|
81598
81775
|
function findExecutable(bin, env) {
|
|
81599
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
81776
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path57.delimiter).filter(Boolean);
|
|
81600
81777
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
81601
81778
|
for (const dir of dirs)
|
|
81602
81779
|
for (const ext of exts) {
|
|
81603
|
-
const candidate =
|
|
81780
|
+
const candidate = path57.join(dir, `${bin}${ext}`);
|
|
81604
81781
|
try {
|
|
81605
81782
|
const stat = fs30.statSync(candidate);
|
|
81606
81783
|
if (stat.isFile())
|
|
@@ -83344,7 +83521,7 @@ var init_duration = __esm(() => {
|
|
|
83344
83521
|
});
|
|
83345
83522
|
|
|
83346
83523
|
// packages/workit-cli/src/verbs/forge-common.ts
|
|
83347
|
-
import { readFileSync as
|
|
83524
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
83348
83525
|
function parseFlags(argv, spec) {
|
|
83349
83526
|
const parsed = { values: {}, booleans: new Set, lists: {}, positionals: [] };
|
|
83350
83527
|
for (let index = 0;index < argv.length; index += 1) {
|
|
@@ -83488,7 +83665,7 @@ var init_forge_common = __esm(() => {
|
|
|
83488
83665
|
forgeDeps = {
|
|
83489
83666
|
runner: undefined,
|
|
83490
83667
|
npm: undefined,
|
|
83491
|
-
readStdin: () =>
|
|
83668
|
+
readStdin: () => readFileSync23(0, "utf8"),
|
|
83492
83669
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
83493
83670
|
now: () => Date.now()
|
|
83494
83671
|
};
|
|
@@ -83499,12 +83676,12 @@ var exports_pr = {};
|
|
|
83499
83676
|
__export(exports_pr, {
|
|
83500
83677
|
run: () => run14
|
|
83501
83678
|
});
|
|
83502
|
-
import { readFileSync as
|
|
83503
|
-
import
|
|
83679
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
83680
|
+
import path58 from "node:path";
|
|
83504
83681
|
function readBodyFile(io, file) {
|
|
83505
83682
|
try {
|
|
83506
83683
|
return {
|
|
83507
|
-
body: file === "-" ? forgeDeps.readStdin() :
|
|
83684
|
+
body: file === "-" ? forgeDeps.readStdin() : readFileSync24(path58.resolve(io.cwd, file), "utf8")
|
|
83508
83685
|
};
|
|
83509
83686
|
} catch {
|
|
83510
83687
|
return `cannot read --body-file ${file}`;
|
|
@@ -84209,8 +84386,8 @@ var exports_git = {};
|
|
|
84209
84386
|
__export(exports_git, {
|
|
84210
84387
|
run: () => run16
|
|
84211
84388
|
});
|
|
84212
|
-
import { readFileSync as
|
|
84213
|
-
import
|
|
84389
|
+
import { readFileSync as readFileSync25 } from "node:fs";
|
|
84390
|
+
import path59 from "node:path";
|
|
84214
84391
|
function kindHint(cwd, kind) {
|
|
84215
84392
|
let kinds = [...BRANCH_KINDS];
|
|
84216
84393
|
try {
|
|
@@ -84314,7 +84491,7 @@ function commitMessage(parsed, io) {
|
|
|
84314
84491
|
|
|
84315
84492
|
`);
|
|
84316
84493
|
try {
|
|
84317
|
-
return file === "-" ?
|
|
84494
|
+
return file === "-" ? readFileSync25(0, "utf8") : readFileSync25(path59.resolve(io.cwd, file), "utf8");
|
|
84318
84495
|
} catch (error) {
|
|
84319
84496
|
return {
|
|
84320
84497
|
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -85735,7 +85912,7 @@ var init_live_session = __esm(() => {
|
|
|
85735
85912
|
});
|
|
85736
85913
|
|
|
85737
85914
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
85738
|
-
import
|
|
85915
|
+
import path60 from "node:path";
|
|
85739
85916
|
var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
|
|
85740
85917
|
var init_write_gate = __esm(() => {
|
|
85741
85918
|
init_task_store();
|
|
@@ -85775,7 +85952,7 @@ var init_write_gate = __esm(() => {
|
|
|
85775
85952
|
CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
85776
85953
|
PUSHD2 = new Set(["pushd", "push-location"]);
|
|
85777
85954
|
POPD2 = new Set(["popd", "pop-location"]);
|
|
85778
|
-
UNKNOWN_DIR =
|
|
85955
|
+
UNKNOWN_DIR = path60.resolve(path60.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
85779
85956
|
});
|
|
85780
85957
|
|
|
85781
85958
|
// packages/workit-core/src/hooks/worktree-confine.ts
|
|
@@ -85800,20 +85977,20 @@ var init_worktree_confine = __esm(() => {
|
|
|
85800
85977
|
|
|
85801
85978
|
// packages/workit-core/src/worktree-deps.ts
|
|
85802
85979
|
import fs32 from "node:fs";
|
|
85803
|
-
import
|
|
85980
|
+
import path61 from "node:path";
|
|
85804
85981
|
function moduleDirs(main) {
|
|
85805
85982
|
const out = [];
|
|
85806
85983
|
const walk = (relative, depth) => {
|
|
85807
85984
|
let entries;
|
|
85808
85985
|
try {
|
|
85809
|
-
entries = fs32.readdirSync(
|
|
85986
|
+
entries = fs32.readdirSync(path61.join(main, relative), { withFileTypes: true });
|
|
85810
85987
|
} catch {
|
|
85811
85988
|
return;
|
|
85812
85989
|
}
|
|
85813
85990
|
for (const entry of entries) {
|
|
85814
85991
|
if (!entry.isDirectory())
|
|
85815
85992
|
continue;
|
|
85816
|
-
const child =
|
|
85993
|
+
const child = path61.join(relative, entry.name);
|
|
85817
85994
|
if (entry.name === MODULES)
|
|
85818
85995
|
out.push(child);
|
|
85819
85996
|
else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
|
|
@@ -85827,8 +86004,8 @@ function linkEntry(main, worktree, source, target) {
|
|
|
85827
86004
|
const stat = fs32.lstatSync(source);
|
|
85828
86005
|
if (stat.isSymbolicLink()) {
|
|
85829
86006
|
const link = fs32.readlinkSync(source);
|
|
85830
|
-
const outside =
|
|
85831
|
-
const to = outside ?
|
|
86007
|
+
const outside = path61.isAbsolute(link) && within(link, main) && !path61.relative(main, link).split(path61.sep).includes(MODULES);
|
|
86008
|
+
const to = outside ? path61.join(worktree, path61.relative(main, link)) : link;
|
|
85832
86009
|
fs32.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
|
|
85833
86010
|
return;
|
|
85834
86011
|
}
|
|
@@ -85838,8 +86015,8 @@ function mirror(main, worktree, source, target, top) {
|
|
|
85838
86015
|
fs32.mkdirSync(target);
|
|
85839
86016
|
let count = 0;
|
|
85840
86017
|
for (const entry of fs32.readdirSync(source, { withFileTypes: true })) {
|
|
85841
|
-
const from =
|
|
85842
|
-
const to =
|
|
86018
|
+
const from = path61.join(source, entry.name);
|
|
86019
|
+
const to = path61.join(target, entry.name);
|
|
85843
86020
|
if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
|
|
85844
86021
|
count += mirror(main, worktree, from, to, false);
|
|
85845
86022
|
else {
|
|
@@ -85855,16 +86032,16 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
85855
86032
|
const dirs = [];
|
|
85856
86033
|
let entries = 0;
|
|
85857
86034
|
for (const relative of moduleDirs(main)) {
|
|
85858
|
-
const target =
|
|
85859
|
-
if (!fs32.existsSync(
|
|
86035
|
+
const target = path61.join(worktree, relative);
|
|
86036
|
+
if (!fs32.existsSync(path61.dirname(target)) || fs32.existsSync(target))
|
|
85860
86037
|
continue;
|
|
85861
|
-
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(
|
|
85862
|
-
notes.push(`${relative.split(
|
|
86038
|
+
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path61.sep).join("/")}/`]).ok) {
|
|
86039
|
+
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
86040
|
continue;
|
|
85864
86041
|
}
|
|
85865
86042
|
try {
|
|
85866
|
-
entries += mirror(main, worktree,
|
|
85867
|
-
dirs.push(relative.split(
|
|
86043
|
+
entries += mirror(main, worktree, path61.join(main, relative), target, true);
|
|
86044
|
+
dirs.push(relative.split(path61.sep).join("/"));
|
|
85868
86045
|
} catch (error) {
|
|
85869
86046
|
fs32.rmSync(target, { recursive: true, force: true });
|
|
85870
86047
|
notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
|
|
@@ -85877,8 +86054,8 @@ function linkWorktreeDependencies(main, worktree) {
|
|
|
85877
86054
|
return { linked: { from: main, dirs, entries, ms }, notes };
|
|
85878
86055
|
}
|
|
85879
86056
|
var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
|
|
85880
|
-
const relative =
|
|
85881
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86057
|
+
const relative = path61.relative(parent, child);
|
|
86058
|
+
return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
|
|
85882
86059
|
};
|
|
85883
86060
|
var init_worktree_deps = __esm(() => {
|
|
85884
86061
|
init_fanout();
|
|
@@ -85887,7 +86064,7 @@ var init_worktree_deps = __esm(() => {
|
|
|
85887
86064
|
// packages/workit-core/src/fanout-worktree.ts
|
|
85888
86065
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
85889
86066
|
import fs33 from "node:fs";
|
|
85890
|
-
import
|
|
86067
|
+
import path62 from "node:path";
|
|
85891
86068
|
function rowSample(lines) {
|
|
85892
86069
|
const out = [];
|
|
85893
86070
|
let bytes = 0;
|
|
@@ -85947,7 +86124,7 @@ function adminDir(worktree) {
|
|
|
85947
86124
|
const file = dir.stdout.trim();
|
|
85948
86125
|
let token = null;
|
|
85949
86126
|
try {
|
|
85950
|
-
token = fs33.readFileSync(
|
|
86127
|
+
token = fs33.readFileSync(path62.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
|
|
85951
86128
|
} catch {
|
|
85952
86129
|
token = null;
|
|
85953
86130
|
}
|
|
@@ -85955,7 +86132,7 @@ function adminDir(worktree) {
|
|
|
85955
86132
|
const stat = worktreeDeps.stat(file);
|
|
85956
86133
|
return {
|
|
85957
86134
|
path: file,
|
|
85958
|
-
id:
|
|
86135
|
+
id: path62.basename(file),
|
|
85959
86136
|
ino: stat.ino.toString(),
|
|
85960
86137
|
token,
|
|
85961
86138
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -85971,7 +86148,7 @@ function markAdminDir(worktree) {
|
|
|
85971
86148
|
return null;
|
|
85972
86149
|
const token = randomBytes5(16).toString("hex");
|
|
85973
86150
|
try {
|
|
85974
|
-
fs33.writeFileSync(
|
|
86151
|
+
fs33.writeFileSync(path62.join(admin.path, FANOUT_TOKEN_FILE), `${token}
|
|
85975
86152
|
`);
|
|
85976
86153
|
} catch {
|
|
85977
86154
|
return null;
|
|
@@ -85986,7 +86163,7 @@ function excludeScratch(cwd) {
|
|
|
85986
86163
|
const common = gitCommonDir(cwd);
|
|
85987
86164
|
if (!common)
|
|
85988
86165
|
return;
|
|
85989
|
-
const file =
|
|
86166
|
+
const file = path62.join(common, "info", "exclude");
|
|
85990
86167
|
let text = "";
|
|
85991
86168
|
try {
|
|
85992
86169
|
text = fs33.readFileSync(file, "utf8");
|
|
@@ -85995,7 +86172,7 @@ function excludeScratch(cwd) {
|
|
|
85995
86172
|
}
|
|
85996
86173
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
85997
86174
|
return;
|
|
85998
|
-
fs33.mkdirSync(
|
|
86175
|
+
fs33.mkdirSync(path62.dirname(file), { recursive: true });
|
|
85999
86176
|
fs33.appendFileSync(file, `${text && !text.endsWith(`
|
|
86000
86177
|
`) ? `
|
|
86001
86178
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
@@ -86003,7 +86180,7 @@ ${EXCLUDE_LINE}
|
|
|
86003
86180
|
`);
|
|
86004
86181
|
}
|
|
86005
86182
|
function ensureScratch(worktree) {
|
|
86006
|
-
const scratch =
|
|
86183
|
+
const scratch = path62.join(worktree, SCRATCH_DIR);
|
|
86007
86184
|
fs33.mkdirSync(scratch, { recursive: true });
|
|
86008
86185
|
return scratch;
|
|
86009
86186
|
}
|
|
@@ -86231,7 +86408,7 @@ function unpushedCount(cwd, branch) {
|
|
|
86231
86408
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
86232
86409
|
}
|
|
86233
86410
|
function removeScratch(worktree) {
|
|
86234
|
-
const scratch =
|
|
86411
|
+
const scratch = path62.join(worktree, SCRATCH_DIR);
|
|
86235
86412
|
let stat;
|
|
86236
86413
|
try {
|
|
86237
86414
|
stat = fs33.lstatSync(scratch);
|
|
@@ -86247,16 +86424,16 @@ var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000,
|
|
|
86247
86424
|
try {
|
|
86248
86425
|
return fs33.realpathSync.native(target);
|
|
86249
86426
|
} catch {
|
|
86250
|
-
return
|
|
86427
|
+
return path62.resolve(target);
|
|
86251
86428
|
}
|
|
86252
86429
|
}, samePath = (a, b) => {
|
|
86253
86430
|
const left = canonical2(a);
|
|
86254
86431
|
const right = canonical2(b);
|
|
86255
86432
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
86256
86433
|
}, inside3 = (child, parent) => {
|
|
86257
|
-
const relative =
|
|
86258
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
86259
|
-
}, slicePath = (cwd, slice) =>
|
|
86434
|
+
const relative = path62.relative(canonical2(parent), canonical2(child));
|
|
86435
|
+
return relative === "" || !relative.startsWith("..") && !path62.isAbsolute(relative);
|
|
86436
|
+
}, 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
86437
|
`)[0] || "unknown error"}`);
|
|
86261
86438
|
var init_fanout_worktree = __esm(() => {
|
|
86262
86439
|
init_ops();
|
|
@@ -87092,7 +87269,7 @@ __export(exports_fanout, {
|
|
|
87092
87269
|
run: () => run20
|
|
87093
87270
|
});
|
|
87094
87271
|
import fs34 from "node:fs";
|
|
87095
|
-
import
|
|
87272
|
+
import path63 from "node:path";
|
|
87096
87273
|
function forgeFor(io, offline) {
|
|
87097
87274
|
if (offline)
|
|
87098
87275
|
return { forge: null, error: "--offline" };
|
|
@@ -87153,7 +87330,7 @@ function plan2(argv, io) {
|
|
|
87153
87330
|
return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
87154
87331
|
if (flags.positionals.length !== 1)
|
|
87155
87332
|
return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
87156
|
-
const file =
|
|
87333
|
+
const file = path63.resolve(io.cwd, flags.positionals[0]);
|
|
87157
87334
|
let raw;
|
|
87158
87335
|
try {
|
|
87159
87336
|
raw = JSON.parse(fs34.readFileSync(file, "utf8"));
|
|
@@ -102692,7 +102869,7 @@ var init_ast = __esm(() => {
|
|
|
102692
102869
|
|
|
102693
102870
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
102694
102871
|
import { builtinModules } from "node:module";
|
|
102695
|
-
import
|
|
102872
|
+
import path64 from "node:path";
|
|
102696
102873
|
function testCallee(call) {
|
|
102697
102874
|
let callee = call.callee;
|
|
102698
102875
|
if (callee.type === "CallExpression")
|
|
@@ -103185,12 +103362,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
103185
103362
|
}
|
|
103186
103363
|
function checkOverMocking(ctx, emit) {
|
|
103187
103364
|
const { program } = ctx.parsed;
|
|
103188
|
-
const unit =
|
|
103365
|
+
const unit = path64.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
103189
103366
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
103190
103367
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
103191
103368
|
for (const call of mocked) {
|
|
103192
103369
|
const spec = call.arguments[0].value;
|
|
103193
|
-
const base =
|
|
103370
|
+
const base = path64.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
103194
103371
|
if (base === unit)
|
|
103195
103372
|
emit({
|
|
103196
103373
|
rule: "over-mocking",
|
|
@@ -103579,8 +103756,8 @@ var init_rules = __esm(() => {
|
|
|
103579
103756
|
|
|
103580
103757
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
103581
103758
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
103582
|
-
import { existsSync as
|
|
103583
|
-
import
|
|
103759
|
+
import { existsSync as existsSync23, readdirSync as readdirSync11, readFileSync as readFileSync26, statSync as statSync10 } from "node:fs";
|
|
103760
|
+
import path65 from "node:path";
|
|
103584
103761
|
function git7(cwd, args) {
|
|
103585
103762
|
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
103586
103763
|
cwd,
|
|
@@ -103590,10 +103767,10 @@ function git7(cwd, args) {
|
|
|
103590
103767
|
return { ok: run.status === 0, stdout: run.stdout ?? "" };
|
|
103591
103768
|
}
|
|
103592
103769
|
function walkTests(dir, out) {
|
|
103593
|
-
for (const entry of
|
|
103770
|
+
for (const entry of readdirSync11(dir, { withFileTypes: true })) {
|
|
103594
103771
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
103595
103772
|
continue;
|
|
103596
|
-
const full =
|
|
103773
|
+
const full = path65.join(dir, entry.name);
|
|
103597
103774
|
if (entry.isDirectory()) {
|
|
103598
103775
|
if (!SKIP_DIRS.has(entry.name))
|
|
103599
103776
|
walkTests(full, out);
|
|
@@ -103605,10 +103782,10 @@ function expandPaths(cwd, inputs) {
|
|
|
103605
103782
|
const files = [];
|
|
103606
103783
|
const missing = [];
|
|
103607
103784
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
103608
|
-
const full =
|
|
103609
|
-
if (!
|
|
103785
|
+
const full = path65.resolve(cwd, input);
|
|
103786
|
+
if (!existsSync23(full))
|
|
103610
103787
|
missing.push(input);
|
|
103611
|
-
else if (
|
|
103788
|
+
else if (statSync10(full).isDirectory())
|
|
103612
103789
|
walkTests(full, files);
|
|
103613
103790
|
else
|
|
103614
103791
|
files.push(full);
|
|
@@ -103642,11 +103819,11 @@ function changedLines(cwd, base) {
|
|
|
103642
103819
|
for (let offset = 0;offset < count; offset += 1)
|
|
103643
103820
|
lines.add(start + offset);
|
|
103644
103821
|
}
|
|
103645
|
-
changed.set(
|
|
103822
|
+
changed.set(path65.join(root, file), lines);
|
|
103646
103823
|
}
|
|
103647
103824
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
103648
103825
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
103649
|
-
changed.set(
|
|
103826
|
+
changed.set(path65.join(root, file), "all");
|
|
103650
103827
|
return changed;
|
|
103651
103828
|
}
|
|
103652
103829
|
function auditFiles(files, display) {
|
|
@@ -103659,7 +103836,7 @@ function auditFiles(files, display) {
|
|
|
103659
103836
|
const shown = display(file);
|
|
103660
103837
|
let parsed;
|
|
103661
103838
|
try {
|
|
103662
|
-
parsed = parseSource(
|
|
103839
|
+
parsed = parseSource(readFileSync26(file, "utf8"), file);
|
|
103663
103840
|
} catch (error) {
|
|
103664
103841
|
parseErrors.push({
|
|
103665
103842
|
file: shown,
|
|
@@ -103708,7 +103885,7 @@ function auditFiles(files, display) {
|
|
|
103708
103885
|
durationMs: Math.round(performance.now() - started)
|
|
103709
103886
|
};
|
|
103710
103887
|
}
|
|
103711
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
103888
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path65.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
103712
103889
|
var init_audit = __esm(() => {
|
|
103713
103890
|
init_ast();
|
|
103714
103891
|
init_rules();
|
|
@@ -103722,23 +103899,23 @@ var init_audit = __esm(() => {
|
|
|
103722
103899
|
// packages/workit-cli/src/test-audit/mutate.ts
|
|
103723
103900
|
import { spawn as spawn2 } from "node:child_process";
|
|
103724
103901
|
import {
|
|
103725
|
-
existsSync as
|
|
103902
|
+
existsSync as existsSync24,
|
|
103726
103903
|
lstatSync as lstatSync8,
|
|
103727
103904
|
mkdirSync as mkdirSync11,
|
|
103728
103905
|
mkdtempSync as mkdtempSync4,
|
|
103729
|
-
readdirSync as
|
|
103730
|
-
readFileSync as
|
|
103906
|
+
readdirSync as readdirSync12,
|
|
103907
|
+
readFileSync as readFileSync27,
|
|
103731
103908
|
readlinkSync as readlinkSync3,
|
|
103732
103909
|
realpathSync as realpathSync10,
|
|
103733
103910
|
renameSync as renameSync7,
|
|
103734
103911
|
rmSync as rmSync9,
|
|
103735
|
-
statSync as
|
|
103912
|
+
statSync as statSync11,
|
|
103736
103913
|
symlinkSync,
|
|
103737
103914
|
writeFileSync as writeFileSync11,
|
|
103738
103915
|
copyFileSync as copyFileSync7
|
|
103739
103916
|
} from "node:fs";
|
|
103740
|
-
import
|
|
103741
|
-
import
|
|
103917
|
+
import os22 from "node:os";
|
|
103918
|
+
import path66 from "node:path";
|
|
103742
103919
|
function mutantsFor(source, file, lines) {
|
|
103743
103920
|
const parsed = parseSource(source, file);
|
|
103744
103921
|
const out = [];
|
|
@@ -103811,7 +103988,7 @@ function relatedTests(source, testFiles) {
|
|
|
103811
103988
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
103812
103989
|
const spec = match[1];
|
|
103813
103990
|
if (spec.startsWith(".")) {
|
|
103814
|
-
if (stripExt(
|
|
103991
|
+
if (stripExt(path66.posix.join(path66.posix.dirname(file), spec)) === target)
|
|
103815
103992
|
return true;
|
|
103816
103993
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
103817
103994
|
return true;
|
|
@@ -103819,11 +103996,11 @@ function relatedTests(source, testFiles) {
|
|
|
103819
103996
|
return false;
|
|
103820
103997
|
}).map((entry) => entry.file);
|
|
103821
103998
|
}
|
|
103822
|
-
function removeStaleCopies(tmp =
|
|
103999
|
+
function removeStaleCopies(tmp = os22.tmpdir()) {
|
|
103823
104000
|
let removed = 0;
|
|
103824
104001
|
let names = [];
|
|
103825
104002
|
try {
|
|
103826
|
-
names =
|
|
104003
|
+
names = readdirSync12(tmp);
|
|
103827
104004
|
} catch {
|
|
103828
104005
|
return 0;
|
|
103829
104006
|
}
|
|
@@ -103831,12 +104008,12 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
|
|
|
103831
104008
|
for (const name of names) {
|
|
103832
104009
|
if (!name.startsWith(TEMP_PREFIX))
|
|
103833
104010
|
continue;
|
|
103834
|
-
const dir =
|
|
104011
|
+
const dir = path66.join(tmp, name);
|
|
103835
104012
|
try {
|
|
103836
104013
|
const stat = lstatSync8(dir);
|
|
103837
104014
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
103838
104015
|
continue;
|
|
103839
|
-
const pid = Number(
|
|
104016
|
+
const pid = Number(readFileSync27(path66.join(dir, PID_FILE), "utf8"));
|
|
103840
104017
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
103841
104018
|
continue;
|
|
103842
104019
|
} catch (error) {
|
|
@@ -103852,9 +104029,9 @@ function removeStaleCopies(tmp = os21.tmpdir()) {
|
|
|
103852
104029
|
}
|
|
103853
104030
|
function linkNodeModules(origin, target, repo, copy) {
|
|
103854
104031
|
mkdirSync11(target, { recursive: true });
|
|
103855
|
-
for (const entry of
|
|
103856
|
-
const from =
|
|
103857
|
-
const to =
|
|
104032
|
+
for (const entry of readdirSync12(origin, { withFileTypes: true })) {
|
|
104033
|
+
const from = path66.join(origin, entry.name);
|
|
104034
|
+
const to = path66.join(target, entry.name);
|
|
103858
104035
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
103859
104036
|
linkNodeModules(from, to, repo, copy);
|
|
103860
104037
|
continue;
|
|
@@ -103870,9 +104047,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
103870
104047
|
} catch {
|
|
103871
104048
|
continue;
|
|
103872
104049
|
}
|
|
103873
|
-
const relative =
|
|
103874
|
-
if (!relative.startsWith("..") && !
|
|
103875
|
-
symlinkSync(
|
|
104050
|
+
const relative = path66.relative(repo, real);
|
|
104051
|
+
if (!relative.startsWith("..") && !path66.isAbsolute(relative) && !relative.split(path66.sep).includes("node_modules")) {
|
|
104052
|
+
symlinkSync(path66.join(copy, relative), to, "junction");
|
|
103876
104053
|
continue;
|
|
103877
104054
|
}
|
|
103878
104055
|
}
|
|
@@ -103888,19 +104065,19 @@ function copySymlink(repo, tree, from, to) {
|
|
|
103888
104065
|
}
|
|
103889
104066
|
const realRepo = realpathSync10(repo);
|
|
103890
104067
|
if (real && inside4(realRepo, real)) {
|
|
103891
|
-
symlinkSync(
|
|
104068
|
+
symlinkSync(path66.relative(path66.dirname(to), path66.join(tree, path66.relative(realRepo, real))), to);
|
|
103892
104069
|
return;
|
|
103893
104070
|
}
|
|
103894
|
-
if (real &&
|
|
104071
|
+
if (real && statSync11(real).isFile())
|
|
103895
104072
|
copyFileSync7(real, to);
|
|
103896
104073
|
else
|
|
103897
104074
|
symlinkSync(readlinkSync3(from), to);
|
|
103898
104075
|
}
|
|
103899
104076
|
function writeInside(copy, file, content) {
|
|
103900
|
-
const target =
|
|
104077
|
+
const target = path66.join(copy, file);
|
|
103901
104078
|
try {
|
|
103902
104079
|
const stat = lstatSync8(target);
|
|
103903
|
-
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(
|
|
104080
|
+
if (!stat.isFile() || !inside4(realpathSync10(copy), realpathSync10(path66.dirname(target))))
|
|
103904
104081
|
return false;
|
|
103905
104082
|
} catch {
|
|
103906
104083
|
return false;
|
|
@@ -103911,9 +104088,9 @@ function writeInside(copy, file, content) {
|
|
|
103911
104088
|
return true;
|
|
103912
104089
|
}
|
|
103913
104090
|
function copyWorkingTree(repo) {
|
|
103914
|
-
const dir = mkdtempSync4(
|
|
103915
|
-
writeFileSync11(
|
|
103916
|
-
const tree =
|
|
104091
|
+
const dir = mkdtempSync4(path66.join(os22.tmpdir(), TEMP_PREFIX));
|
|
104092
|
+
writeFileSync11(path66.join(dir, PID_FILE), String(process.pid));
|
|
104093
|
+
const tree = path66.join(dir, "tree");
|
|
103917
104094
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
103918
104095
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
103919
104096
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -103930,29 +104107,29 @@ function copyWorkingTree(repo) {
|
|
|
103930
104107
|
for (const relative of listed) {
|
|
103931
104108
|
if (!relative)
|
|
103932
104109
|
continue;
|
|
103933
|
-
const from =
|
|
104110
|
+
const from = path66.join(repo, relative);
|
|
103934
104111
|
let stat;
|
|
103935
104112
|
try {
|
|
103936
104113
|
stat = lstatSync8(from);
|
|
103937
104114
|
} catch {
|
|
103938
104115
|
continue;
|
|
103939
104116
|
}
|
|
103940
|
-
const to =
|
|
103941
|
-
mkdirSync11(
|
|
104117
|
+
const to = path66.join(tree, relative);
|
|
104118
|
+
mkdirSync11(path66.dirname(to), { recursive: true });
|
|
103942
104119
|
if (stat.isSymbolicLink())
|
|
103943
104120
|
copySymlink(repo, tree, from, to);
|
|
103944
104121
|
else if (stat.isFile())
|
|
103945
104122
|
copyFileSync7(from, to);
|
|
103946
|
-
let parent =
|
|
104123
|
+
let parent = path66.dirname(relative);
|
|
103947
104124
|
while (parent !== "." && !dirs.has(parent)) {
|
|
103948
104125
|
dirs.add(parent);
|
|
103949
|
-
parent =
|
|
104126
|
+
parent = path66.dirname(parent);
|
|
103950
104127
|
}
|
|
103951
104128
|
}
|
|
103952
104129
|
for (const parent of dirs) {
|
|
103953
|
-
const modules =
|
|
103954
|
-
if (
|
|
103955
|
-
linkNodeModules(modules,
|
|
104130
|
+
const modules = path66.join(repo, parent, "node_modules");
|
|
104131
|
+
if (existsSync24(modules) && !existsSync24(path66.join(tree, parent, "node_modules")))
|
|
104132
|
+
linkNodeModules(modules, path66.join(tree, parent, "node_modules"), repo, tree);
|
|
103956
104133
|
}
|
|
103957
104134
|
return { dir, tree };
|
|
103958
104135
|
}
|
|
@@ -103991,20 +104168,20 @@ async function runMutation(options) {
|
|
|
103991
104168
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
103992
104169
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
103993
104170
|
try {
|
|
103994
|
-
return { file, text:
|
|
104171
|
+
return { file, text: readFileSync27(path66.join(repo, file), "utf8") };
|
|
103995
104172
|
} catch {
|
|
103996
104173
|
return { file, text: "" };
|
|
103997
104174
|
}
|
|
103998
104175
|
});
|
|
103999
104176
|
const candidates = [];
|
|
104000
104177
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
104001
|
-
const relative = toPosix(
|
|
104178
|
+
const relative = toPosix(path66.relative(repo, absolute));
|
|
104002
104179
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
104003
104180
|
continue;
|
|
104004
|
-
if (NOT_SOURCE.test(relative) || !
|
|
104181
|
+
if (NOT_SOURCE.test(relative) || !existsSync24(absolute))
|
|
104005
104182
|
continue;
|
|
104006
104183
|
try {
|
|
104007
|
-
candidates.push(...mutantsFor(
|
|
104184
|
+
candidates.push(...mutantsFor(readFileSync27(absolute, "utf8"), relative, lines));
|
|
104008
104185
|
} catch {}
|
|
104009
104186
|
}
|
|
104010
104187
|
const mutants = candidates.map((mutant, index) => ({ ...mutant, id: index + 1 }));
|
|
@@ -104012,9 +104189,9 @@ async function runMutation(options) {
|
|
|
104012
104189
|
for (const mutant of mutants)
|
|
104013
104190
|
if (!related.has(mutant.file))
|
|
104014
104191
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
104015
|
-
const cwdRelative =
|
|
104192
|
+
const cwdRelative = path66.relative(repo, options.cwd);
|
|
104016
104193
|
const asArg = (file) => {
|
|
104017
|
-
const relative = toPosix(
|
|
104194
|
+
const relative = toPosix(path66.relative(cwdRelative, file));
|
|
104018
104195
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
104019
104196
|
};
|
|
104020
104197
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -104050,7 +104227,7 @@ async function runMutation(options) {
|
|
|
104050
104227
|
return finish3(options, 0, results, counts, started);
|
|
104051
104228
|
removeStaleCopies();
|
|
104052
104229
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
104053
|
-
const copyCwd =
|
|
104230
|
+
const copyCwd = path66.join(copy, cwdRelative);
|
|
104054
104231
|
let current = null;
|
|
104055
104232
|
const restore = () => {
|
|
104056
104233
|
if (current)
|
|
@@ -104085,7 +104262,7 @@ async function runMutation(options) {
|
|
|
104085
104262
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
104086
104263
|
continue;
|
|
104087
104264
|
}
|
|
104088
|
-
const original =
|
|
104265
|
+
const original = readFileSync27(path66.join(copy, mutant.file), "utf8");
|
|
104089
104266
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
104090
104267
|
current = { file: mutant.file, original };
|
|
104091
104268
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -104142,8 +104319,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
104142
104319
|
return error.code === "EPERM";
|
|
104143
104320
|
}
|
|
104144
104321
|
}, inside4 = (root, file) => {
|
|
104145
|
-
const relative =
|
|
104146
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
104322
|
+
const relative = path66.relative(root, file);
|
|
104323
|
+
return relative === "" || !relative.startsWith("..") && !path66.isAbsolute(relative);
|
|
104147
104324
|
}, active, killTree = (child) => {
|
|
104148
104325
|
try {
|
|
104149
104326
|
if (child.pid && process.platform !== "win32")
|
|
@@ -104191,8 +104368,8 @@ var exports_test_audit = {};
|
|
|
104191
104368
|
__export(exports_test_audit, {
|
|
104192
104369
|
run: () => run22
|
|
104193
104370
|
});
|
|
104194
|
-
import { existsSync as
|
|
104195
|
-
import
|
|
104371
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
104372
|
+
import path67 from "node:path";
|
|
104196
104373
|
function parse8(argv) {
|
|
104197
104374
|
const options = {
|
|
104198
104375
|
paths: [],
|
|
@@ -104297,8 +104474,8 @@ async function run22(argv, io) {
|
|
|
104297
104474
|
return emit(io, fail2("invalid_input", `${options}
|
|
104298
104475
|
usage: ${USAGE14}`));
|
|
104299
104476
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
104300
|
-
const repo = top.ok ?
|
|
104301
|
-
const display = (file) => toPosix(
|
|
104477
|
+
const repo = top.ok ? path67.resolve(top.stdout.trim()) : null;
|
|
104478
|
+
const display = (file) => toPosix(path67.relative(io.cwd, file) || file);
|
|
104302
104479
|
let base = null;
|
|
104303
104480
|
let changed = null;
|
|
104304
104481
|
if (options.diff || options.mutate) {
|
|
@@ -104315,7 +104492,7 @@ usage: ${USAGE14}`));
|
|
|
104315
104492
|
}
|
|
104316
104493
|
let files;
|
|
104317
104494
|
if (options.diff && changed)
|
|
104318
|
-
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) &&
|
|
104495
|
+
files = [...changed.keys()].filter((file) => TEST_FILE.test(toPosix(file)) && existsSync25(file)).toSorted();
|
|
104319
104496
|
else {
|
|
104320
104497
|
const expanded = expandPaths(io.cwd, options.paths);
|
|
104321
104498
|
if (expanded.missing.length > 0)
|
|
@@ -104436,8 +104613,8 @@ var exports_youtrack = {};
|
|
|
104436
104613
|
__export(exports_youtrack, {
|
|
104437
104614
|
run: () => run24
|
|
104438
104615
|
});
|
|
104439
|
-
import { readFileSync as
|
|
104440
|
-
import
|
|
104616
|
+
import { readFileSync as readFileSync28 } from "node:fs";
|
|
104617
|
+
import path68 from "node:path";
|
|
104441
104618
|
async function run24(argv, io) {
|
|
104442
104619
|
const [sub, ...rest] = argv;
|
|
104443
104620
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -104483,7 +104660,7 @@ async function run24(argv, io) {
|
|
|
104483
104660
|
let markdown = flags.values.markdown ?? "";
|
|
104484
104661
|
if (flags.values.file)
|
|
104485
104662
|
try {
|
|
104486
|
-
markdown =
|
|
104663
|
+
markdown = readFileSync28(path68.resolve(io.cwd, flags.values.file), "utf8");
|
|
104487
104664
|
} catch (error) {
|
|
104488
104665
|
return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE16);
|
|
104489
104666
|
}
|
|
@@ -104551,8 +104728,8 @@ var exports_changelog = {};
|
|
|
104551
104728
|
__export(exports_changelog, {
|
|
104552
104729
|
run: () => run25
|
|
104553
104730
|
});
|
|
104554
|
-
import { readFileSync as
|
|
104555
|
-
import
|
|
104731
|
+
import { readFileSync as readFileSync29 } from "node:fs";
|
|
104732
|
+
import path69 from "node:path";
|
|
104556
104733
|
async function run25(argv, io) {
|
|
104557
104734
|
const [sub, ...rest] = argv;
|
|
104558
104735
|
if (sub !== "apply")
|
|
@@ -104598,7 +104775,7 @@ async function run25(argv, io) {
|
|
|
104598
104775
|
]);
|
|
104599
104776
|
}
|
|
104600
104777
|
var USAGE17 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
104601
|
-
const text = raw === "-" ?
|
|
104778
|
+
const text = raw === "-" ? readFileSync29(0, "utf8") : raw.startsWith("@") ? readFileSync29(path69.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
104602
104779
|
return JSON.parse(text);
|
|
104603
104780
|
};
|
|
104604
104781
|
var init_changelog2 = __esm(() => {
|
|
@@ -104695,7 +104872,7 @@ var init_handoff = __esm(() => {
|
|
|
104695
104872
|
// packages/workit-cli/src/main.ts
|
|
104696
104873
|
init_host_session();
|
|
104697
104874
|
init_package();
|
|
104698
|
-
import
|
|
104875
|
+
import path70 from "node:path";
|
|
104699
104876
|
|
|
104700
104877
|
// packages/workit-cli/src/verbs/registry.ts
|
|
104701
104878
|
var TASK_FAMILY_NAMES = [
|
|
@@ -104940,7 +105117,7 @@ var VERBS = [
|
|
|
104940
105117
|
subcommands: [
|
|
104941
105118
|
{
|
|
104942
105119
|
name: "show",
|
|
104943
|
-
usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--json]",
|
|
105120
|
+
usage: "workit models show [--role <role>] [--tier <mundane|standard|hard>] [--host <host>] [--report [--days <n>]] [--json]",
|
|
104944
105121
|
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
105122
|
}
|
|
104946
105123
|
],
|
|
@@ -105557,7 +105734,7 @@ var defaultIo = (json) => ({
|
|
|
105557
105734
|
});
|
|
105558
105735
|
async function main(argv, overrides = {}, options = {}) {
|
|
105559
105736
|
const parsed = parseGlobals(argv);
|
|
105560
|
-
const cwd =
|
|
105737
|
+
const cwd = path70.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
105561
105738
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
105562
105739
|
if (parsed.error)
|
|
105563
105740
|
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.1",
|
|
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.1",
|
|
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.1"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|