@brainervirus/workit-cli 8.22.3 → 8.23.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 +274 -95
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -9050,7 +9050,7 @@ var package_default;
|
|
|
9050
9050
|
var init_package = __esm(() => {
|
|
9051
9051
|
package_default = {
|
|
9052
9052
|
name: "@brainervirus/workit-cli",
|
|
9053
|
-
version: "8.
|
|
9053
|
+
version: "8.23.0",
|
|
9054
9054
|
private: false,
|
|
9055
9055
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
9056
9056
|
keywords: [
|
|
@@ -9088,13 +9088,13 @@ var init_package = __esm(() => {
|
|
|
9088
9088
|
},
|
|
9089
9089
|
dependencies: {
|
|
9090
9090
|
"@babel/parser": "7.29.9",
|
|
9091
|
-
"@brainervirus/workit-cursor": "^8.
|
|
9091
|
+
"@brainervirus/workit-cursor": "^8.23.0",
|
|
9092
9092
|
"@inkjs/ui": "2.0.0",
|
|
9093
9093
|
ink: "7.1.1",
|
|
9094
9094
|
react: "19.2.8"
|
|
9095
9095
|
},
|
|
9096
9096
|
devDependencies: {
|
|
9097
|
-
"@brainervirus/workit-core": "^8.
|
|
9097
|
+
"@brainervirus/workit-core": "^8.23.0"
|
|
9098
9098
|
},
|
|
9099
9099
|
engines: {
|
|
9100
9100
|
node: ">=24"
|
|
@@ -82928,10 +82928,176 @@ var init_stack2 = __esm(() => {
|
|
|
82928
82928
|
METHODS3 = new Set(["squash", "merge", "rebase"]);
|
|
82929
82929
|
});
|
|
82930
82930
|
|
|
82931
|
+
// packages/workit-core/src/core/live-session.ts
|
|
82932
|
+
import { spawnSync as spawnSync27 } from "node:child_process";
|
|
82933
|
+
var LIVE_SESSION_TTL_MS, liveProbe, PIDS;
|
|
82934
|
+
var init_live_session = __esm(() => {
|
|
82935
|
+
init_paths();
|
|
82936
|
+
init_logger();
|
|
82937
|
+
init_store_lock();
|
|
82938
|
+
LIVE_SESSION_TTL_MS = 15 * 60000;
|
|
82939
|
+
liveProbe = {
|
|
82940
|
+
platform: process.platform,
|
|
82941
|
+
run: (args) => spawnSync27("ps", args, { encoding: "utf8", timeout: 2000 }).stdout ?? "",
|
|
82942
|
+
start: (pid) => processStartOf(pid)
|
|
82943
|
+
};
|
|
82944
|
+
PIDS = new Map;
|
|
82945
|
+
});
|
|
82946
|
+
|
|
82947
|
+
// packages/workit-core/src/hooks/write-gate.ts
|
|
82948
|
+
import path55 from "node:path";
|
|
82949
|
+
var CASE_INSENSITIVE, PREFIXES2, SCRIPT_SHELLS, cache3, MUTATING_GIT, DRY_N, MUTATING_WORKIT_GIT, CD2, PUSHD2, POPD2, UNKNOWN_DIR;
|
|
82950
|
+
var init_write_gate = __esm(() => {
|
|
82951
|
+
init_task_store();
|
|
82952
|
+
init_derive();
|
|
82953
|
+
init_task_evaluation();
|
|
82954
|
+
init_live_session();
|
|
82955
|
+
init_logger();
|
|
82956
|
+
init_workspaces();
|
|
82957
|
+
init_ledger();
|
|
82958
|
+
init_raw_git();
|
|
82959
|
+
init_shell_words();
|
|
82960
|
+
CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
|
|
82961
|
+
PREFIXES2 = new Set(["sudo", "command", "env", "nohup", "time", "exec", "xargs", "busybox"]);
|
|
82962
|
+
SCRIPT_SHELLS = new Set(["sh", "bash", "zsh", "dash", "ksh"]);
|
|
82963
|
+
cache3 = new Map;
|
|
82964
|
+
MUTATING_GIT = new Set([
|
|
82965
|
+
"add",
|
|
82966
|
+
"am",
|
|
82967
|
+
"apply",
|
|
82968
|
+
"checkout",
|
|
82969
|
+
"cherry-pick",
|
|
82970
|
+
"clean",
|
|
82971
|
+
"commit",
|
|
82972
|
+
"merge",
|
|
82973
|
+
"mv",
|
|
82974
|
+
"pull",
|
|
82975
|
+
"rebase",
|
|
82976
|
+
"reset",
|
|
82977
|
+
"restore",
|
|
82978
|
+
"revert",
|
|
82979
|
+
"rm",
|
|
82980
|
+
"stash",
|
|
82981
|
+
"switch"
|
|
82982
|
+
]);
|
|
82983
|
+
DRY_N = new Set(["add", "clean", "rm", "mv"]);
|
|
82984
|
+
MUTATING_WORKIT_GIT = new Set(["commit", "branch"]);
|
|
82985
|
+
CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
82986
|
+
PUSHD2 = new Set(["pushd", "push-location"]);
|
|
82987
|
+
POPD2 = new Set(["popd", "pop-location"]);
|
|
82988
|
+
UNKNOWN_DIR = path55.resolve(path55.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
82989
|
+
});
|
|
82990
|
+
|
|
82991
|
+
// packages/workit-core/src/hooks/worktree-confine.ts
|
|
82992
|
+
var FANOUT_TOKEN_FILE = "workit-fanout-token", CASE_INSENSITIVE2, MUTATING_REMOTE;
|
|
82993
|
+
var init_worktree_confine = __esm(() => {
|
|
82994
|
+
init_logger();
|
|
82995
|
+
init_ledger();
|
|
82996
|
+
init_raw_git();
|
|
82997
|
+
init_write_gate();
|
|
82998
|
+
CASE_INSENSITIVE2 = process.platform === "darwin" || process.platform === "win32";
|
|
82999
|
+
MUTATING_REMOTE = new Set([
|
|
83000
|
+
"add",
|
|
83001
|
+
"remove",
|
|
83002
|
+
"rm",
|
|
83003
|
+
"rename",
|
|
83004
|
+
"set-url",
|
|
83005
|
+
"set-head",
|
|
83006
|
+
"set-branches",
|
|
83007
|
+
"prune"
|
|
83008
|
+
]);
|
|
83009
|
+
});
|
|
83010
|
+
|
|
83011
|
+
// packages/workit-core/src/worktree-deps.ts
|
|
83012
|
+
import fs31 from "node:fs";
|
|
83013
|
+
import path56 from "node:path";
|
|
83014
|
+
function moduleDirs(main) {
|
|
83015
|
+
const out = [];
|
|
83016
|
+
const walk = (relative, depth) => {
|
|
83017
|
+
let entries;
|
|
83018
|
+
try {
|
|
83019
|
+
entries = fs31.readdirSync(path56.join(main, relative), { withFileTypes: true });
|
|
83020
|
+
} catch {
|
|
83021
|
+
return;
|
|
83022
|
+
}
|
|
83023
|
+
for (const entry of entries) {
|
|
83024
|
+
if (!entry.isDirectory())
|
|
83025
|
+
continue;
|
|
83026
|
+
const child = path56.join(relative, entry.name);
|
|
83027
|
+
if (entry.name === MODULES)
|
|
83028
|
+
out.push(child);
|
|
83029
|
+
else if (depth < MAX_DEPTH2 && !entry.name.startsWith("."))
|
|
83030
|
+
walk(child, depth + 1);
|
|
83031
|
+
}
|
|
83032
|
+
};
|
|
83033
|
+
walk("", 0);
|
|
83034
|
+
return out;
|
|
83035
|
+
}
|
|
83036
|
+
function linkEntry(main, worktree, source, target) {
|
|
83037
|
+
const stat = fs31.lstatSync(source);
|
|
83038
|
+
if (stat.isSymbolicLink()) {
|
|
83039
|
+
const link = fs31.readlinkSync(source);
|
|
83040
|
+
const outside = path56.isAbsolute(link) && within(link, main) && !path56.relative(main, link).split(path56.sep).includes(MODULES);
|
|
83041
|
+
const to = outside ? path56.join(worktree, path56.relative(main, link)) : link;
|
|
83042
|
+
fs31.symlinkSync(to, target, process.platform === "win32" ? "junction" : undefined);
|
|
83043
|
+
return;
|
|
83044
|
+
}
|
|
83045
|
+
fs31.symlinkSync(source, target, process.platform === "win32" ? stat.isDirectory() ? "junction" : "file" : undefined);
|
|
83046
|
+
}
|
|
83047
|
+
function mirror(main, worktree, source, target, top) {
|
|
83048
|
+
fs31.mkdirSync(target);
|
|
83049
|
+
let count = 0;
|
|
83050
|
+
for (const entry of fs31.readdirSync(source, { withFileTypes: true })) {
|
|
83051
|
+
const from = path56.join(source, entry.name);
|
|
83052
|
+
const to = path56.join(target, entry.name);
|
|
83053
|
+
if (top && entry.isDirectory() && (entry.name.startsWith("@") || entry.name === ".bin"))
|
|
83054
|
+
count += mirror(main, worktree, from, to, false);
|
|
83055
|
+
else {
|
|
83056
|
+
linkEntry(main, worktree, from, to);
|
|
83057
|
+
count += 1;
|
|
83058
|
+
}
|
|
83059
|
+
}
|
|
83060
|
+
return count;
|
|
83061
|
+
}
|
|
83062
|
+
function linkWorktreeDependencies(main, worktree) {
|
|
83063
|
+
const started = performance.now();
|
|
83064
|
+
const notes = [];
|
|
83065
|
+
const dirs = [];
|
|
83066
|
+
let entries = 0;
|
|
83067
|
+
for (const relative of moduleDirs(main)) {
|
|
83068
|
+
const target = path56.join(worktree, relative);
|
|
83069
|
+
if (!fs31.existsSync(path56.dirname(target)) || fs31.existsSync(target))
|
|
83070
|
+
continue;
|
|
83071
|
+
if (!gitRun4(worktree, ["check-ignore", "-q", `${relative.split(path56.sep).join("/")}/`]).ok) {
|
|
83072
|
+
notes.push(`${relative.split(path56.sep).join("/")} is not ignored by git, so it was not linked from ${main}; install dependencies in the worktree yourself`);
|
|
83073
|
+
continue;
|
|
83074
|
+
}
|
|
83075
|
+
try {
|
|
83076
|
+
entries += mirror(main, worktree, path56.join(main, relative), target, true);
|
|
83077
|
+
dirs.push(relative.split(path56.sep).join("/"));
|
|
83078
|
+
} catch (error) {
|
|
83079
|
+
fs31.rmSync(target, { recursive: true, force: true });
|
|
83080
|
+
notes.push(`could not link ${relative} from ${main} (${error.message}); install dependencies in the worktree yourself`);
|
|
83081
|
+
}
|
|
83082
|
+
}
|
|
83083
|
+
if (dirs.length === 0)
|
|
83084
|
+
return { linked: null, notes };
|
|
83085
|
+
const ms = Math.round(performance.now() - started);
|
|
83086
|
+
notes.push(`linked ${dirs.join(", ")} from ${main} (${entries} entries, ${ms} ms): workspace packages resolve to this worktree, installed packages are shared`);
|
|
83087
|
+
return { linked: { from: main, dirs, entries, ms }, notes };
|
|
83088
|
+
}
|
|
83089
|
+
var MODULES = "node_modules", MAX_DEPTH2 = 2, within = (child, parent) => {
|
|
83090
|
+
const relative = path56.relative(parent, child);
|
|
83091
|
+
return relative === "" || !relative.startsWith("..") && !path56.isAbsolute(relative);
|
|
83092
|
+
};
|
|
83093
|
+
var init_worktree_deps = __esm(() => {
|
|
83094
|
+
init_fanout();
|
|
83095
|
+
});
|
|
83096
|
+
|
|
82931
83097
|
// packages/workit-core/src/fanout-worktree.ts
|
|
82932
83098
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
82933
|
-
import
|
|
82934
|
-
import
|
|
83099
|
+
import fs32 from "node:fs";
|
|
83100
|
+
import path57 from "node:path";
|
|
82935
83101
|
function rowSample(lines) {
|
|
82936
83102
|
const out = [];
|
|
82937
83103
|
let bytes = 0;
|
|
@@ -82991,7 +83157,7 @@ function adminDir(worktree) {
|
|
|
82991
83157
|
const file = dir.stdout.trim();
|
|
82992
83158
|
let token = null;
|
|
82993
83159
|
try {
|
|
82994
|
-
token =
|
|
83160
|
+
token = fs32.readFileSync(path57.join(file, FANOUT_TOKEN_FILE), "utf8").trim() || null;
|
|
82995
83161
|
} catch {
|
|
82996
83162
|
token = null;
|
|
82997
83163
|
}
|
|
@@ -82999,7 +83165,7 @@ function adminDir(worktree) {
|
|
|
82999
83165
|
const stat = worktreeDeps.stat(file);
|
|
83000
83166
|
return {
|
|
83001
83167
|
path: file,
|
|
83002
|
-
id:
|
|
83168
|
+
id: path57.basename(file),
|
|
83003
83169
|
ino: stat.ino.toString(),
|
|
83004
83170
|
token,
|
|
83005
83171
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -83015,7 +83181,7 @@ function markAdminDir(worktree) {
|
|
|
83015
83181
|
return null;
|
|
83016
83182
|
const token = randomBytes5(16).toString("hex");
|
|
83017
83183
|
try {
|
|
83018
|
-
|
|
83184
|
+
fs32.writeFileSync(path57.join(admin.path, FANOUT_TOKEN_FILE), `${token}
|
|
83019
83185
|
`);
|
|
83020
83186
|
} catch {
|
|
83021
83187
|
return null;
|
|
@@ -83030,25 +83196,25 @@ function excludeScratch(cwd) {
|
|
|
83030
83196
|
const common = gitCommonDir(cwd);
|
|
83031
83197
|
if (!common)
|
|
83032
83198
|
return;
|
|
83033
|
-
const file =
|
|
83199
|
+
const file = path57.join(common, "info", "exclude");
|
|
83034
83200
|
let text = "";
|
|
83035
83201
|
try {
|
|
83036
|
-
text =
|
|
83202
|
+
text = fs32.readFileSync(file, "utf8");
|
|
83037
83203
|
} catch {
|
|
83038
83204
|
text = "";
|
|
83039
83205
|
}
|
|
83040
83206
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
83041
83207
|
return;
|
|
83042
|
-
|
|
83043
|
-
|
|
83208
|
+
fs32.mkdirSync(path57.dirname(file), { recursive: true });
|
|
83209
|
+
fs32.appendFileSync(file, `${text && !text.endsWith(`
|
|
83044
83210
|
`) ? `
|
|
83045
83211
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
83046
83212
|
${EXCLUDE_LINE}
|
|
83047
83213
|
`);
|
|
83048
83214
|
}
|
|
83049
83215
|
function ensureScratch(worktree) {
|
|
83050
|
-
const scratch =
|
|
83051
|
-
|
|
83216
|
+
const scratch = path57.join(worktree, SCRATCH_DIR);
|
|
83217
|
+
fs32.mkdirSync(scratch, { recursive: true });
|
|
83052
83218
|
return scratch;
|
|
83053
83219
|
}
|
|
83054
83220
|
function createSliceWorktree(cwd, plan, input) {
|
|
@@ -83075,6 +83241,7 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
83075
83241
|
if (!createdRow(cwd, plan, slice, target))
|
|
83076
83242
|
return fanoutFail("blocked", `${target} is a worktree that workit fanout worktree create did not make for slice ${slice.id}`, `remove it yourself (git worktree remove ${target}) once you know what it holds`);
|
|
83077
83243
|
excludeScratch(cwd);
|
|
83244
|
+
const deps = linkWorktreeDependencies(mainCheckout(cwd), target);
|
|
83078
83245
|
return {
|
|
83079
83246
|
ok: true,
|
|
83080
83247
|
data: {
|
|
@@ -83083,7 +83250,11 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
83083
83250
|
head: existing.head ?? "",
|
|
83084
83251
|
mode: resolveRef(cwd, localRef) ? "resume" : "new",
|
|
83085
83252
|
created: false,
|
|
83086
|
-
|
|
83253
|
+
dependencies: deps.linked,
|
|
83254
|
+
notes: [
|
|
83255
|
+
deps.linked ? "the worktree already exists; only its missing dependencies were linked" : "the worktree already exists; nothing was changed",
|
|
83256
|
+
...deps.notes
|
|
83257
|
+
]
|
|
83087
83258
|
}
|
|
83088
83259
|
};
|
|
83089
83260
|
}
|
|
@@ -83092,8 +83263,8 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
83092
83263
|
return fanoutFail("blocked", `${slice.branch} is checked out at ${elsewhere.path}: never two live workers on one branch`, `stop that worker, then workit fanout worktree release ${slice.id} (or git worktree remove ${elsewhere.path})`);
|
|
83093
83264
|
let dirExisted = false;
|
|
83094
83265
|
try {
|
|
83095
|
-
const stat =
|
|
83096
|
-
if (!stat.isDirectory() ||
|
|
83266
|
+
const stat = fs32.statSync(target);
|
|
83267
|
+
if (!stat.isDirectory() || fs32.readdirSync(target).length > 0)
|
|
83097
83268
|
return fanoutFail("blocked", `${target} exists and is ${stat.isDirectory() ? "not empty" : "not a directory"} (not a worktree of this repository)`, `move it away, or set slice ${slice.id}'s worktree to another path`);
|
|
83098
83269
|
dirExisted = true;
|
|
83099
83270
|
} catch (error) {
|
|
@@ -83133,6 +83304,8 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
83133
83304
|
}
|
|
83134
83305
|
excludeScratch(cwd);
|
|
83135
83306
|
const scratch = ensureScratch(target);
|
|
83307
|
+
const deps = linkWorktreeDependencies(mainCheckout(cwd), target);
|
|
83308
|
+
notes.push(...deps.notes);
|
|
83136
83309
|
const head = gitRun4(target, ["rev-parse", "HEAD"]).stdout.trim();
|
|
83137
83310
|
const baseSha = mode === "new" ? head : null;
|
|
83138
83311
|
const admin = markAdminDir(target);
|
|
@@ -83152,7 +83325,10 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
83152
83325
|
...admin ? { adminId: admin.id, adminIno: admin.ino, adminToken: admin.token } : {},
|
|
83153
83326
|
...baseSha ? { baseSha } : {}
|
|
83154
83327
|
});
|
|
83155
|
-
return {
|
|
83328
|
+
return {
|
|
83329
|
+
ok: true,
|
|
83330
|
+
data: { ...base, scratch, head, mode, created: true, dependencies: deps.linked, notes }
|
|
83331
|
+
};
|
|
83156
83332
|
}
|
|
83157
83333
|
function releaseSliceWorktree(cwd, plan, input) {
|
|
83158
83334
|
const found = findSlice(plan, input.slice);
|
|
@@ -83175,7 +83351,7 @@ function releaseSliceWorktree(cwd, plan, input) {
|
|
|
83175
83351
|
notes: []
|
|
83176
83352
|
};
|
|
83177
83353
|
if (index < 0) {
|
|
83178
|
-
if (
|
|
83354
|
+
if (fs32.existsSync(target))
|
|
83179
83355
|
return fanoutFail("blocked", `${target} is not a worktree of this repository; nothing was removed`, "remove it yourself once you know what it holds");
|
|
83180
83356
|
out.notes.push(`no worktree at ${target}; nothing to release`);
|
|
83181
83357
|
return { ok: true, data: out };
|
|
@@ -83237,7 +83413,7 @@ function releaseSliceWorktree(cwd, plan, input) {
|
|
|
83237
83413
|
`)[0]}`, entry.locked ? `git worktree unlock ${entry.path}, then release again` : undefined, { ...out });
|
|
83238
83414
|
out.removed = true;
|
|
83239
83415
|
if (made.dirExisted === true)
|
|
83240
|
-
|
|
83416
|
+
fs32.mkdirSync(entry.path, { recursive: true });
|
|
83241
83417
|
if (out.unpushed)
|
|
83242
83418
|
out.notes.push(`${slice.branch} is kept with ${out.unpushed} commit(s) not on the remote`);
|
|
83243
83419
|
return { ok: true, data: out };
|
|
@@ -83265,42 +83441,44 @@ function unpushedCount(cwd, branch) {
|
|
|
83265
83441
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
83266
83442
|
}
|
|
83267
83443
|
function removeScratch(worktree) {
|
|
83268
|
-
const scratch =
|
|
83444
|
+
const scratch = path57.join(worktree, SCRATCH_DIR);
|
|
83269
83445
|
let stat;
|
|
83270
83446
|
try {
|
|
83271
|
-
stat =
|
|
83447
|
+
stat = fs32.lstatSync(scratch);
|
|
83272
83448
|
} catch {
|
|
83273
83449
|
return;
|
|
83274
83450
|
}
|
|
83275
83451
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
83276
|
-
|
|
83452
|
+
fs32.unlinkSync(scratch);
|
|
83277
83453
|
else
|
|
83278
|
-
|
|
83454
|
+
fs32.rmSync(scratch, { recursive: true, force: true, maxRetries: 2 });
|
|
83279
83455
|
}
|
|
83280
83456
|
var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000, canonical2 = (target) => {
|
|
83281
83457
|
try {
|
|
83282
|
-
return
|
|
83458
|
+
return fs32.realpathSync.native(target);
|
|
83283
83459
|
} catch {
|
|
83284
|
-
return
|
|
83460
|
+
return path57.resolve(target);
|
|
83285
83461
|
}
|
|
83286
83462
|
}, samePath = (a, b) => {
|
|
83287
83463
|
const left = canonical2(a);
|
|
83288
83464
|
const right = canonical2(b);
|
|
83289
83465
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
83290
83466
|
}, inside3 = (child, parent) => {
|
|
83291
|
-
const relative =
|
|
83292
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
83293
|
-
}, slicePath = (cwd, slice) =>
|
|
83467
|
+
const relative = path57.relative(canonical2(parent), canonical2(child));
|
|
83468
|
+
return relative === "" || !relative.startsWith("..") && !path57.isAbsolute(relative);
|
|
83469
|
+
}, slicePath = (cwd, slice) => path57.isAbsolute(slice.worktree) ? slice.worktree : path57.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
|
|
83294
83470
|
`)[0] || "unknown error"}`);
|
|
83295
83471
|
var init_fanout_worktree = __esm(() => {
|
|
83296
83472
|
init_ops();
|
|
83297
83473
|
init_rev();
|
|
83298
83474
|
init_ledger();
|
|
83475
|
+
init_worktree_confine();
|
|
83476
|
+
init_worktree_deps();
|
|
83299
83477
|
init_fanout();
|
|
83300
83478
|
SLOW = GIT_TIMEOUTS.worktree;
|
|
83301
83479
|
EXCLUDE_LINE = `/${SCRATCH_DIR}/`;
|
|
83302
83480
|
worktreeDeps = {
|
|
83303
|
-
stat: (file) =>
|
|
83481
|
+
stat: (file) => fs32.statSync(file, { bigint: true })
|
|
83304
83482
|
};
|
|
83305
83483
|
});
|
|
83306
83484
|
|
|
@@ -83378,8 +83556,9 @@ function renderBrief(cwd, plan, input) {
|
|
|
83378
83556
|
...REPORT,
|
|
83379
83557
|
"STANDING:",
|
|
83380
83558
|
...standing.length ? standing.map((order) => ` - ${order.what}`) : [" - none recorded beyond this brief"],
|
|
83559
|
+
exists ? `WORKTREE: ${planned} (made by \`workit fanout worktree create ${slice.id}\`; yours alone)` : `WORKTREE: ${planned} (not made yet: the lead runs \`workit fanout worktree create ${slice.id}\` before spawning, then renders this brief again)`,
|
|
83381
83560
|
...identityLines(identity, minted),
|
|
83382
|
-
...rules(
|
|
83561
|
+
...rules(mode, branch, slice.base, exists ? planned : null)
|
|
83383
83562
|
];
|
|
83384
83563
|
return {
|
|
83385
83564
|
ok: true,
|
|
@@ -83412,25 +83591,25 @@ var DEFAULT_TIMEBOX = "30 minutes", REPORT, identityOf = (host) => {
|
|
|
83412
83591
|
}, identityLines = (identity, session) => {
|
|
83413
83592
|
if (identity === "issued")
|
|
83414
83593
|
return [
|
|
83415
|
-
" Session: your env already has WORKIT_SESSION_ID (the lead's id; SubagentStart issues ids only to verifiers and reviewers). Use it as is
|
|
83594
|
+
" Session: your env already has WORKIT_SESSION_ID (the lead's id; SubagentStart issues ids only to verifiers and reviewers). Use it as is: workit commands read it and `workit git commit` adds the Workit-Session trailer; never export or hand-mint one."
|
|
83416
83595
|
];
|
|
83417
83596
|
if (identity === "derived")
|
|
83418
83597
|
return [
|
|
83419
83598
|
" Session: your host already sets WORKIT_SESSION_ID in your shell; export nothing and never hand-mint one."
|
|
83420
83599
|
];
|
|
83421
83600
|
return [` export WORKIT_SESSION_ID=${session}`];
|
|
83422
|
-
}, rules = (
|
|
83423
|
-
const
|
|
83601
|
+
}, rules = (mode, branch, base, worktree) => {
|
|
83602
|
+
const workit = worktree ? `workit --cwd ${worktree}` : "workit";
|
|
83424
83603
|
let first = ` 1. First command: \`workit git branch ${branch} --base ${base}\` (your worktree may start on another name).`;
|
|
83425
|
-
if (
|
|
83604
|
+
if (worktree)
|
|
83605
|
+
first = ` 1. Work only in WORKTREE, already on ${branch}${mode === "resume" ? " at its head" : ""}: edit files under it and run each git and check command against it, one verb per call (\`${workit} git commit …\`, \`${workit} check <name>\`), never \`cd … &&\` chains or \`$VAR\` paths. An implementer's change outside it is denied.`;
|
|
83606
|
+
else if (mode === "resume")
|
|
83426
83607
|
first = ` 1. First command: \`git switch ${branch}\`, then continue from its head.`;
|
|
83427
|
-
else if (plain)
|
|
83428
|
-
first = ` 1. First command: \`git fetch origin && git switch -c ${branch} origin/${base}\` (plain git: worktree isolation refuses every \`workit git\` form).`;
|
|
83429
83608
|
return [
|
|
83430
83609
|
"RULES:",
|
|
83431
83610
|
first,
|
|
83432
83611
|
' 2. Decide ambiguities yourself: `workit ledger ruling "<what>" --why "<why>" --cost-if-wrong "<cost>"`; stop only for an irreversible, security-sensitive or out-of-worktree action.',
|
|
83433
|
-
|
|
83612
|
+
` 3. Commit with \`${workit} git commit -m <msg> -- <paths in SCOPE>\`; push only if this brief says so.`,
|
|
83434
83613
|
" 4. Never record a verdict on your own work.",
|
|
83435
83614
|
" 5. Run tests, lint, typecheck and builds only through `workit check` (a named check, or `workit check --heavy -- <cmd>`): one machine-wide lease queues every agent, so never a hand-made flock; `workit lock status` shows who holds it.",
|
|
83436
83615
|
" 6. A failed review gets one fix round and one recheck. Still failing: stop and report the open finding, never a third round (the lead spawns a decider). A product choice is the user's: report it, do not decide it."
|
|
@@ -83449,7 +83628,7 @@ var init_fanout_brief = __esm(() => {
|
|
|
83449
83628
|
});
|
|
83450
83629
|
|
|
83451
83630
|
// packages/workit-core/src/fanout-landed.ts
|
|
83452
|
-
import { spawnSync as
|
|
83631
|
+
import { spawnSync as spawnSync28 } from "node:child_process";
|
|
83453
83632
|
function forgeBreaker(resolved) {
|
|
83454
83633
|
if (!resolved)
|
|
83455
83634
|
return { forge: null, down: () => null };
|
|
@@ -83540,7 +83719,7 @@ function trunkPatchIds(ctx, fork) {
|
|
|
83540
83719
|
"--"
|
|
83541
83720
|
]);
|
|
83542
83721
|
if (log.ok && log.stdout.trim()) {
|
|
83543
|
-
const run =
|
|
83722
|
+
const run = spawnSync28("git", ["patch-id", "--stable"], {
|
|
83544
83723
|
cwd: ctx.cwd,
|
|
83545
83724
|
input: log.stdout,
|
|
83546
83725
|
encoding: "utf8",
|
|
@@ -84114,8 +84293,8 @@ var exports_fanout = {};
|
|
|
84114
84293
|
__export(exports_fanout, {
|
|
84115
84294
|
run: () => run18
|
|
84116
84295
|
});
|
|
84117
|
-
import
|
|
84118
|
-
import
|
|
84296
|
+
import fs33 from "node:fs";
|
|
84297
|
+
import path58 from "node:path";
|
|
84119
84298
|
function forgeFor(io, offline) {
|
|
84120
84299
|
if (offline)
|
|
84121
84300
|
return { forge: null, error: "--offline" };
|
|
@@ -84176,10 +84355,10 @@ function plan2(argv, io) {
|
|
|
84176
84355
|
return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
84177
84356
|
if (flags.positionals.length !== 1)
|
|
84178
84357
|
return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
84179
|
-
const file =
|
|
84358
|
+
const file = path58.resolve(io.cwd, flags.positionals[0]);
|
|
84180
84359
|
let raw;
|
|
84181
84360
|
try {
|
|
84182
|
-
raw = JSON.parse(
|
|
84361
|
+
raw = JSON.parse(fs33.readFileSync(file, "utf8"));
|
|
84183
84362
|
} catch (error) {
|
|
84184
84363
|
return usage3(io, `cannot read ${file} as JSON: ${error.message}`, PLAN_USAGE2);
|
|
84185
84364
|
}
|
|
@@ -99710,7 +99889,7 @@ var init_ast = __esm(() => {
|
|
|
99710
99889
|
|
|
99711
99890
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
99712
99891
|
import { builtinModules } from "node:module";
|
|
99713
|
-
import
|
|
99892
|
+
import path59 from "node:path";
|
|
99714
99893
|
function testCallee(call) {
|
|
99715
99894
|
let callee = call.callee;
|
|
99716
99895
|
if (callee.type === "CallExpression")
|
|
@@ -100203,12 +100382,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
100203
100382
|
}
|
|
100204
100383
|
function checkOverMocking(ctx, emit) {
|
|
100205
100384
|
const { program } = ctx.parsed;
|
|
100206
|
-
const unit =
|
|
100385
|
+
const unit = path59.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
100207
100386
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
100208
100387
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
100209
100388
|
for (const call of mocked) {
|
|
100210
100389
|
const spec = call.arguments[0].value;
|
|
100211
|
-
const base =
|
|
100390
|
+
const base = path59.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
100212
100391
|
if (base === unit)
|
|
100213
100392
|
emit({
|
|
100214
100393
|
rule: "over-mocking",
|
|
@@ -100596,11 +100775,11 @@ var init_rules = __esm(() => {
|
|
|
100596
100775
|
});
|
|
100597
100776
|
|
|
100598
100777
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
100599
|
-
import { spawnSync as
|
|
100778
|
+
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
100600
100779
|
import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync23, statSync as statSync8 } from "node:fs";
|
|
100601
|
-
import
|
|
100780
|
+
import path60 from "node:path";
|
|
100602
100781
|
function git7(cwd, args) {
|
|
100603
|
-
const run =
|
|
100782
|
+
const run = spawnSync29("git", ["-c", "core.quotepath=off", ...args], {
|
|
100604
100783
|
cwd,
|
|
100605
100784
|
encoding: "utf8",
|
|
100606
100785
|
maxBuffer: 64 * 1024 * 1024
|
|
@@ -100611,7 +100790,7 @@ function walkTests(dir, out) {
|
|
|
100611
100790
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
100612
100791
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
100613
100792
|
continue;
|
|
100614
|
-
const full =
|
|
100793
|
+
const full = path60.join(dir, entry.name);
|
|
100615
100794
|
if (entry.isDirectory()) {
|
|
100616
100795
|
if (!SKIP_DIRS.has(entry.name))
|
|
100617
100796
|
walkTests(full, out);
|
|
@@ -100623,7 +100802,7 @@ function expandPaths(cwd, inputs) {
|
|
|
100623
100802
|
const files = [];
|
|
100624
100803
|
const missing = [];
|
|
100625
100804
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
100626
|
-
const full =
|
|
100805
|
+
const full = path60.resolve(cwd, input);
|
|
100627
100806
|
if (!existsSync20(full))
|
|
100628
100807
|
missing.push(input);
|
|
100629
100808
|
else if (statSync8(full).isDirectory())
|
|
@@ -100660,11 +100839,11 @@ function changedLines(cwd, base) {
|
|
|
100660
100839
|
for (let offset = 0;offset < count; offset += 1)
|
|
100661
100840
|
lines.add(start + offset);
|
|
100662
100841
|
}
|
|
100663
|
-
changed.set(
|
|
100842
|
+
changed.set(path60.join(root, file), lines);
|
|
100664
100843
|
}
|
|
100665
100844
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
100666
100845
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
100667
|
-
changed.set(
|
|
100846
|
+
changed.set(path60.join(root, file), "all");
|
|
100668
100847
|
return changed;
|
|
100669
100848
|
}
|
|
100670
100849
|
function auditFiles(files, display) {
|
|
@@ -100726,7 +100905,7 @@ function auditFiles(files, display) {
|
|
|
100726
100905
|
durationMs: Math.round(performance.now() - started)
|
|
100727
100906
|
};
|
|
100728
100907
|
}
|
|
100729
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
100908
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path60.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
100730
100909
|
var init_audit = __esm(() => {
|
|
100731
100910
|
init_ast();
|
|
100732
100911
|
init_rules();
|
|
@@ -100756,7 +100935,7 @@ import {
|
|
|
100756
100935
|
copyFileSync as copyFileSync6
|
|
100757
100936
|
} from "node:fs";
|
|
100758
100937
|
import os18 from "node:os";
|
|
100759
|
-
import
|
|
100938
|
+
import path61 from "node:path";
|
|
100760
100939
|
function mutantsFor(source, file, lines) {
|
|
100761
100940
|
const parsed = parseSource(source, file);
|
|
100762
100941
|
const out = [];
|
|
@@ -100829,7 +101008,7 @@ function relatedTests(source, testFiles) {
|
|
|
100829
101008
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
100830
101009
|
const spec = match[1];
|
|
100831
101010
|
if (spec.startsWith(".")) {
|
|
100832
|
-
if (stripExt(
|
|
101011
|
+
if (stripExt(path61.posix.join(path61.posix.dirname(file), spec)) === target)
|
|
100833
101012
|
return true;
|
|
100834
101013
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
100835
101014
|
return true;
|
|
@@ -100849,12 +101028,12 @@ function removeStaleCopies(tmp = os18.tmpdir()) {
|
|
|
100849
101028
|
for (const name of names) {
|
|
100850
101029
|
if (!name.startsWith(TEMP_PREFIX))
|
|
100851
101030
|
continue;
|
|
100852
|
-
const dir =
|
|
101031
|
+
const dir = path61.join(tmp, name);
|
|
100853
101032
|
try {
|
|
100854
101033
|
const stat = lstatSync8(dir);
|
|
100855
101034
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
100856
101035
|
continue;
|
|
100857
|
-
const pid = Number(readFileSync24(
|
|
101036
|
+
const pid = Number(readFileSync24(path61.join(dir, PID_FILE), "utf8"));
|
|
100858
101037
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
100859
101038
|
continue;
|
|
100860
101039
|
} catch (error) {
|
|
@@ -100871,8 +101050,8 @@ function removeStaleCopies(tmp = os18.tmpdir()) {
|
|
|
100871
101050
|
function linkNodeModules(origin, target, repo, copy) {
|
|
100872
101051
|
mkdirSync10(target, { recursive: true });
|
|
100873
101052
|
for (const entry of readdirSync11(origin, { withFileTypes: true })) {
|
|
100874
|
-
const from =
|
|
100875
|
-
const to =
|
|
101053
|
+
const from = path61.join(origin, entry.name);
|
|
101054
|
+
const to = path61.join(target, entry.name);
|
|
100876
101055
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
100877
101056
|
linkNodeModules(from, to, repo, copy);
|
|
100878
101057
|
continue;
|
|
@@ -100888,9 +101067,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
100888
101067
|
} catch {
|
|
100889
101068
|
continue;
|
|
100890
101069
|
}
|
|
100891
|
-
const relative =
|
|
100892
|
-
if (!relative.startsWith("..") && !
|
|
100893
|
-
symlinkSync(
|
|
101070
|
+
const relative = path61.relative(repo, real);
|
|
101071
|
+
if (!relative.startsWith("..") && !path61.isAbsolute(relative) && !relative.split(path61.sep).includes("node_modules")) {
|
|
101072
|
+
symlinkSync(path61.join(copy, relative), to, "junction");
|
|
100894
101073
|
continue;
|
|
100895
101074
|
}
|
|
100896
101075
|
}
|
|
@@ -100906,7 +101085,7 @@ function copySymlink(repo, tree, from, to) {
|
|
|
100906
101085
|
}
|
|
100907
101086
|
const realRepo = realpathSync9(repo);
|
|
100908
101087
|
if (real && inside4(realRepo, real)) {
|
|
100909
|
-
symlinkSync(
|
|
101088
|
+
symlinkSync(path61.relative(path61.dirname(to), path61.join(tree, path61.relative(realRepo, real))), to);
|
|
100910
101089
|
return;
|
|
100911
101090
|
}
|
|
100912
101091
|
if (real && statSync9(real).isFile())
|
|
@@ -100915,10 +101094,10 @@ function copySymlink(repo, tree, from, to) {
|
|
|
100915
101094
|
symlinkSync(readlinkSync3(from), to);
|
|
100916
101095
|
}
|
|
100917
101096
|
function writeInside(copy, file, content) {
|
|
100918
|
-
const target =
|
|
101097
|
+
const target = path61.join(copy, file);
|
|
100919
101098
|
try {
|
|
100920
101099
|
const stat = lstatSync8(target);
|
|
100921
|
-
if (!stat.isFile() || !inside4(realpathSync9(copy), realpathSync9(
|
|
101100
|
+
if (!stat.isFile() || !inside4(realpathSync9(copy), realpathSync9(path61.dirname(target))))
|
|
100922
101101
|
return false;
|
|
100923
101102
|
} catch {
|
|
100924
101103
|
return false;
|
|
@@ -100929,9 +101108,9 @@ function writeInside(copy, file, content) {
|
|
|
100929
101108
|
return true;
|
|
100930
101109
|
}
|
|
100931
101110
|
function copyWorkingTree(repo) {
|
|
100932
|
-
const dir = mkdtempSync4(
|
|
100933
|
-
writeFileSync11(
|
|
100934
|
-
const tree =
|
|
101111
|
+
const dir = mkdtempSync4(path61.join(os18.tmpdir(), TEMP_PREFIX));
|
|
101112
|
+
writeFileSync11(path61.join(dir, PID_FILE), String(process.pid));
|
|
101113
|
+
const tree = path61.join(dir, "tree");
|
|
100935
101114
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
100936
101115
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
100937
101116
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -100948,29 +101127,29 @@ function copyWorkingTree(repo) {
|
|
|
100948
101127
|
for (const relative of listed) {
|
|
100949
101128
|
if (!relative)
|
|
100950
101129
|
continue;
|
|
100951
|
-
const from =
|
|
101130
|
+
const from = path61.join(repo, relative);
|
|
100952
101131
|
let stat;
|
|
100953
101132
|
try {
|
|
100954
101133
|
stat = lstatSync8(from);
|
|
100955
101134
|
} catch {
|
|
100956
101135
|
continue;
|
|
100957
101136
|
}
|
|
100958
|
-
const to =
|
|
100959
|
-
mkdirSync10(
|
|
101137
|
+
const to = path61.join(tree, relative);
|
|
101138
|
+
mkdirSync10(path61.dirname(to), { recursive: true });
|
|
100960
101139
|
if (stat.isSymbolicLink())
|
|
100961
101140
|
copySymlink(repo, tree, from, to);
|
|
100962
101141
|
else if (stat.isFile())
|
|
100963
101142
|
copyFileSync6(from, to);
|
|
100964
|
-
let parent =
|
|
101143
|
+
let parent = path61.dirname(relative);
|
|
100965
101144
|
while (parent !== "." && !dirs.has(parent)) {
|
|
100966
101145
|
dirs.add(parent);
|
|
100967
|
-
parent =
|
|
101146
|
+
parent = path61.dirname(parent);
|
|
100968
101147
|
}
|
|
100969
101148
|
}
|
|
100970
101149
|
for (const parent of dirs) {
|
|
100971
|
-
const modules =
|
|
100972
|
-
if (existsSync21(modules) && !existsSync21(
|
|
100973
|
-
linkNodeModules(modules,
|
|
101150
|
+
const modules = path61.join(repo, parent, "node_modules");
|
|
101151
|
+
if (existsSync21(modules) && !existsSync21(path61.join(tree, parent, "node_modules")))
|
|
101152
|
+
linkNodeModules(modules, path61.join(tree, parent, "node_modules"), repo, tree);
|
|
100974
101153
|
}
|
|
100975
101154
|
return { dir, tree };
|
|
100976
101155
|
}
|
|
@@ -101009,14 +101188,14 @@ async function runMutation(options) {
|
|
|
101009
101188
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
101010
101189
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
101011
101190
|
try {
|
|
101012
|
-
return { file, text: readFileSync24(
|
|
101191
|
+
return { file, text: readFileSync24(path61.join(repo, file), "utf8") };
|
|
101013
101192
|
} catch {
|
|
101014
101193
|
return { file, text: "" };
|
|
101015
101194
|
}
|
|
101016
101195
|
});
|
|
101017
101196
|
const candidates = [];
|
|
101018
101197
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
101019
|
-
const relative = toPosix(
|
|
101198
|
+
const relative = toPosix(path61.relative(repo, absolute));
|
|
101020
101199
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
101021
101200
|
continue;
|
|
101022
101201
|
if (NOT_SOURCE.test(relative) || !existsSync21(absolute))
|
|
@@ -101030,9 +101209,9 @@ async function runMutation(options) {
|
|
|
101030
101209
|
for (const mutant of mutants)
|
|
101031
101210
|
if (!related.has(mutant.file))
|
|
101032
101211
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
101033
|
-
const cwdRelative =
|
|
101212
|
+
const cwdRelative = path61.relative(repo, options.cwd);
|
|
101034
101213
|
const asArg = (file) => {
|
|
101035
|
-
const relative = toPosix(
|
|
101214
|
+
const relative = toPosix(path61.relative(cwdRelative, file));
|
|
101036
101215
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
101037
101216
|
};
|
|
101038
101217
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -101068,7 +101247,7 @@ async function runMutation(options) {
|
|
|
101068
101247
|
return finish3(options, 0, results, counts, started);
|
|
101069
101248
|
removeStaleCopies();
|
|
101070
101249
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
101071
|
-
const copyCwd =
|
|
101250
|
+
const copyCwd = path61.join(copy, cwdRelative);
|
|
101072
101251
|
let current = null;
|
|
101073
101252
|
const restore = () => {
|
|
101074
101253
|
if (current)
|
|
@@ -101103,7 +101282,7 @@ async function runMutation(options) {
|
|
|
101103
101282
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
101104
101283
|
continue;
|
|
101105
101284
|
}
|
|
101106
|
-
const original = readFileSync24(
|
|
101285
|
+
const original = readFileSync24(path61.join(copy, mutant.file), "utf8");
|
|
101107
101286
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
101108
101287
|
current = { file: mutant.file, original };
|
|
101109
101288
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -101160,8 +101339,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
101160
101339
|
return error.code === "EPERM";
|
|
101161
101340
|
}
|
|
101162
101341
|
}, inside4 = (root, file) => {
|
|
101163
|
-
const relative =
|
|
101164
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
101342
|
+
const relative = path61.relative(root, file);
|
|
101343
|
+
return relative === "" || !relative.startsWith("..") && !path61.isAbsolute(relative);
|
|
101165
101344
|
}, active, killTree = (child) => {
|
|
101166
101345
|
try {
|
|
101167
101346
|
if (child.pid && process.platform !== "win32")
|
|
@@ -101210,7 +101389,7 @@ __export(exports_test_audit, {
|
|
|
101210
101389
|
run: () => run20
|
|
101211
101390
|
});
|
|
101212
101391
|
import { existsSync as existsSync22 } from "node:fs";
|
|
101213
|
-
import
|
|
101392
|
+
import path62 from "node:path";
|
|
101214
101393
|
function parse7(argv) {
|
|
101215
101394
|
const options = {
|
|
101216
101395
|
paths: [],
|
|
@@ -101315,8 +101494,8 @@ async function run20(argv, io) {
|
|
|
101315
101494
|
return emit(io, fail2("invalid_input", `${options}
|
|
101316
101495
|
usage: ${USAGE12}`));
|
|
101317
101496
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
101318
|
-
const repo = top.ok ?
|
|
101319
|
-
const display = (file) => toPosix(
|
|
101497
|
+
const repo = top.ok ? path62.resolve(top.stdout.trim()) : null;
|
|
101498
|
+
const display = (file) => toPosix(path62.relative(io.cwd, file) || file);
|
|
101320
101499
|
let base = null;
|
|
101321
101500
|
let changed = null;
|
|
101322
101501
|
if (options.diff || options.mutate) {
|
|
@@ -101455,7 +101634,7 @@ __export(exports_youtrack, {
|
|
|
101455
101634
|
run: () => run22
|
|
101456
101635
|
});
|
|
101457
101636
|
import { readFileSync as readFileSync25 } from "node:fs";
|
|
101458
|
-
import
|
|
101637
|
+
import path63 from "node:path";
|
|
101459
101638
|
async function run22(argv, io) {
|
|
101460
101639
|
const [sub, ...rest] = argv;
|
|
101461
101640
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -101501,7 +101680,7 @@ async function run22(argv, io) {
|
|
|
101501
101680
|
let markdown = flags.values.markdown ?? "";
|
|
101502
101681
|
if (flags.values.file)
|
|
101503
101682
|
try {
|
|
101504
|
-
markdown = readFileSync25(
|
|
101683
|
+
markdown = readFileSync25(path63.resolve(io.cwd, flags.values.file), "utf8");
|
|
101505
101684
|
} catch (error) {
|
|
101506
101685
|
return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE14);
|
|
101507
101686
|
}
|
|
@@ -101570,7 +101749,7 @@ __export(exports_changelog, {
|
|
|
101570
101749
|
run: () => run23
|
|
101571
101750
|
});
|
|
101572
101751
|
import { readFileSync as readFileSync26 } from "node:fs";
|
|
101573
|
-
import
|
|
101752
|
+
import path64 from "node:path";
|
|
101574
101753
|
async function run23(argv, io) {
|
|
101575
101754
|
const [sub, ...rest] = argv;
|
|
101576
101755
|
if (sub !== "apply")
|
|
@@ -101616,7 +101795,7 @@ async function run23(argv, io) {
|
|
|
101616
101795
|
]);
|
|
101617
101796
|
}
|
|
101618
101797
|
var USAGE15 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
101619
|
-
const text = raw === "-" ? readFileSync26(0, "utf8") : raw.startsWith("@") ? readFileSync26(
|
|
101798
|
+
const text = raw === "-" ? readFileSync26(0, "utf8") : raw.startsWith("@") ? readFileSync26(path64.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
101620
101799
|
return JSON.parse(text);
|
|
101621
101800
|
};
|
|
101622
101801
|
var init_changelog2 = __esm(() => {
|
|
@@ -101713,7 +101892,7 @@ var init_handoff = __esm(() => {
|
|
|
101713
101892
|
// packages/workit-cli/src/main.ts
|
|
101714
101893
|
init_host_session();
|
|
101715
101894
|
init_package();
|
|
101716
|
-
import
|
|
101895
|
+
import path65 from "node:path";
|
|
101717
101896
|
|
|
101718
101897
|
// packages/workit-cli/src/verbs/registry.ts
|
|
101719
101898
|
var TASK_FAMILY_NAMES = [
|
|
@@ -102551,7 +102730,7 @@ var defaultIo = (json) => ({
|
|
|
102551
102730
|
});
|
|
102552
102731
|
async function main(argv, overrides = {}, options = {}) {
|
|
102553
102732
|
const parsed = parseGlobals(argv);
|
|
102554
|
-
const cwd =
|
|
102733
|
+
const cwd = path65.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
102555
102734
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
102556
102735
|
if (parsed.error)
|
|
102557
102736
|
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.23.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.23.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.23.0"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24"
|