@brainervirus/workit-cli 8.20.0 → 8.21.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 +719 -668
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@brainervirus/workit-cli",
|
|
68
|
-
version: "8.
|
|
68
|
+
version: "8.21.0",
|
|
69
69
|
private: false,
|
|
70
70
|
description: "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
|
|
71
71
|
keywords: [
|
|
@@ -103,13 +103,13 @@ var init_package = __esm(() => {
|
|
|
103
103
|
},
|
|
104
104
|
dependencies: {
|
|
105
105
|
"@babel/parser": "7.29.9",
|
|
106
|
-
"@brainervirus/workit-cursor": "^8.
|
|
106
|
+
"@brainervirus/workit-cursor": "^8.21.0",
|
|
107
107
|
"@inkjs/ui": "2.0.0",
|
|
108
108
|
ink: "7.1.1",
|
|
109
109
|
react: "19.2.8"
|
|
110
110
|
},
|
|
111
111
|
devDependencies: {
|
|
112
|
-
"@brainervirus/workit-core": "^8.
|
|
112
|
+
"@brainervirus/workit-core": "^8.21.0"
|
|
113
113
|
},
|
|
114
114
|
engines: {
|
|
115
115
|
node: ">=24"
|
|
@@ -15262,11 +15262,23 @@ var init_workers = __esm(() => {
|
|
|
15262
15262
|
UNCERTAIN_WORKER_STATES = ["dispatching", "running", "cancelling", "unknown"];
|
|
15263
15263
|
});
|
|
15264
15264
|
|
|
15265
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
15266
|
+
import fs12 from "node:fs";
|
|
15267
|
+
import path16 from "node:path";
|
|
15268
|
+
var standingRevFile = (store) => path16.join(store, "standing", "rev"), bumpStandingRev = (store, rev) => {
|
|
15269
|
+
try {
|
|
15270
|
+
fs12.mkdirSync(path16.join(store, "standing"), { recursive: true });
|
|
15271
|
+
fs12.writeFileSync(standingRevFile(store), `${rev}
|
|
15272
|
+
`);
|
|
15273
|
+
} catch {}
|
|
15274
|
+
};
|
|
15275
|
+
var init_standing_signal = () => {};
|
|
15276
|
+
|
|
15265
15277
|
// packages/workit-core/src/ledger.ts
|
|
15266
15278
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
15267
15279
|
import { createHash as createHash10, randomBytes as randomBytes3 } from "node:crypto";
|
|
15268
|
-
import
|
|
15269
|
-
import
|
|
15280
|
+
import fs13 from "node:fs";
|
|
15281
|
+
import path17 from "node:path";
|
|
15270
15282
|
function resolveCommit(cwd, ref) {
|
|
15271
15283
|
if (!safeRef(ref))
|
|
15272
15284
|
return null;
|
|
@@ -15332,14 +15344,14 @@ function diffHash(cwd, base, head) {
|
|
|
15332
15344
|
return `sha256:${hash.digest("hex")}`;
|
|
15333
15345
|
}
|
|
15334
15346
|
function storeRoot(cwd) {
|
|
15335
|
-
const location = resolveStore(
|
|
15347
|
+
const location = resolveStore(path17.resolve(cwd));
|
|
15336
15348
|
if (location instanceof Error)
|
|
15337
15349
|
return err("unavailable", location.message.replace(/; fix the repository.*$/u, ""), "fix the repository (git status should work here) or run from a non-git directory");
|
|
15338
15350
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
15339
15351
|
}
|
|
15340
15352
|
function ledgerPath(cwd) {
|
|
15341
15353
|
const root = storeRoot(cwd);
|
|
15342
|
-
return root.ok ? { ok: true, value:
|
|
15354
|
+
return root.ok ? { ok: true, value: path17.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
15343
15355
|
}
|
|
15344
15356
|
function actorFromEnv(env) {
|
|
15345
15357
|
const value = (key) => {
|
|
@@ -15377,15 +15389,15 @@ function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
|
|
|
15377
15389
|
}
|
|
15378
15390
|
function appendLine(file, build, options) {
|
|
15379
15391
|
const write = () => {
|
|
15380
|
-
const fd =
|
|
15392
|
+
const fd = fs13.openSync(file, "a+", 384);
|
|
15381
15393
|
try {
|
|
15382
15394
|
if (process.platform !== "win32")
|
|
15383
15395
|
tighten(fd);
|
|
15384
|
-
const size =
|
|
15396
|
+
const size = fs13.fstatSync(fd).size;
|
|
15385
15397
|
let fence = "";
|
|
15386
15398
|
if (size > 0) {
|
|
15387
15399
|
const last = Buffer.alloc(1);
|
|
15388
|
-
|
|
15400
|
+
fs13.readSync(fd, last, 0, 1, size - 1);
|
|
15389
15401
|
if (last[0] !== 10)
|
|
15390
15402
|
fence = `
|
|
15391
15403
|
`;
|
|
@@ -15394,17 +15406,17 @@ function appendLine(file, build, options) {
|
|
|
15394
15406
|
if (!line.ok)
|
|
15395
15407
|
return line;
|
|
15396
15408
|
const bytes = Buffer.from(fence + line.value);
|
|
15397
|
-
const written =
|
|
15409
|
+
const written = fs13.writeSync(fd, bytes);
|
|
15398
15410
|
if (written !== bytes.length)
|
|
15399
15411
|
return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
|
|
15400
15412
|
return { ok: true, value: undefined };
|
|
15401
15413
|
} finally {
|
|
15402
|
-
|
|
15414
|
+
fs13.closeSync(fd);
|
|
15403
15415
|
}
|
|
15404
15416
|
};
|
|
15405
15417
|
try {
|
|
15406
|
-
|
|
15407
|
-
if (!options.forceLock && !onNetworkFs(
|
|
15418
|
+
fs13.mkdirSync(path17.dirname(file), { recursive: true });
|
|
15419
|
+
if (!options.forceLock && !onNetworkFs(path17.dirname(file)))
|
|
15408
15420
|
return write();
|
|
15409
15421
|
const locked = withLedgerLock(file, write);
|
|
15410
15422
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -15461,8 +15473,8 @@ function readLedger(cwd, options = {}) {
|
|
|
15461
15473
|
let text = "";
|
|
15462
15474
|
let stat = null;
|
|
15463
15475
|
try {
|
|
15464
|
-
stat =
|
|
15465
|
-
text =
|
|
15476
|
+
stat = fs13.statSync(file.value);
|
|
15477
|
+
text = fs13.readFileSync(file.value, "utf8");
|
|
15466
15478
|
} catch (error) {
|
|
15467
15479
|
if (error.code === "ENOENT")
|
|
15468
15480
|
return {
|
|
@@ -15594,7 +15606,7 @@ function ledgerTampering(cwd) {
|
|
|
15594
15606
|
if (!file.ok)
|
|
15595
15607
|
return [];
|
|
15596
15608
|
try {
|
|
15597
|
-
const stat =
|
|
15609
|
+
const stat = fs13.statSync(file.value);
|
|
15598
15610
|
const cached = tamperCache.get(file.value);
|
|
15599
15611
|
if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
|
|
15600
15612
|
return cached.breaks;
|
|
@@ -16011,8 +16023,14 @@ function leadOnly(context, lead) {
|
|
|
16011
16023
|
return { ok: true, value: undefined };
|
|
16012
16024
|
return err("blocked", lead !== null ? `session ${session ?? "(none)"} is not the fanout's lead (${lead}): standing orders come from the lead` : `session ${session} is a worker or verifier: standing orders come from the lead`, lead !== null ? `the lead in a new session? workit fanout plan <plan.json> --take-lead from this session; a worker or verifier reports the order to the lead instead` : "a worker or verifier reports the order to the lead instead");
|
|
16013
16025
|
}
|
|
16026
|
+
function signalStanding(cwd, result) {
|
|
16027
|
+
const root = result.ok ? storeRoot(cwd) : null;
|
|
16028
|
+
if (result.ok && root?.ok && root.value.shared)
|
|
16029
|
+
bumpStandingRev(root.value.root, result.value.id);
|
|
16030
|
+
return result;
|
|
16031
|
+
}
|
|
16014
16032
|
function recordStanding(context, input) {
|
|
16015
|
-
const what = required2(input.what, "<order>");
|
|
16033
|
+
const what = input.stop ? { ok: true, value: stopOrderText(input.what?.trim() || null) } : required2(input.what, "<order>");
|
|
16016
16034
|
if (!what.ok)
|
|
16017
16035
|
return what;
|
|
16018
16036
|
if (/\p{Cc}/u.test(what.value))
|
|
@@ -16023,12 +16041,14 @@ function recordStanding(context, input) {
|
|
|
16023
16041
|
const link = checkSupersede(context, "standing");
|
|
16024
16042
|
if (!link.ok)
|
|
16025
16043
|
return link;
|
|
16026
|
-
|
|
16044
|
+
const recorded = appendRow(context.cwd, {
|
|
16027
16045
|
...common(context, noteKey(context)),
|
|
16028
16046
|
type: "standing",
|
|
16029
16047
|
fanout: input.fanout,
|
|
16030
|
-
what: what.value
|
|
16048
|
+
what: what.value,
|
|
16049
|
+
...input.stop ? { stop: true } : {}
|
|
16031
16050
|
}, { now: context.now });
|
|
16051
|
+
return signalStanding(context.cwd, recorded);
|
|
16032
16052
|
}
|
|
16033
16053
|
function clearStanding(context, input) {
|
|
16034
16054
|
const lead = leadOnly(context, input.lead);
|
|
@@ -16041,12 +16061,31 @@ function clearStanding(context, input) {
|
|
|
16041
16061
|
if (!activeStanding(ledger.value.rows, input.fanout, input.leads ?? null).some((row) => row.id === input.target))
|
|
16042
16062
|
return err("not_found", `no standing order ${input.target} in force for fanout ${input.fanout}`, `workit ledger standing list --fanout ${input.fanout}`);
|
|
16043
16063
|
}
|
|
16044
|
-
return appendRow(context.cwd, {
|
|
16064
|
+
return signalStanding(context.cwd, appendRow(context.cwd, {
|
|
16045
16065
|
...common(context, noteKey(context)),
|
|
16046
16066
|
type: "standing.cleared",
|
|
16047
16067
|
fanout: input.fanout,
|
|
16048
16068
|
target: input.target
|
|
16049
|
-
}, { now: context.now });
|
|
16069
|
+
}, { now: context.now }));
|
|
16070
|
+
}
|
|
16071
|
+
function liftStop(context, input) {
|
|
16072
|
+
const lead = leadOnly(context, input.lead);
|
|
16073
|
+
if (!lead.ok)
|
|
16074
|
+
return lead;
|
|
16075
|
+
const ledger = readLedger(context.cwd);
|
|
16076
|
+
if (!ledger.ok)
|
|
16077
|
+
return ledger;
|
|
16078
|
+
const stops = activeStanding(ledger.value.rows, input.fanout, input.leads ?? null).filter((row) => row.stop === true);
|
|
16079
|
+
if (!stops.length)
|
|
16080
|
+
return err("not_found", `no stop line in force for fanout ${input.fanout}`, `workit ledger standing list --fanout ${input.fanout}`);
|
|
16081
|
+
const cleared = [];
|
|
16082
|
+
for (const stop of stops) {
|
|
16083
|
+
const row = clearStanding(context, { ...input, target: stop.id });
|
|
16084
|
+
if (!row.ok)
|
|
16085
|
+
return row;
|
|
16086
|
+
cleared.push(row.value);
|
|
16087
|
+
}
|
|
16088
|
+
return { ok: true, value: cleared };
|
|
16050
16089
|
}
|
|
16051
16090
|
function dirtyElsewhere(cwd, branch, head) {
|
|
16052
16091
|
if (headSha(cwd) === head)
|
|
@@ -16202,17 +16241,17 @@ function summarizeRow(row) {
|
|
|
16202
16241
|
};
|
|
16203
16242
|
}
|
|
16204
16243
|
function stackPosition(root, branch) {
|
|
16205
|
-
const dir =
|
|
16244
|
+
const dir = path17.join(root, "stacks");
|
|
16206
16245
|
let names = [];
|
|
16207
16246
|
try {
|
|
16208
|
-
names =
|
|
16247
|
+
names = fs13.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
16209
16248
|
} catch {
|
|
16210
16249
|
return null;
|
|
16211
16250
|
}
|
|
16212
16251
|
for (const name of names.toSorted()) {
|
|
16213
16252
|
let parsed;
|
|
16214
16253
|
try {
|
|
16215
|
-
parsed = JSON.parse(
|
|
16254
|
+
parsed = JSON.parse(fs13.readFileSync(path17.join(dir, name), "utf8"));
|
|
16216
16255
|
} catch {
|
|
16217
16256
|
continue;
|
|
16218
16257
|
}
|
|
@@ -16351,20 +16390,20 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, VERDICT_RESULTS, PASSING, FAILING
|
|
|
16351
16390
|
if (process.platform !== "linux")
|
|
16352
16391
|
return false;
|
|
16353
16392
|
try {
|
|
16354
|
-
return isNetworkFsType(
|
|
16393
|
+
return isNetworkFsType(fs13.statfsSync(dir).type);
|
|
16355
16394
|
} catch {
|
|
16356
16395
|
return false;
|
|
16357
16396
|
}
|
|
16358
16397
|
}, LOCK_WAIT_MS = 5000, LOCK_STALE_MS = 30000, LOCK_OWNER = "owner", lockToken = (lock) => {
|
|
16359
16398
|
try {
|
|
16360
|
-
return
|
|
16399
|
+
return fs13.readFileSync(path17.join(lock, LOCK_OWNER), "utf8");
|
|
16361
16400
|
} catch {
|
|
16362
16401
|
return null;
|
|
16363
16402
|
}
|
|
16364
16403
|
}, lockAgeMs = (lock) => {
|
|
16365
|
-
for (const target of [
|
|
16404
|
+
for (const target of [path17.join(lock, LOCK_OWNER), lock]) {
|
|
16366
16405
|
try {
|
|
16367
|
-
return Date.now() -
|
|
16406
|
+
return Date.now() - fs13.statSync(target).mtimeMs;
|
|
16368
16407
|
} catch {}
|
|
16369
16408
|
}
|
|
16370
16409
|
return null;
|
|
@@ -16372,7 +16411,7 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, VERDICT_RESULTS, PASSING, FAILING
|
|
|
16372
16411
|
${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
16373
16412
|
for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
|
|
16374
16413
|
const buffer = Buffer.alloc(span);
|
|
16375
|
-
|
|
16414
|
+
fs13.readSync(fd, buffer, 0, span, size - span);
|
|
16376
16415
|
const end = buffer.lastIndexOf(10);
|
|
16377
16416
|
if (end < 0) {
|
|
16378
16417
|
if (span === size)
|
|
@@ -16402,8 +16441,8 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
16402
16441
|
return null;
|
|
16403
16442
|
}, tighten = (fd) => {
|
|
16404
16443
|
try {
|
|
16405
|
-
if ((
|
|
16406
|
-
|
|
16444
|
+
if ((fs13.fstatSync(fd).mode & 63) !== 0)
|
|
16445
|
+
fs13.fchmodSync(fd, 384);
|
|
16407
16446
|
} catch {}
|
|
16408
16447
|
}, sealed = (row, id, at, previous) => {
|
|
16409
16448
|
const { prevHash: _prev, rowHash: _row, ...fields } = row;
|
|
@@ -16465,7 +16504,7 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
16465
16504
|
}, required2 = (value, flag) => {
|
|
16466
16505
|
const text = value?.trim();
|
|
16467
16506
|
return text ? { ok: true, value: text } : err("invalid_input", `${flag} is required`);
|
|
16468
|
-
}, fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session), isDelegateSession = (session) => session !== null && (/-w-[a-z0-9._-]+(?:\+try\d)?$/u.test(session) || /-v\d+$/u.test(session) || session.includes(":")), OBSERVED_ONLY, MAX_DIRTY_PATHS = 10, dirtyState = (cwd) => {
|
|
16507
|
+
}, fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session), isDelegateSession = (session) => session !== null && (/-w-[a-z0-9._-]+(?:\+try\d)?$/u.test(session) || /-v\d+$/u.test(session) || session.includes(":")), stopOrderText = (note) => `STOP: start nothing new, stop every process you started (dev servers, browsers, watchers), commit only finished work, and report to the lead now${note ? ` (${note})` : ""}`, OBSERVED_ONLY, MAX_DIRTY_PATHS = 10, dirtyState = (cwd) => {
|
|
16469
16508
|
const run = gitRun2(cwd, ["status", "--porcelain=v1", "-z", "--untracked-files=normal"], GIT_TIMEOUTS.worktree);
|
|
16470
16509
|
if (!run.ok)
|
|
16471
16510
|
return { dirty: false, files: 0, paths: [] };
|
|
@@ -16502,6 +16541,7 @@ var init_ledger = __esm(() => {
|
|
|
16502
16541
|
init_vcs_config();
|
|
16503
16542
|
init_rev();
|
|
16504
16543
|
init_host_session();
|
|
16544
|
+
init_standing_signal();
|
|
16505
16545
|
init_paths();
|
|
16506
16546
|
VERDICT_RESULTS = [
|
|
16507
16547
|
"verified",
|
|
@@ -16536,14 +16576,14 @@ var init_ledger = __esm(() => {
|
|
|
16536
16576
|
ledgerLock = {
|
|
16537
16577
|
acquire(lock) {
|
|
16538
16578
|
try {
|
|
16539
|
-
|
|
16579
|
+
fs13.mkdirSync(lock);
|
|
16540
16580
|
} catch (error) {
|
|
16541
16581
|
if (error.code === "EEXIST")
|
|
16542
16582
|
return null;
|
|
16543
16583
|
throw error;
|
|
16544
16584
|
}
|
|
16545
16585
|
const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
|
|
16546
|
-
|
|
16586
|
+
fs13.writeFileSync(path17.join(lock, LOCK_OWNER), token);
|
|
16547
16587
|
return token;
|
|
16548
16588
|
},
|
|
16549
16589
|
release(lock, token) {
|
|
@@ -16551,35 +16591,35 @@ var init_ledger = __esm(() => {
|
|
|
16551
16591
|
return false;
|
|
16552
16592
|
const tomb = `${lock}.release-${randomBytes3(6).toString("hex")}`;
|
|
16553
16593
|
try {
|
|
16554
|
-
|
|
16594
|
+
fs13.renameSync(lock, tomb);
|
|
16555
16595
|
} catch {
|
|
16556
16596
|
return false;
|
|
16557
16597
|
}
|
|
16558
16598
|
if (lockToken(tomb) !== token) {
|
|
16559
16599
|
try {
|
|
16560
|
-
|
|
16600
|
+
fs13.renameSync(tomb, lock);
|
|
16561
16601
|
} catch {}
|
|
16562
16602
|
return false;
|
|
16563
16603
|
}
|
|
16564
|
-
|
|
16604
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
16565
16605
|
return true;
|
|
16566
16606
|
},
|
|
16567
16607
|
token: lockToken,
|
|
16568
16608
|
reap(lock, observed) {
|
|
16569
16609
|
const tomb = `${lock}.reap-${randomBytes3(6).toString("hex")}`;
|
|
16570
16610
|
try {
|
|
16571
|
-
|
|
16611
|
+
fs13.renameSync(lock, tomb);
|
|
16572
16612
|
} catch {
|
|
16573
16613
|
return false;
|
|
16574
16614
|
}
|
|
16575
16615
|
if (lockToken(tomb) === observed) {
|
|
16576
|
-
|
|
16616
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
16577
16617
|
return true;
|
|
16578
16618
|
}
|
|
16579
16619
|
try {
|
|
16580
|
-
|
|
16620
|
+
fs13.renameSync(tomb, lock);
|
|
16581
16621
|
} catch {
|
|
16582
|
-
|
|
16622
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
16583
16623
|
}
|
|
16584
16624
|
return false;
|
|
16585
16625
|
}
|
|
@@ -16613,7 +16653,7 @@ var init_ledger = __esm(() => {
|
|
|
16613
16653
|
|
|
16614
16654
|
// packages/workit-core/src/core/policy/derive.ts
|
|
16615
16655
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16616
|
-
import
|
|
16656
|
+
import path18 from "node:path";
|
|
16617
16657
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
16618
16658
|
const out = [];
|
|
16619
16659
|
const base = { scope, dependentAction: null };
|
|
@@ -16754,7 +16794,7 @@ var RULES, derived2 = (spec) => ({
|
|
|
16754
16794
|
decisionIds: []
|
|
16755
16795
|
};
|
|
16756
16796
|
}, planRecorded = (task, root) => {
|
|
16757
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(
|
|
16797
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path18.resolve(root, ref.path)));
|
|
16758
16798
|
if (cited)
|
|
16759
16799
|
return {
|
|
16760
16800
|
met: true,
|
|
@@ -16801,13 +16841,13 @@ var init_derive = __esm(() => {
|
|
|
16801
16841
|
|
|
16802
16842
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
16803
16843
|
import { createHash as createHash11 } from "node:crypto";
|
|
16804
|
-
import * as
|
|
16844
|
+
import * as fs14 from "node:fs";
|
|
16805
16845
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
16806
|
-
import
|
|
16846
|
+
import path19 from "node:path";
|
|
16807
16847
|
function captureCandidate(root, scope, environment = []) {
|
|
16808
16848
|
let checkout;
|
|
16809
16849
|
try {
|
|
16810
|
-
checkout =
|
|
16850
|
+
checkout = fs14.realpathSync(root);
|
|
16811
16851
|
} catch {
|
|
16812
16852
|
return failure2("invalid_input", "candidate root does not exist");
|
|
16813
16853
|
}
|
|
@@ -16825,11 +16865,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
16825
16865
|
if (item === ".git" || item === ".workit")
|
|
16826
16866
|
continue;
|
|
16827
16867
|
names.add(item);
|
|
16828
|
-
if (!
|
|
16868
|
+
if (!fs14.existsSync(target))
|
|
16829
16869
|
continue;
|
|
16830
16870
|
let stat;
|
|
16831
16871
|
try {
|
|
16832
|
-
stat =
|
|
16872
|
+
stat = fs14.lstatSync(target);
|
|
16833
16873
|
} catch {
|
|
16834
16874
|
uncertain = true;
|
|
16835
16875
|
continue;
|
|
@@ -16845,17 +16885,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
16845
16885
|
for (const item of [...names].toSorted()) {
|
|
16846
16886
|
if (!scopeMatches(item, normalizedScope))
|
|
16847
16887
|
continue;
|
|
16848
|
-
const target =
|
|
16888
|
+
const target = path19.join(checkout, item);
|
|
16849
16889
|
try {
|
|
16850
|
-
const stat =
|
|
16890
|
+
const stat = fs14.lstatSync(target);
|
|
16851
16891
|
if (stat.isSymbolicLink()) {
|
|
16852
|
-
const link =
|
|
16892
|
+
const link = fs14.readlinkSync(target);
|
|
16853
16893
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
16854
16894
|
} else if (stat.isFile()) {
|
|
16855
16895
|
files.push({
|
|
16856
16896
|
path: item,
|
|
16857
16897
|
kind: "file",
|
|
16858
|
-
digest: digestBytes(
|
|
16898
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
16859
16899
|
executable: (stat.mode & 73) !== 0
|
|
16860
16900
|
});
|
|
16861
16901
|
} else if (!stat.isDirectory()) {
|
|
@@ -17254,12 +17294,12 @@ function boundTaskSummary(summary) {
|
|
|
17254
17294
|
brief.truncated = JSON.stringify(brief).includes("…") || progress.blockers.length > BRIEF_BLOCKERS || unmet.length > BRIEF_OPEN;
|
|
17255
17295
|
return brief;
|
|
17256
17296
|
}
|
|
17257
|
-
var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
17297
|
+
var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path19.sep}`), relative = (root, candidate) => path19.relative(root, candidate).split(path19.sep).join("/") || ".", canonicalPath = (value) => {
|
|
17258
17298
|
if (typeof value !== "string" || !value)
|
|
17259
17299
|
return null;
|
|
17260
17300
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
17261
17301
|
return null;
|
|
17262
|
-
const normalized =
|
|
17302
|
+
const normalized = path19.posix.normalize(value);
|
|
17263
17303
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
17264
17304
|
return null;
|
|
17265
17305
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -17301,20 +17341,20 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17301
17341
|
git: !/not a git repository/i.test(stderr)
|
|
17302
17342
|
};
|
|
17303
17343
|
}
|
|
17304
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
17344
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")) : [];
|
|
17305
17345
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
17306
17346
|
if (stagedDeleted.status !== 0) {
|
|
17307
17347
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
17308
17348
|
if (!/not a git repository/i.test(stderr))
|
|
17309
17349
|
return { paths, uncertain: true, git: true };
|
|
17310
17350
|
} else if (stagedDeleted.stdout) {
|
|
17311
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
17351
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path19.sep).join("/")));
|
|
17312
17352
|
}
|
|
17313
17353
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
17314
17354
|
}, walk = (root, directory, output) => {
|
|
17315
17355
|
let names;
|
|
17316
17356
|
try {
|
|
17317
|
-
names =
|
|
17357
|
+
names = fs14.readdirSync(directory);
|
|
17318
17358
|
} catch {
|
|
17319
17359
|
return true;
|
|
17320
17360
|
}
|
|
@@ -17322,10 +17362,10 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17322
17362
|
for (const name of names) {
|
|
17323
17363
|
if (name === ".git" || name === ".workit")
|
|
17324
17364
|
continue;
|
|
17325
|
-
const target =
|
|
17365
|
+
const target = path19.join(directory, name);
|
|
17326
17366
|
let stat;
|
|
17327
17367
|
try {
|
|
17328
|
-
stat =
|
|
17368
|
+
stat = fs14.lstatSync(target);
|
|
17329
17369
|
} catch {
|
|
17330
17370
|
uncertain = true;
|
|
17331
17371
|
continue;
|
|
@@ -17339,14 +17379,14 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17339
17379
|
}, scopeRoots = (root, scope) => {
|
|
17340
17380
|
const roots = [];
|
|
17341
17381
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
17342
|
-
const target =
|
|
17382
|
+
const target = path19.resolve(root, item);
|
|
17343
17383
|
if (!inside(root, target))
|
|
17344
17384
|
return failure2("invalid_input", `candidate scope escapes checkout: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} is outside the checkout` }] });
|
|
17345
17385
|
let ancestor = target;
|
|
17346
|
-
while (!
|
|
17347
|
-
ancestor =
|
|
17386
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
17387
|
+
ancestor = path19.dirname(ancestor);
|
|
17348
17388
|
try {
|
|
17349
|
-
if (!inside(root,
|
|
17389
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
17350
17390
|
return failure2("invalid_input", `candidate scope escapes checkout through a symlink: ${item} — keep one task per repository and coordinate a separate linked task in the other checkout`, { fields: [{ path: "scope.paths", reason: `${item} resolves outside the checkout` }] });
|
|
17351
17391
|
} catch {
|
|
17352
17392
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -17399,7 +17439,7 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17399
17439
|
}, findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId != null), verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
17400
17440
|
let root;
|
|
17401
17441
|
try {
|
|
17402
|
-
root =
|
|
17442
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
17403
17443
|
} catch {
|
|
17404
17444
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
17405
17445
|
}
|
|
@@ -17408,23 +17448,23 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17408
17448
|
continue;
|
|
17409
17449
|
if (!reference.digest)
|
|
17410
17450
|
return failure2("invalid_input", "document references require a byte digest");
|
|
17411
|
-
const target =
|
|
17412
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
17451
|
+
const target = path19.resolve(root, reference.path);
|
|
17452
|
+
if (target !== root && !target.startsWith(`${root}${path19.sep}`))
|
|
17413
17453
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
17414
17454
|
fields: [
|
|
17415
17455
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
17416
17456
|
]
|
|
17417
17457
|
});
|
|
17418
17458
|
try {
|
|
17419
|
-
const below =
|
|
17459
|
+
const below = path19.relative(root, target);
|
|
17420
17460
|
let current = root;
|
|
17421
|
-
for (const segment of below.split(
|
|
17461
|
+
for (const segment of below.split(path19.sep)) {
|
|
17422
17462
|
if (!segment)
|
|
17423
17463
|
continue;
|
|
17424
|
-
current =
|
|
17425
|
-
const stat =
|
|
17426
|
-
const real =
|
|
17427
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
17464
|
+
current = path19.join(current, segment);
|
|
17465
|
+
const stat = fs14.lstatSync(current);
|
|
17466
|
+
const real = fs14.realpathSync(current);
|
|
17467
|
+
if (real !== root && !real.startsWith(`${root}${path19.sep}`))
|
|
17428
17468
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
17429
17469
|
fields: [
|
|
17430
17470
|
{
|
|
@@ -17440,7 +17480,7 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
17440
17480
|
if (current !== target && !stat.isDirectory())
|
|
17441
17481
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
17442
17482
|
}
|
|
17443
|
-
if (digestBytes(
|
|
17483
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
17444
17484
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
17445
17485
|
} catch {
|
|
17446
17486
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -18089,7 +18129,7 @@ var init_shell_words = __esm(() => {
|
|
|
18089
18129
|
|
|
18090
18130
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
18091
18131
|
import os4 from "node:os";
|
|
18092
|
-
import
|
|
18132
|
+
import path20 from "node:path";
|
|
18093
18133
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
18094
18134
|
if (depth > 0)
|
|
18095
18135
|
return walk2(command, dialect, depth);
|
|
@@ -18271,12 +18311,12 @@ function simpleCommand(command, dialect = "posix", depth = 0) {
|
|
|
18271
18311
|
return null;
|
|
18272
18312
|
return words;
|
|
18273
18313
|
}
|
|
18274
|
-
var SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, GIT_CONFIG_OPTIONS, GIT_CONFIG_ENV, ASSIGNMENT, MAX_DEPTH = 4, MAX_EXPANSIONS = 16, isAbsolute = (value) =>
|
|
18314
|
+
var SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLARATIONS, SCRIPT_FLAG, CD, PUSHD, POPD, GIT_VALUE_OPTIONS, GIT_CONFIG_OPTIONS, GIT_CONFIG_ENV, ASSIGNMENT, MAX_DEPTH = 4, MAX_EXPANSIONS = 16, isAbsolute = (value) => path20.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"), HERE, joinDir = (base, raw) => {
|
|
18275
18315
|
const next = raw.replace(HERE, ".");
|
|
18276
18316
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
18277
18317
|
return;
|
|
18278
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
18279
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
18318
|
+
const expanded = next === "~" || next.startsWith("~/") ? path20.join(os4.homedir(), next.slice(1)) : next;
|
|
18319
|
+
return base === null || isAbsolute(expanded) ? expanded : path20.join(base, expanded);
|
|
18280
18320
|
}, rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner), cdTarget = (words) => {
|
|
18281
18321
|
const args = words.slice(1);
|
|
18282
18322
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -18795,7 +18835,7 @@ import {
|
|
|
18795
18835
|
unlinkSync as unlinkSync2,
|
|
18796
18836
|
writeFileSync as writeFileSync3
|
|
18797
18837
|
} from "node:fs";
|
|
18798
|
-
import
|
|
18838
|
+
import path21 from "node:path";
|
|
18799
18839
|
function writeFileExclusive(file, content, mode) {
|
|
18800
18840
|
try {
|
|
18801
18841
|
writeFileSync3(file, content, { encoding: "utf8", flag: "wx", mode });
|
|
@@ -18807,9 +18847,9 @@ function writeFileExclusive(file, content, mode) {
|
|
|
18807
18847
|
}
|
|
18808
18848
|
}
|
|
18809
18849
|
function writeFileAtomic(file, content, mode) {
|
|
18810
|
-
const absolute =
|
|
18811
|
-
let parent =
|
|
18812
|
-
const root =
|
|
18850
|
+
const absolute = path21.resolve(file);
|
|
18851
|
+
let parent = path21.dirname(absolute);
|
|
18852
|
+
const root = path21.parse(parent).root;
|
|
18813
18853
|
for (;; ) {
|
|
18814
18854
|
try {
|
|
18815
18855
|
if (lstatSync3(parent).isSymbolicLink())
|
|
@@ -18818,12 +18858,12 @@ function writeFileAtomic(file, content, mode) {
|
|
|
18818
18858
|
if (error.code !== "ENOENT")
|
|
18819
18859
|
throw error;
|
|
18820
18860
|
}
|
|
18821
|
-
const next =
|
|
18861
|
+
const next = path21.dirname(parent);
|
|
18822
18862
|
if (parent === root || next === parent)
|
|
18823
18863
|
break;
|
|
18824
18864
|
parent = next;
|
|
18825
18865
|
}
|
|
18826
|
-
const directory =
|
|
18866
|
+
const directory = path21.dirname(absolute);
|
|
18827
18867
|
mkdirSync4(directory, { recursive: true });
|
|
18828
18868
|
let existing = null;
|
|
18829
18869
|
try {
|
|
@@ -18863,7 +18903,7 @@ var init_safe_write = () => {};
|
|
|
18863
18903
|
// packages/workit-core/src/autonomy.ts
|
|
18864
18904
|
import { copyFileSync as copyFileSync3, existsSync as existsSync6 } from "node:fs";
|
|
18865
18905
|
import os5 from "node:os";
|
|
18866
|
-
import
|
|
18906
|
+
import path22 from "node:path";
|
|
18867
18907
|
function endpointOf(entry) {
|
|
18868
18908
|
const raw = entry?.defaultEndpoint;
|
|
18869
18909
|
if (raw === undefined)
|
|
@@ -19106,9 +19146,9 @@ var accountHome = () => {
|
|
|
19106
19146
|
} catch {
|
|
19107
19147
|
return os5.homedir();
|
|
19108
19148
|
}
|
|
19109
|
-
}, grantsHome, grantsDir = () =>
|
|
19110
|
-
const configured =
|
|
19111
|
-
return configured ===
|
|
19149
|
+
}, grantsHome, grantsDir = () => path22.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
|
|
19150
|
+
const configured = path22.resolve(resolveConfigDir());
|
|
19151
|
+
return configured === path22.resolve(grantsDir()) ? null : `the config directory is redirected to ${configured} (WORKFLOW_TOOLKIT_CONFIG, WORKFLOW_TOOLKIT_CONFIG_DIR or XDG_CONFIG_HOME); grants are read only from ${path22.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
19112
19152
|
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), raisesEndpoint = (current, next) => DEFAULT_ENDPOINTS.indexOf(next) > DEFAULT_ENDPOINTS.indexOf(current), DEFAULT_VERIFICATION = "self", verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self", isGrantKind = (value) => typeof value === "string" && GRANT_KINDS.includes(value), isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
|
|
19113
19153
|
if (value === true)
|
|
19114
19154
|
return { push: true, pr: true, merge: "verified" };
|
|
@@ -20842,12 +20882,12 @@ var init_pr_body = __esm(() => {
|
|
|
20842
20882
|
});
|
|
20843
20883
|
|
|
20844
20884
|
// packages/workit-core/src/core/pr-create.ts
|
|
20845
|
-
import
|
|
20885
|
+
import path23 from "node:path";
|
|
20846
20886
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
20847
20887
|
import { pathToFileURL } from "node:url";
|
|
20848
20888
|
var safePushUrl = (remote) => {
|
|
20849
20889
|
const raw = remote.trim();
|
|
20850
|
-
if (
|
|
20890
|
+
if (path23.isAbsolute(raw))
|
|
20851
20891
|
return pathToFileURL(raw).href;
|
|
20852
20892
|
if (!raw.includes("://")) {
|
|
20853
20893
|
const scp = /^(?:([^@\s]+)@)?([^:]+):(.+)$/u.exec(raw);
|
|
@@ -20907,16 +20947,16 @@ var init_scripts = __esm(() => {
|
|
|
20907
20947
|
});
|
|
20908
20948
|
|
|
20909
20949
|
// packages/workit-core/src/core/youtrack.ts
|
|
20910
|
-
import
|
|
20911
|
-
import
|
|
20950
|
+
import fs15 from "node:fs";
|
|
20951
|
+
import path24 from "node:path";
|
|
20912
20952
|
function readYouTrackConfig(required) {
|
|
20913
20953
|
const cfgPath = youTrackConfigPath();
|
|
20914
|
-
if (!
|
|
20954
|
+
if (!fs15.existsSync(cfgPath)) {
|
|
20915
20955
|
return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
|
|
20916
20956
|
}
|
|
20917
20957
|
let parsed;
|
|
20918
20958
|
try {
|
|
20919
|
-
parsed = JSON.parse(
|
|
20959
|
+
parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
|
|
20920
20960
|
} catch {
|
|
20921
20961
|
return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
|
|
20922
20962
|
}
|
|
@@ -20932,22 +20972,22 @@ function youTrackConfigLoad() {
|
|
|
20932
20972
|
}
|
|
20933
20973
|
const cfgPath = loaded.path;
|
|
20934
20974
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
20935
|
-
const tokenPath = tokenFile ?
|
|
20936
|
-
if (!tokenPath || !
|
|
20975
|
+
const tokenPath = tokenFile ? path24.isAbsolute(tokenFile) ? path24.resolve(tokenFile) : path24.resolve(process.cwd(), tokenFile) : "";
|
|
20976
|
+
if (!tokenPath || !fs15.existsSync(tokenPath)) {
|
|
20937
20977
|
return { error: "missing youtrack.token" };
|
|
20938
20978
|
}
|
|
20939
20979
|
if (!youTrackTokenModeOk(tokenPath)) {
|
|
20940
20980
|
return { error: "youtrack.token mode must be 0600" };
|
|
20941
20981
|
}
|
|
20942
|
-
const token =
|
|
20982
|
+
const token = fs15.readFileSync(tokenPath, "utf8").trim();
|
|
20943
20983
|
if (!token || token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
|
|
20944
20984
|
return { error: "token file still placeholder — edit locally, then /wk-status" };
|
|
20945
20985
|
}
|
|
20946
20986
|
const redacted = { ...loaded.config };
|
|
20947
20987
|
delete redacted.tokenFile;
|
|
20948
20988
|
redacted.tokenPresent = true;
|
|
20949
|
-
redacted.configPath =
|
|
20950
|
-
redacted.tokenPath =
|
|
20989
|
+
redacted.configPath = path24.resolve(cfgPath);
|
|
20990
|
+
redacted.tokenPath = path24.resolve(tokenPath);
|
|
20951
20991
|
return { data: redacted };
|
|
20952
20992
|
}
|
|
20953
20993
|
function tzParts(date, tz) {
|
|
@@ -20976,10 +21016,10 @@ function youTrackParseDuration(text) {
|
|
|
20976
21016
|
function youTrackWorkDateMs(dateRaw) {
|
|
20977
21017
|
const cfgPath = youTrackConfigPath();
|
|
20978
21018
|
let effective = effectiveWorkTimezone(null);
|
|
20979
|
-
if (
|
|
21019
|
+
if (fs15.existsSync(cfgPath)) {
|
|
20980
21020
|
let parsed;
|
|
20981
21021
|
try {
|
|
20982
|
-
parsed = JSON.parse(
|
|
21022
|
+
parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
|
|
20983
21023
|
} catch {
|
|
20984
21024
|
return { error: `${cfgPath} is not valid JSON` };
|
|
20985
21025
|
}
|
|
@@ -21119,9 +21159,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
|
|
|
21119
21159
|
} catch {
|
|
21120
21160
|
continue;
|
|
21121
21161
|
}
|
|
21122
|
-
if (!
|
|
21162
|
+
if (!fs15.existsSync(full))
|
|
21123
21163
|
continue;
|
|
21124
|
-
const text =
|
|
21164
|
+
const text = fs15.readFileSync(full, "utf8");
|
|
21125
21165
|
const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
|
|
21126
21166
|
if (m)
|
|
21127
21167
|
return m[1];
|
|
@@ -21270,18 +21310,18 @@ async function postUpdate({
|
|
|
21270
21310
|
}
|
|
21271
21311
|
return { ok: true, issueId, postedComment: true };
|
|
21272
21312
|
}
|
|
21273
|
-
var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
21313
|
+
var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(configDir(), "youtrack.json"), youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(resolveConfigDir(), "youtrack.json"), youTrackTokenModeOk = (p) => {
|
|
21274
21314
|
if (process.platform === "win32")
|
|
21275
21315
|
return true;
|
|
21276
|
-
const mode =
|
|
21316
|
+
const mode = fs15.statSync(p).mode & 511;
|
|
21277
21317
|
return mode === 384;
|
|
21278
21318
|
}, readYouTrackContextConfig = () => {
|
|
21279
21319
|
const cfgPath = youTrackReadOnlyConfigPath();
|
|
21280
|
-
if (!
|
|
21320
|
+
if (!fs15.existsSync(cfgPath))
|
|
21281
21321
|
return { data: {} };
|
|
21282
21322
|
let parsed;
|
|
21283
21323
|
try {
|
|
21284
|
-
parsed = JSON.parse(
|
|
21324
|
+
parsed = JSON.parse(fs15.readFileSync(cfgPath, "utf8"));
|
|
21285
21325
|
} catch {
|
|
21286
21326
|
return { error: "YouTrack configuration is unavailable" };
|
|
21287
21327
|
}
|
|
@@ -21312,12 +21352,12 @@ var ISSUE_RE, TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE", youTrackConfigPath = () =>
|
|
|
21312
21352
|
if ("error" in loaded)
|
|
21313
21353
|
return loaded;
|
|
21314
21354
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
21315
|
-
const tokenPath = tokenFile ?
|
|
21316
|
-
if (!tokenPath || !
|
|
21355
|
+
const tokenPath = tokenFile ? path24.isAbsolute(tokenFile) ? path24.resolve(tokenFile) : path24.resolve(process.cwd(), tokenFile) : "";
|
|
21356
|
+
if (!tokenPath || !fs15.existsSync(tokenPath))
|
|
21317
21357
|
return { error: "missing youtrack.token" };
|
|
21318
21358
|
if (!youTrackTokenModeOk(tokenPath))
|
|
21319
21359
|
return { error: "youtrack.token mode must be 0600" };
|
|
21320
|
-
const token =
|
|
21360
|
+
const token = fs15.readFileSync(tokenPath, "utf8").trim();
|
|
21321
21361
|
if (!token)
|
|
21322
21362
|
return { error: "empty token file" };
|
|
21323
21363
|
if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
|
|
@@ -21417,18 +21457,18 @@ var init_context_read = __esm(() => {
|
|
|
21417
21457
|
|
|
21418
21458
|
// packages/workit-core/src/core.ts
|
|
21419
21459
|
import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
21420
|
-
import
|
|
21460
|
+
import path25 from "node:path";
|
|
21421
21461
|
function resolveInside(root, candidate) {
|
|
21422
21462
|
const base = realpathSync5(root);
|
|
21423
|
-
const target =
|
|
21424
|
-
if (target !== base && !target.startsWith(base +
|
|
21463
|
+
const target = path25.resolve(base, candidate);
|
|
21464
|
+
if (target !== base && !target.startsWith(base + path25.sep)) {
|
|
21425
21465
|
throw new Error("path must stay inside repository root");
|
|
21426
21466
|
}
|
|
21427
21467
|
let ancestor = target;
|
|
21428
21468
|
while (!existsSync7(ancestor))
|
|
21429
|
-
ancestor =
|
|
21469
|
+
ancestor = path25.dirname(ancestor);
|
|
21430
21470
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
21431
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
21471
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path25.sep)) {
|
|
21432
21472
|
throw new Error("path must stay inside repository root");
|
|
21433
21473
|
}
|
|
21434
21474
|
return target;
|
|
@@ -21454,7 +21494,7 @@ var init_core3 = __esm(() => {
|
|
|
21454
21494
|
|
|
21455
21495
|
// packages/workit-cli/src/task.ts
|
|
21456
21496
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
21457
|
-
import
|
|
21497
|
+
import path26 from "node:path";
|
|
21458
21498
|
async function readInput(input) {
|
|
21459
21499
|
if (typeof input === "string")
|
|
21460
21500
|
return input;
|
|
@@ -21781,7 +21821,7 @@ var TASK_FAMILIES, workspaceRootFor = (deps = {}) => {
|
|
|
21781
21821
|
return explicit;
|
|
21782
21822
|
const cwd = deps.cwd ?? process.cwd();
|
|
21783
21823
|
const top = checkRoot(cwd);
|
|
21784
|
-
return sameDirectoryIdentity(top,
|
|
21824
|
+
return sameDirectoryIdentity(top, path26.resolve(cwd)) ? cwd : top;
|
|
21785
21825
|
}, TASK_ACTIONS, outOf = (deps) => deps.out ?? process.stdout, errOf = (deps) => deps.err ?? process.stderr, write = (stream, value) => stream.write(value.endsWith(`
|
|
21786
21826
|
`) ? value : `${value}
|
|
21787
21827
|
`), jsonResult = (stream, result) => write(stream, JSON.stringify(result)), usage = (message) => failure2("invalid_input", message), parseUsage = (message, json) => ({
|
|
@@ -25834,7 +25874,7 @@ var init_wrap_ansi = __esm(() => {
|
|
|
25834
25874
|
// node_modules/terminal-size/index.js
|
|
25835
25875
|
import process3 from "node:process";
|
|
25836
25876
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
25837
|
-
import
|
|
25877
|
+
import fs16 from "node:fs";
|
|
25838
25878
|
import tty from "node:tty";
|
|
25839
25879
|
function terminalSize() {
|
|
25840
25880
|
const { env, stdout, stderr } = process3;
|
|
@@ -25882,7 +25922,7 @@ var defaultColumns = 80, defaultRows = 24, exec2 = (command, arguments_, { shell
|
|
|
25882
25922
|
return true;
|
|
25883
25923
|
}
|
|
25884
25924
|
try {
|
|
25885
|
-
const statContents =
|
|
25925
|
+
const statContents = fs16.readFileSync("/proc/self/stat", "utf8");
|
|
25886
25926
|
const closingParenthesisIndex = statContents.lastIndexOf(") ");
|
|
25887
25927
|
if (closingParenthesisIndex === -1) {
|
|
25888
25928
|
return false;
|
|
@@ -25902,8 +25942,8 @@ var defaultColumns = 80, defaultRows = 24, exec2 = (command, arguments_, { shell
|
|
|
25902
25942
|
}
|
|
25903
25943
|
}, devTty = () => {
|
|
25904
25944
|
try {
|
|
25905
|
-
const flags = process3.platform === "darwin" ?
|
|
25906
|
-
const { columns, rows } = tty.WriteStream(
|
|
25945
|
+
const flags = process3.platform === "darwin" ? fs16.constants.O_EVTONLY | fs16.constants.O_NONBLOCK : fs16.constants.O_NONBLOCK;
|
|
25946
|
+
const { columns, rows } = tty.WriteStream(fs16.openSync("/dev/tty", flags));
|
|
25907
25947
|
return { columns, rows };
|
|
25908
25948
|
} catch {}
|
|
25909
25949
|
}, tput = () => {
|
|
@@ -61016,7 +61056,7 @@ var init_Text = __esm(() => {
|
|
|
61016
61056
|
});
|
|
61017
61057
|
|
|
61018
61058
|
// node_modules/ink/build/components/ErrorOverview.js
|
|
61019
|
-
import * as
|
|
61059
|
+
import * as fs17 from "node:fs";
|
|
61020
61060
|
import { cwd } from "node:process";
|
|
61021
61061
|
function ErrorOverview({ error }) {
|
|
61022
61062
|
const stack = error.stack ? error.stack.split(`
|
|
@@ -61026,8 +61066,8 @@ function ErrorOverview({ error }) {
|
|
|
61026
61066
|
let excerpt;
|
|
61027
61067
|
let lineWidth = 0;
|
|
61028
61068
|
const stackLineCounts = new Map;
|
|
61029
|
-
if (filePath && origin?.line &&
|
|
61030
|
-
const sourceCode =
|
|
61069
|
+
if (filePath && origin?.line && fs17.existsSync(filePath)) {
|
|
61070
|
+
const sourceCode = fs17.readFileSync(filePath, "utf8");
|
|
61031
61071
|
excerpt = dist_default3(sourceCode, origin.line);
|
|
61032
61072
|
if (excerpt) {
|
|
61033
61073
|
for (const { line } of excerpt) {
|
|
@@ -64692,8 +64732,8 @@ var init_gitignore = __esm(() => {
|
|
|
64692
64732
|
});
|
|
64693
64733
|
|
|
64694
64734
|
// packages/workit-core/src/core/changelog.ts
|
|
64695
|
-
import
|
|
64696
|
-
import
|
|
64735
|
+
import fs18 from "node:fs";
|
|
64736
|
+
import path27 from "node:path";
|
|
64697
64737
|
import { createHash as createHash13 } from "node:crypto";
|
|
64698
64738
|
function normalizeBullet(text) {
|
|
64699
64739
|
text = text.trim();
|
|
@@ -64853,8 +64893,8 @@ function applyChangelog(target, entries, normalizeOnly) {
|
|
|
64853
64893
|
const rendered = renderChangelog(source.text, entries, normalizeOnly);
|
|
64854
64894
|
if ("error" in rendered)
|
|
64855
64895
|
return { error: rendered.error };
|
|
64856
|
-
|
|
64857
|
-
|
|
64896
|
+
fs18.mkdirSync(path27.dirname(target), { recursive: true });
|
|
64897
|
+
fs18.writeFileSync(target, rendered.text, "utf8");
|
|
64858
64898
|
return { ...rendered.result, path: target };
|
|
64859
64899
|
}
|
|
64860
64900
|
function renderChangelog(source, entries, normalizeOnly) {
|
|
@@ -64982,12 +65022,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
64982
65022
|
## [Unreleased]
|
|
64983
65023
|
|
|
64984
65024
|
`, digestBytes2 = (value) => createHash13("sha256").update(value).digest("hex"), readChangelogSource = (target) => {
|
|
64985
|
-
if (!
|
|
65025
|
+
if (!fs18.existsSync(target)) {
|
|
64986
65026
|
const bytes = Buffer.from(SKELETON, "utf8");
|
|
64987
65027
|
return { exists: false, bytes, text: SKELETON };
|
|
64988
65028
|
}
|
|
64989
65029
|
try {
|
|
64990
|
-
const bytes =
|
|
65030
|
+
const bytes = fs18.readFileSync(target);
|
|
64991
65031
|
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
64992
65032
|
return { exists: true, bytes, text };
|
|
64993
65033
|
} catch {
|
|
@@ -64995,17 +65035,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
64995
65035
|
}
|
|
64996
65036
|
}, changelogTarget = (workspaceRoot, changelogPath) => {
|
|
64997
65037
|
try {
|
|
64998
|
-
const cwd =
|
|
64999
|
-
const target =
|
|
65000
|
-
if (target !== cwd && !target.startsWith(cwd +
|
|
65038
|
+
const cwd = fs18.realpathSync(resolveWorkspaceRoot(workspaceRoot));
|
|
65039
|
+
const target = path27.resolve(cwd, changelogPath || "CHANGELOG.md");
|
|
65040
|
+
if (target !== cwd && !target.startsWith(cwd + path27.sep))
|
|
65001
65041
|
return { error: "changelog path must be inside workspace_root" };
|
|
65002
65042
|
let ancestor = target;
|
|
65003
|
-
while (!
|
|
65004
|
-
ancestor =
|
|
65005
|
-
const canonicalAncestor =
|
|
65006
|
-
if (canonicalAncestor !== cwd && !canonicalAncestor.startsWith(cwd +
|
|
65043
|
+
while (!fs18.existsSync(ancestor))
|
|
65044
|
+
ancestor = path27.dirname(ancestor);
|
|
65045
|
+
const canonicalAncestor = fs18.realpathSync(ancestor);
|
|
65046
|
+
if (canonicalAncestor !== cwd && !canonicalAncestor.startsWith(cwd + path27.sep))
|
|
65007
65047
|
return { error: "changelog path must be inside workspace_root" };
|
|
65008
|
-
return { cwd, target:
|
|
65048
|
+
return { cwd, target: fs18.existsSync(target) ? fs18.realpathSync(target) : target };
|
|
65009
65049
|
} catch {
|
|
65010
65050
|
return { error: "changelog path must be inside workspace_root" };
|
|
65011
65051
|
}
|
|
@@ -65023,22 +65063,22 @@ var init_changelog = __esm(() => {
|
|
|
65023
65063
|
// packages/workit-core/src/core/hygiene.ts
|
|
65024
65064
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
65025
65065
|
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as readdirSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
65026
|
-
import
|
|
65027
|
-
var repoRoot2, templatesDir = () =>
|
|
65028
|
-
if (!existsSync9(
|
|
65066
|
+
import path28 from "node:path";
|
|
65067
|
+
var repoRoot2, templatesDir = () => path28.join(repoRoot2, "templates", "hygiene"), packageJson = (root) => {
|
|
65068
|
+
if (!existsSync9(path28.join(root, "package.json")))
|
|
65029
65069
|
return null;
|
|
65030
65070
|
try {
|
|
65031
|
-
return JSON.parse(readFileSync9(
|
|
65071
|
+
return JSON.parse(readFileSync9(path28.join(root, "package.json"), "utf8"));
|
|
65032
65072
|
} catch {
|
|
65033
65073
|
return null;
|
|
65034
65074
|
}
|
|
65035
65075
|
}, isOpenSource = (root) => {
|
|
65036
|
-
if (existsSync9(
|
|
65076
|
+
if (existsSync9(path28.join(root, "LICENSE")))
|
|
65037
65077
|
return true;
|
|
65038
65078
|
const pkg = packageJson(root);
|
|
65039
65079
|
if (pkg && !pkg.private)
|
|
65040
65080
|
return true;
|
|
65041
|
-
return
|
|
65081
|
+
return path28.basename(root) === "workflow-toolkit";
|
|
65042
65082
|
}, licenseHolder = (root) => {
|
|
65043
65083
|
const pkg = packageJson(root);
|
|
65044
65084
|
if (pkg) {
|
|
@@ -65053,14 +65093,14 @@ var repoRoot2, templatesDir = () => path27.join(repoRoot2, "templates", "hygiene
|
|
|
65053
65093
|
}
|
|
65054
65094
|
return "";
|
|
65055
65095
|
}, projectTarget = (dir) => {
|
|
65056
|
-
const start =
|
|
65096
|
+
const start = path28.resolve(dir);
|
|
65057
65097
|
const top = spawnSync12("git", ["rev-parse", "--show-toplevel"], { cwd: start, encoding: "utf8" });
|
|
65058
65098
|
const root = top.status === 0 ? (top.stdout ?? "").trim() : "";
|
|
65059
65099
|
if (root)
|
|
65060
|
-
return { ok: true, root:
|
|
65100
|
+
return { ok: true, root: path28.resolve(root) };
|
|
65061
65101
|
let children = [];
|
|
65062
65102
|
try {
|
|
65063
|
-
children = readdirSync5(start, { withFileTypes: true }).filter((entry) => entry.isDirectory() && existsSync9(
|
|
65103
|
+
children = readdirSync5(start, { withFileTypes: true }).filter((entry) => entry.isDirectory() && existsSync9(path28.join(start, entry.name, ".git"))).map((entry) => path28.join(start, entry.name)).toSorted();
|
|
65064
65104
|
} catch {
|
|
65065
65105
|
children = [];
|
|
65066
65106
|
}
|
|
@@ -65076,13 +65116,13 @@ var repoRoot2, templatesDir = () => path27.join(repoRoot2, "templates", "hygiene
|
|
|
65076
65116
|
files.push("LICENSE", "CONTRIBUTING.md");
|
|
65077
65117
|
const planned = [];
|
|
65078
65118
|
for (const file of files) {
|
|
65079
|
-
if (existsSync9(
|
|
65119
|
+
if (existsSync9(path28.join(root, file)))
|
|
65080
65120
|
continue;
|
|
65081
|
-
const tpl =
|
|
65121
|
+
const tpl = path28.join(templatesDir(), file);
|
|
65082
65122
|
if (!existsSync9(tpl))
|
|
65083
65123
|
continue;
|
|
65084
|
-
const content = readFileSync9(tpl, "utf8").replace(/<PROJECT>/g,
|
|
65085
|
-
planned.push({ path:
|
|
65124
|
+
const content = readFileSync9(tpl, "utf8").replace(/<PROJECT>/g, path28.basename(root)).replace(/<YEAR>/g, String(new Date().getFullYear())).replace(/<HOLDER>\s*/g, licenseHolder(root));
|
|
65125
|
+
planned.push({ path: path28.join(root, file), content });
|
|
65086
65126
|
}
|
|
65087
65127
|
return planned;
|
|
65088
65128
|
};
|
|
@@ -65094,9 +65134,9 @@ var init_hygiene = __esm(() => {
|
|
|
65094
65134
|
|
|
65095
65135
|
// packages/workit-cli/src/admin/setup-state.ts
|
|
65096
65136
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
65097
|
-
import
|
|
65137
|
+
import path29 from "node:path";
|
|
65098
65138
|
var classifySetupFile = (dir, name) => {
|
|
65099
|
-
const file =
|
|
65139
|
+
const file = path29.join(dir, name);
|
|
65100
65140
|
let raw;
|
|
65101
65141
|
try {
|
|
65102
65142
|
raw = readFileSync10(file, "utf8");
|
|
@@ -65134,7 +65174,7 @@ var init_setup_state = __esm(() => {
|
|
|
65134
65174
|
});
|
|
65135
65175
|
|
|
65136
65176
|
// packages/workit-cli/src/admin/registration.ts
|
|
65137
|
-
import
|
|
65177
|
+
import path30 from "node:path";
|
|
65138
65178
|
function isWorkitPlugin(value) {
|
|
65139
65179
|
const s = String(value).replaceAll("\\", "/");
|
|
65140
65180
|
const url = s.startsWith("file://") || s.startsWith("git+file://");
|
|
@@ -65167,11 +65207,11 @@ function mergeCursorEnabledPlugins(enabled) {
|
|
|
65167
65207
|
}
|
|
65168
65208
|
function mergeCursorPluginDirs(pluginDirs, pluginDir) {
|
|
65169
65209
|
const strip = (p) => {
|
|
65170
|
-
const j =
|
|
65171
|
-
return
|
|
65210
|
+
const j = path30.join(p);
|
|
65211
|
+
return path30.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
|
|
65172
65212
|
};
|
|
65173
65213
|
const normalized = strip(pluginDir);
|
|
65174
|
-
const legacy = strip(
|
|
65214
|
+
const legacy = strip(path30.join(path30.dirname(pluginDir), "workflow-toolkit"));
|
|
65175
65215
|
const prev = Array.isArray(pluginDirs) ? pluginDirs.map(String) : [];
|
|
65176
65216
|
const kept = prev.filter((d) => strip(d) !== legacy);
|
|
65177
65217
|
const exists = kept.some((d) => strip(d) === normalized);
|
|
@@ -65259,7 +65299,7 @@ function cursorMcpServerEntry(_packageDir) {
|
|
|
65259
65299
|
function cursorHooksEntry(pluginDir) {
|
|
65260
65300
|
return { command: `${cursorHookLauncher(pluginDir)} workit-cursor-session-start`, args: [] };
|
|
65261
65301
|
}
|
|
65262
|
-
var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode", isRecord4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), named = (s, name) => s === name || s.startsWith(`${name}@`), CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest", cursorHookLauncher = (pluginDir) => pluginDir ? `node "${shellQuotedPath(
|
|
65302
|
+
var OPENCODE_NPM_PIN = "@brainervirus/workit-opencode", isRecord4 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), named = (s, name) => s === name || s.startsWith(`${name}@`), CURSOR_RUNTIME_PACKAGE = "@brainervirus/workit-cursor@latest", cursorHookLauncher = (pluginDir) => pluginDir ? `node "${shellQuotedPath(path30.join(pluginDir, "hooks", "launch.mjs"))}"` : 'node "${CURSOR_PLUGIN_ROOT}/hooks/launch.mjs"', shellQuotedPath = (file) => path30.sep === "\\" ? file : file.replace(/([$`"\\])/g, "\\$1"), CURSOR_HOOK_RUN_COMMAND, CURSOR_PRETOOLUSE_MATCHER = "Write|Edit|Delete|Shell|Remove|ApplyPatch|Apply_Patch|Patch|Rename|Mkdir|Mv|Cp|Touch", CURSOR_HOOK_EVENTS, canonicalHookEntry = (event, pluginDir) => {
|
|
65263
65303
|
const command = `${cursorHookLauncher(pluginDir)} workit-cursor-hook`;
|
|
65264
65304
|
if (event === "preToolUse")
|
|
65265
65305
|
return { command, matcher: CURSOR_PRETOOLUSE_MATCHER, failClosed: false };
|
|
@@ -65294,8 +65334,8 @@ var init_support_matrix = __esm(() => {
|
|
|
65294
65334
|
|
|
65295
65335
|
// packages/workit-core/src/core/heavy-scope.ts
|
|
65296
65336
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
65297
|
-
import
|
|
65298
|
-
import
|
|
65337
|
+
import fs19 from "node:fs";
|
|
65338
|
+
import path31 from "node:path";
|
|
65299
65339
|
function scopeSupport(env, platform = process.platform, read = readText2) {
|
|
65300
65340
|
if (platform !== "linux")
|
|
65301
65341
|
return { ok: false, reason: `no systemd scopes on ${platform}` };
|
|
@@ -65303,7 +65343,7 @@ function scopeSupport(env, platform = process.platform, read = readText2) {
|
|
|
65303
65343
|
return { ok: false, reason: "systemd-run is not on PATH" };
|
|
65304
65344
|
const uid = process.getuid?.() ?? 0;
|
|
65305
65345
|
const runtime = env.XDG_RUNTIME_DIR || `/run/user/${uid}`;
|
|
65306
|
-
if (!
|
|
65346
|
+
if (!fs19.existsSync(path31.join(runtime, "systemd", "private")))
|
|
65307
65347
|
return { ok: false, reason: "no user systemd manager is running" };
|
|
65308
65348
|
const controllers = read(`/sys/fs/cgroup/user.slice/user-${uid}.slice/user@${uid}.service/cgroup.controllers`);
|
|
65309
65349
|
if (controllers === null)
|
|
@@ -65366,13 +65406,13 @@ function probeScope(env = process.env) {
|
|
|
65366
65406
|
}
|
|
65367
65407
|
var readText2 = (file) => {
|
|
65368
65408
|
try {
|
|
65369
|
-
return
|
|
65409
|
+
return fs19.readFileSync(file, "utf8");
|
|
65370
65410
|
} catch {
|
|
65371
65411
|
return null;
|
|
65372
65412
|
}
|
|
65373
|
-
}, onPath = (command, env) => (env.PATH ?? "").split(
|
|
65413
|
+
}, onPath = (command, env) => (env.PATH ?? "").split(path31.delimiter).filter(Boolean).some((dir) => {
|
|
65374
65414
|
try {
|
|
65375
|
-
|
|
65415
|
+
fs19.accessSync(path31.join(dir, command), fs19.constants.X_OK);
|
|
65376
65416
|
return true;
|
|
65377
65417
|
} catch {
|
|
65378
65418
|
return false;
|
|
@@ -65392,7 +65432,7 @@ import {
|
|
|
65392
65432
|
statSync as statSync2
|
|
65393
65433
|
} from "node:fs";
|
|
65394
65434
|
import os8 from "node:os";
|
|
65395
|
-
import
|
|
65435
|
+
import path32 from "node:path";
|
|
65396
65436
|
function hostCommand(name, args, options = {}) {
|
|
65397
65437
|
const executable = findHostExecutable(name, options);
|
|
65398
65438
|
if (!executable)
|
|
@@ -65409,11 +65449,11 @@ function hostCommand(name, args, options = {}) {
|
|
|
65409
65449
|
return { command: executable, args, cwd: options.cwd, purpose: `${name} CLI` };
|
|
65410
65450
|
}
|
|
65411
65451
|
function resolveWindowsShimEntry(contents, shim, exists = existsSync11) {
|
|
65412
|
-
const root =
|
|
65452
|
+
const root = path32.win32.dirname(shim);
|
|
65413
65453
|
const matches = contents.matchAll(/(["']?)([^\r\n"']*node_modules[\\/][^\r\n"']+?\.js)\1/gi);
|
|
65414
65454
|
for (const match of matches) {
|
|
65415
65455
|
const raw = match[2].replace(/%~?dp0%?/gi, root);
|
|
65416
|
-
const candidate =
|
|
65456
|
+
const candidate = path32.win32.isAbsolute(raw) ? raw : path32.win32.resolve(root, raw);
|
|
65417
65457
|
if (exists(candidate))
|
|
65418
65458
|
return candidate;
|
|
65419
65459
|
}
|
|
@@ -65423,22 +65463,22 @@ function findHostExecutable(name, options = {}) {
|
|
|
65423
65463
|
const env = options.env ?? process.env;
|
|
65424
65464
|
const home = options.home ?? env.HOME ?? os8.homedir();
|
|
65425
65465
|
const suffixes = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
|
|
65426
|
-
const dirs = (env.PATH ?? "").split(
|
|
65427
|
-
dirs.push(
|
|
65466
|
+
const dirs = (env.PATH ?? "").split(path32.delimiter).filter(Boolean);
|
|
65467
|
+
dirs.push(path32.join(home, ".local", "bin"), path32.join(home, ".asdf", "shims"));
|
|
65428
65468
|
for (const [base, tail] of [
|
|
65429
|
-
[
|
|
65430
|
-
[
|
|
65469
|
+
[path32.join(home, ".local", "share", "fnm", "node-versions"), path32.join("installation", "bin")],
|
|
65470
|
+
[path32.join(home, ".nvm", "versions", "node"), "bin"]
|
|
65431
65471
|
]) {
|
|
65432
65472
|
try {
|
|
65433
65473
|
for (const entry of readdirSync6(base, { withFileTypes: true })) {
|
|
65434
65474
|
if (entry.isDirectory())
|
|
65435
|
-
dirs.push(
|
|
65475
|
+
dirs.push(path32.join(base, entry.name, tail));
|
|
65436
65476
|
}
|
|
65437
65477
|
} catch {}
|
|
65438
65478
|
}
|
|
65439
65479
|
for (const dir of dirs) {
|
|
65440
65480
|
for (const suffix of suffixes) {
|
|
65441
|
-
const candidate =
|
|
65481
|
+
const candidate = path32.join(dir, `${name}${suffix}`);
|
|
65442
65482
|
try {
|
|
65443
65483
|
if (statSync2(candidate).isFile()) {
|
|
65444
65484
|
if (process.platform === "win32")
|
|
@@ -65453,7 +65493,7 @@ function findHostExecutable(name, options = {}) {
|
|
|
65453
65493
|
}
|
|
65454
65494
|
function installedHostApp(host, home, env = process.env, platform = process.platform, exists = existsSync11) {
|
|
65455
65495
|
const candidates = [];
|
|
65456
|
-
const pathApi = platform === "win32" ?
|
|
65496
|
+
const pathApi = platform === "win32" ? path32.win32 : path32;
|
|
65457
65497
|
if (platform === "darwin") {
|
|
65458
65498
|
const app = host === "cursor" ? "Cursor.app" : host === "codex" ? "Codex.app" : host === "opencode" ? "OpenCode.app" : "";
|
|
65459
65499
|
if (app)
|
|
@@ -65558,8 +65598,8 @@ function planHostInstall(host, options = {}) {
|
|
|
65558
65598
|
const npmCli = npm ? findNpmCli(npm) : null;
|
|
65559
65599
|
if (!npmCli)
|
|
65560
65600
|
throw new Error("npm CLI could not be resolved; install Node.js 24+ and npm, then retry");
|
|
65561
|
-
const stage =
|
|
65562
|
-
const target = options.targetDir ??
|
|
65601
|
+
const stage = path32.join(home, ".cursor", "plugins", "local", ".workit-package-bootstrap");
|
|
65602
|
+
const target = options.targetDir ?? path32.join(home, ".cursor", "plugins", "local", "workit");
|
|
65563
65603
|
return [
|
|
65564
65604
|
nodePrerequisite({ home, cwd, env }),
|
|
65565
65605
|
{
|
|
@@ -65575,7 +65615,7 @@ function planHostInstall(host, options = {}) {
|
|
|
65575
65615
|
],
|
|
65576
65616
|
cwd,
|
|
65577
65617
|
purpose: upgrading ? "Download the current Workit Cursor adapter for the managed local plugin directory" : "Download the Workit Cursor adapter package for the managed local plugin directory",
|
|
65578
|
-
packageRoot:
|
|
65618
|
+
packageRoot: path32.join(stage, "node_modules", "@brainervirus", "workit-cursor"),
|
|
65579
65619
|
packageTarget: target
|
|
65580
65620
|
}
|
|
65581
65621
|
];
|
|
@@ -65657,10 +65697,10 @@ function runHostCommand(step, context = {}) {
|
|
|
65657
65697
|
env: (() => {
|
|
65658
65698
|
const home = context.home ?? context.env?.HOME ?? os8.homedir();
|
|
65659
65699
|
const env = { ...process.env, ...context.env, HOME: home };
|
|
65660
|
-
env.CODEX_HOME = context.env?.CODEX_HOME ??
|
|
65661
|
-
env.PI_CODING_AGENT_DIR = context.env?.PI_CODING_AGENT_DIR ??
|
|
65662
|
-
env.CLAUDE_CONFIG_DIR = context.env?.CLAUDE_CONFIG_DIR ??
|
|
65663
|
-
env.XDG_CONFIG_HOME = context.env?.XDG_CONFIG_HOME ??
|
|
65700
|
+
env.CODEX_HOME = context.env?.CODEX_HOME ?? path32.join(home, ".codex");
|
|
65701
|
+
env.PI_CODING_AGENT_DIR = context.env?.PI_CODING_AGENT_DIR ?? path32.join(home, ".pi", "agent");
|
|
65702
|
+
env.CLAUDE_CONFIG_DIR = context.env?.CLAUDE_CONFIG_DIR ?? path32.join(home, ".claude");
|
|
65703
|
+
env.XDG_CONFIG_HOME = context.env?.XDG_CONFIG_HOME ?? path32.join(home, ".config");
|
|
65664
65704
|
return env;
|
|
65665
65705
|
})(),
|
|
65666
65706
|
encoding: "utf8",
|
|
@@ -65695,7 +65735,7 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65695
65735
|
purpose: "Check the Node.js 24+ package runtime requirement"
|
|
65696
65736
|
};
|
|
65697
65737
|
}, isPiWorkitInstalled = (home, env = process.env) => {
|
|
65698
|
-
const settings =
|
|
65738
|
+
const settings = path32.join(env.PI_CODING_AGENT_DIR ?? path32.join(home, ".pi", "agent"), "settings.json");
|
|
65699
65739
|
try {
|
|
65700
65740
|
const document2 = JSON.parse(readFileSync11(settings, "utf8"));
|
|
65701
65741
|
return (document2.packages ?? []).some((entry) => {
|
|
@@ -65708,7 +65748,7 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65708
65748
|
}
|
|
65709
65749
|
}, OPENCODE_PLUGIN_SCOPE = "@brainervirus", OPENCODE_PLUGIN_NAME = "workit-opencode", packageVersionAt = (root, name) => {
|
|
65710
65750
|
try {
|
|
65711
|
-
const pkg = JSON.parse(readFileSync11(
|
|
65751
|
+
const pkg = JSON.parse(readFileSync11(path32.join(root, "package.json"), "utf8"));
|
|
65712
65752
|
return pkg.name === name && typeof pkg.version === "string" ? pkg.version : null;
|
|
65713
65753
|
} catch {
|
|
65714
65754
|
return null;
|
|
@@ -65722,17 +65762,17 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65722
65762
|
return d;
|
|
65723
65763
|
}
|
|
65724
65764
|
return 0;
|
|
65725
|
-
}, openCodeCacheDir = (home, env = process.env) =>
|
|
65765
|
+
}, openCodeCacheDir = (home, env = process.env) => path32.join(env.XDG_CACHE_HOME || path32.join(home, ".cache"), "opencode"), subdirs = (dir) => {
|
|
65726
65766
|
try {
|
|
65727
|
-
return readdirSync6(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
65767
|
+
return readdirSync6(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path32.join(dir, entry.name));
|
|
65728
65768
|
} catch {
|
|
65729
65769
|
return [];
|
|
65730
65770
|
}
|
|
65731
65771
|
}, openCodeInstalledPlugin = (home, env = process.env) => {
|
|
65732
65772
|
const name = `${OPENCODE_PLUGIN_SCOPE}/${OPENCODE_PLUGIN_NAME}`;
|
|
65733
65773
|
const cache = openCodeCacheDir(home, env);
|
|
65734
|
-
const specDirs = (layout) => subdirs(
|
|
65735
|
-
const installs = [...specDirs("npm").flatMap(subdirs), ...specDirs("packages")].map((dir) =>
|
|
65774
|
+
const specDirs = (layout) => subdirs(path32.join(cache, layout, OPENCODE_PLUGIN_SCOPE)).filter((dir) => path32.basename(dir) === `${OPENCODE_PLUGIN_NAME}@latest`);
|
|
65775
|
+
const installs = [...specDirs("npm").flatMap(subdirs), ...specDirs("packages")].map((dir) => path32.join(dir, "node_modules", OPENCODE_PLUGIN_SCOPE, OPENCODE_PLUGIN_NAME));
|
|
65736
65776
|
let best = null;
|
|
65737
65777
|
for (const root of installs) {
|
|
65738
65778
|
const version = packageVersionAt(root, name);
|
|
@@ -65742,8 +65782,8 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65742
65782
|
return best;
|
|
65743
65783
|
}, isCanonicalCodexPackage = (root) => {
|
|
65744
65784
|
for (const file of [
|
|
65745
|
-
|
|
65746
|
-
|
|
65785
|
+
path32.join(root, ".codex-plugin", "plugin.json"),
|
|
65786
|
+
path32.join(root, "package.json")
|
|
65747
65787
|
]) {
|
|
65748
65788
|
try {
|
|
65749
65789
|
const manifest = JSON.parse(readFileSync11(file, "utf8"));
|
|
@@ -65754,47 +65794,47 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65754
65794
|
}
|
|
65755
65795
|
return false;
|
|
65756
65796
|
}, isCodexWorkitInstalled = (home, env = process.env) => {
|
|
65757
|
-
const codexHome = env.CODEX_HOME ??
|
|
65797
|
+
const codexHome = env.CODEX_HOME ?? path32.join(home, ".codex");
|
|
65758
65798
|
const isPackageOrVersionDirectory = (root) => {
|
|
65759
65799
|
if (isCanonicalCodexPackage(root))
|
|
65760
65800
|
return true;
|
|
65761
65801
|
try {
|
|
65762
|
-
return readdirSync6(root, { withFileTypes: true }).some((entry) => entry.isDirectory() && isCanonicalCodexPackage(
|
|
65802
|
+
return readdirSync6(root, { withFileTypes: true }).some((entry) => entry.isDirectory() && isCanonicalCodexPackage(path32.join(root, entry.name)));
|
|
65763
65803
|
} catch {
|
|
65764
65804
|
return false;
|
|
65765
65805
|
}
|
|
65766
65806
|
};
|
|
65767
|
-
if (isPackageOrVersionDirectory(
|
|
65807
|
+
if (isPackageOrVersionDirectory(path32.join(codexHome, "plugins", "workit")))
|
|
65768
65808
|
return true;
|
|
65769
|
-
const root =
|
|
65809
|
+
const root = path32.join(codexHome, "plugins", "cache");
|
|
65770
65810
|
try {
|
|
65771
65811
|
for (const marketplace of readdirSync6(root, { withFileTypes: true })) {
|
|
65772
65812
|
if (!marketplace.isDirectory())
|
|
65773
65813
|
continue;
|
|
65774
|
-
if (isPackageOrVersionDirectory(
|
|
65814
|
+
if (isPackageOrVersionDirectory(path32.join(root, marketplace.name, "workit")))
|
|
65775
65815
|
return true;
|
|
65776
65816
|
}
|
|
65777
65817
|
} catch {
|
|
65778
65818
|
return false;
|
|
65779
65819
|
}
|
|
65780
65820
|
return false;
|
|
65781
|
-
}, claudeConfigDir = (home, env = process.env) => env.CLAUDE_CONFIG_DIR ??
|
|
65821
|
+
}, claudeConfigDir = (home, env = process.env) => env.CLAUDE_CONFIG_DIR ?? path32.join(home, ".claude"), CLAUDE_SCOPES, appliesTo = (install, cwd) => {
|
|
65782
65822
|
if (install.scope === "user")
|
|
65783
65823
|
return true;
|
|
65784
65824
|
if (cwd === null || install.projectPath === null)
|
|
65785
65825
|
return false;
|
|
65786
|
-
const relative =
|
|
65787
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
65826
|
+
const relative = path32.relative(path32.resolve(install.projectPath), path32.resolve(cwd));
|
|
65827
|
+
return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
|
|
65788
65828
|
}, isCanonicalClaudePlugin = (root) => {
|
|
65789
65829
|
try {
|
|
65790
|
-
const manifest = JSON.parse(readFileSync11(
|
|
65830
|
+
const manifest = JSON.parse(readFileSync11(path32.join(root, ".claude-plugin", "plugin.json"), "utf8"));
|
|
65791
65831
|
const repository = typeof manifest.repository === "string" ? manifest.repository : manifest.repository?.url;
|
|
65792
65832
|
return manifest.name === "workit" && repository?.replace(/\.git$/, "").toLowerCase() === "https://github.com/brainervirus/workit";
|
|
65793
65833
|
} catch {
|
|
65794
65834
|
return false;
|
|
65795
65835
|
}
|
|
65796
65836
|
}, claudeWorkitInstalls = (home, env = process.env, cwd = process.cwd()) => {
|
|
65797
|
-
const file =
|
|
65837
|
+
const file = path32.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json");
|
|
65798
65838
|
let registry;
|
|
65799
65839
|
try {
|
|
65800
65840
|
registry = JSON.parse(readFileSync11(file, "utf8"));
|
|
@@ -65829,14 +65869,14 @@ var resolveWindowsShimScript = (shim) => {
|
|
|
65829
65869
|
}, isClaudeWorkitInstalled = (home, env = process.env, cwd = process.cwd()) => claudeWorkitInstalls(home, env, cwd).length > 0, findNpmCli = (npm) => {
|
|
65830
65870
|
try {
|
|
65831
65871
|
const resolved = realpathSync6(npm);
|
|
65832
|
-
if (
|
|
65872
|
+
if (path32.basename(resolved) === "npm-cli.js")
|
|
65833
65873
|
return resolved;
|
|
65834
65874
|
} catch {}
|
|
65835
|
-
const dir =
|
|
65875
|
+
const dir = path32.dirname(npm);
|
|
65836
65876
|
const candidates = [
|
|
65837
|
-
|
|
65838
|
-
|
|
65839
|
-
|
|
65877
|
+
path32.join(dir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
65878
|
+
path32.join(dir, "..", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
65879
|
+
path32.join(dir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
65840
65880
|
];
|
|
65841
65881
|
return candidates.find((candidate) => existsSync11(candidate)) ?? null;
|
|
65842
65882
|
};
|
|
@@ -65847,21 +65887,21 @@ var init_host_install = __esm(() => {
|
|
|
65847
65887
|
|
|
65848
65888
|
// packages/workit-core/src/core/skill-manifests.ts
|
|
65849
65889
|
import { cpSync as cpSync3, existsSync as existsSync12, readFileSync as readFileSync12, readdirSync as readdirSync7, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
65850
|
-
import
|
|
65851
|
-
var WORKIT_METHOD_SKILLS, skillManifestNames = (root) => existsSync12(root) ? readdirSync7(root).filter((name) => existsSync12(
|
|
65890
|
+
import path33 from "node:path";
|
|
65891
|
+
var WORKIT_METHOD_SKILLS, skillManifestNames = (root) => existsSync12(root) ? readdirSync7(root).filter((name) => existsSync12(path33.join(root, name, "SKILL.md"))).toSorted() : [], validateSkillManifests = (root, expected, label) => {
|
|
65852
65892
|
const actual = skillManifestNames(root);
|
|
65853
65893
|
const missing = expected.filter((name) => !actual.includes(name));
|
|
65854
65894
|
const extra = actual.filter((name) => !expected.includes(name));
|
|
65855
65895
|
return missing.length === 0 && extra.length === 0 ? null : `${label} mismatch at ${root} (missing: ${missing.join(", ") || "none"}; extra: ${extra.join(", ") || "none"})`;
|
|
65856
65896
|
}, validateCursorSkills = (pluginDir, expected = WORKIT_METHOD_SKILLS) => {
|
|
65857
|
-
const workit = validateSkillManifests(
|
|
65897
|
+
const workit = validateSkillManifests(path33.join(pluginDir, "skills"), expected, "Cursor Workit skills");
|
|
65858
65898
|
if (workit)
|
|
65859
65899
|
return workit;
|
|
65860
|
-
const pending = [
|
|
65900
|
+
const pending = [path33.join(pluginDir, "skills")];
|
|
65861
65901
|
while (pending.length > 0) {
|
|
65862
65902
|
const dir = pending.pop();
|
|
65863
65903
|
for (const entry of readdirSync7(dir, { withFileTypes: true })) {
|
|
65864
|
-
const file =
|
|
65904
|
+
const file = path33.join(dir, entry.name);
|
|
65865
65905
|
if (entry.isDirectory())
|
|
65866
65906
|
pending.push(file);
|
|
65867
65907
|
else if ((statSync3(file).mode & 73) !== 0 || readFileSync12(file).subarray(0, 2).toString("latin1") === "#!") {
|
|
@@ -65903,7 +65943,7 @@ import {
|
|
|
65903
65943
|
statSync as statSync4,
|
|
65904
65944
|
writeFileSync as writeFileSync6
|
|
65905
65945
|
} from "node:fs";
|
|
65906
|
-
import
|
|
65946
|
+
import path34 from "node:path";
|
|
65907
65947
|
function inspectSessionHook(cwd, env = process.env) {
|
|
65908
65948
|
const none = { hooksDir: null, hookPath: null, helperPath: null, helperCurrent: false };
|
|
65909
65949
|
if (!existsSync13(cwd))
|
|
@@ -65915,8 +65955,8 @@ function inspectSessionHook(cwd, env = process.env) {
|
|
|
65915
65955
|
const [commonDir, hooksDir] = paths.out.split(/\r?\n/);
|
|
65916
65956
|
if (!paths.ok || !commonDir || !hooksDir)
|
|
65917
65957
|
return { state: "not_git", ...none };
|
|
65918
|
-
const hookPath =
|
|
65919
|
-
const helperPath =
|
|
65958
|
+
const hookPath = path34.join(hooksDir, SESSION_HOOK_NAME);
|
|
65959
|
+
const helperPath = path34.join(commonDir, ...HELPER);
|
|
65920
65960
|
const helperCurrent = readText3(helperPath) === SESSION_TRAILER_SCRIPT;
|
|
65921
65961
|
const leftover = leftoverOf(hooksDir);
|
|
65922
65962
|
const base = { hooksDir, hookPath, helperPath, helperCurrent, ...leftover ? { leftover } : {} };
|
|
@@ -65955,7 +65995,7 @@ function inspectSessionHook(cwd, env = process.env) {
|
|
|
65955
65995
|
return blocked(`${hookPath} belongs to ${owner === "other" ? "another hook" : owner}; Workit never replaces it`, owner, text);
|
|
65956
65996
|
}
|
|
65957
65997
|
if (!inside2(hooksDir, commonDir)) {
|
|
65958
|
-
const rel =
|
|
65998
|
+
const rel = path34.relative(top.out, hookPath).split(path34.sep).join("/");
|
|
65959
65999
|
if (!run2(top.out, ["check-ignore", "-q", "--", rel], env).ok)
|
|
65960
66000
|
return blocked(`${hooksDir} is in the working tree and not ignored; the hook would show up as a new file`, "other");
|
|
65961
66001
|
}
|
|
@@ -66096,8 +66136,8 @@ exit 0
|
|
|
66096
66136
|
});
|
|
66097
66137
|
return { ok: r.status === 0, out: (r.stdout ?? "").trim() };
|
|
66098
66138
|
}, inside2 = (child, parent) => {
|
|
66099
|
-
const rel =
|
|
66100
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
66139
|
+
const rel = path34.relative(path34.resolve(parent), path34.resolve(child));
|
|
66140
|
+
return rel === "" || !rel.startsWith("..") && !path34.isAbsolute(rel);
|
|
66101
66141
|
}, readText3 = (file) => {
|
|
66102
66142
|
try {
|
|
66103
66143
|
return readFileSync13(file, "utf8");
|
|
@@ -66111,7 +66151,7 @@ exit 0
|
|
|
66111
66151
|
} catch {
|
|
66112
66152
|
return false;
|
|
66113
66153
|
}
|
|
66114
|
-
}, LEFTHOOK_CONFIGS, lefthookConfig = (top) => LEFTHOOK_CONFIGS.map((name) =>
|
|
66154
|
+
}, LEFTHOOK_CONFIGS, lefthookConfig = (top) => LEFTHOOK_CONFIGS.map((name) => path34.join(top, name)).find((file) => existsSync13(file)) ?? null, isComment = (line) => /^\s*#/.test(line), COMMAND_SH, DIRECT_CALL, VAR_CALL, runsHelperText = (text) => {
|
|
66115
66155
|
const lines = text.split(/\r?\n/).filter((line) => !isComment(line));
|
|
66116
66156
|
const assigned = lines.some((line) => /(?:^|[\s;])h=/.test(line) && line.includes(HELPER_REF));
|
|
66117
66157
|
return lines.some((line) => DIRECT_CALL.test(line) || assigned && VAR_CALL.test(line));
|
|
@@ -66156,14 +66196,14 @@ exit 0
|
|
|
66156
66196
|
}, manualInPlace = (input, target) => {
|
|
66157
66197
|
if (input.owner === "lefthook")
|
|
66158
66198
|
return LEFTHOOK_YAML.some((name) => {
|
|
66159
|
-
const text = readText3(
|
|
66199
|
+
const text = readText3(path34.join(input.top, name));
|
|
66160
66200
|
return text !== null && lefthookRunsHelper(text);
|
|
66161
66201
|
});
|
|
66162
66202
|
const text = readText3(target);
|
|
66163
66203
|
if (text === null || !runsHelperText(text))
|
|
66164
66204
|
return false;
|
|
66165
66205
|
return input.owner === "husky" && target !== input.hookPath || isExecutable(target);
|
|
66166
|
-
}, isHuskyV9 = (text, hooksDir) => /\$\(dirname (?:-- )?"\$0"\)\/h"/.test(text) && existsSync13(
|
|
66206
|
+
}, isHuskyV9 = (text, hooksDir) => /\$\(dirname (?:-- )?"\$0"\)\/h"/.test(text) && existsSync13(path34.join(hooksDir, "h")), ownerOf = (text, hooksDir, top) => {
|
|
66167
66207
|
if (text.includes("husky.sh") || isHuskyV9(text, hooksDir))
|
|
66168
66208
|
return "husky";
|
|
66169
66209
|
if (/lefthook/i.test(text) || lefthookConfig(top))
|
|
@@ -66171,9 +66211,9 @@ exit 0
|
|
|
66171
66211
|
return "other";
|
|
66172
66212
|
}, manualTargetOf = ({ owner, text, hooksDir, hookPath, top }) => {
|
|
66173
66213
|
if (owner === "husky" && isHuskyV9(text, hooksDir))
|
|
66174
|
-
return
|
|
66214
|
+
return path34.join(path34.dirname(hooksDir), SESSION_HOOK_NAME);
|
|
66175
66215
|
if (owner === "lefthook")
|
|
66176
|
-
return lefthookConfig(top) ??
|
|
66216
|
+
return lefthookConfig(top) ?? path34.join(top, "lefthook.yml");
|
|
66177
66217
|
return hookPath;
|
|
66178
66218
|
}, manualFor = (input) => {
|
|
66179
66219
|
const { owner, displaced } = input;
|
|
@@ -66192,8 +66232,8 @@ exit 0
|
|
|
66192
66232
|
`);
|
|
66193
66233
|
return `add this line to ${target} (a new file needs \`#!/bin/sh\` as its first line and \`chmod +x\`)${stale}: ${manualTrailerLine()}`;
|
|
66194
66234
|
}, leftoverOf = (hooksDir) => {
|
|
66195
|
-
const chained =
|
|
66196
|
-
const commitMsg =
|
|
66235
|
+
const chained = path34.join(hooksDir, LEGACY_CHAINED);
|
|
66236
|
+
const commitMsg = path34.join(hooksDir, "commit-msg");
|
|
66197
66237
|
const oldOurs = readText3(commitMsg)?.includes(SESSION_HOOK_MARKER) ?? false;
|
|
66198
66238
|
if (exists(chained))
|
|
66199
66239
|
return oldOurs ? `${chained} was left by an earlier Workit build: move it back to ${commitMsg} (replacing Workit's old hook there)` : `${chained} was left by an earlier Workit build and nothing runs it: if it is your original commit-msg hook, move it back to ${commitMsg}; otherwise delete it`;
|
|
@@ -66201,7 +66241,7 @@ exit 0
|
|
|
66201
66241
|
return `${commitMsg} is a hook from an earlier Workit build; delete it (the trailer now comes from ${SESSION_HOOK_NAME})`;
|
|
66202
66242
|
return;
|
|
66203
66243
|
}, writeExecutable = (file, content) => {
|
|
66204
|
-
mkdirSync5(
|
|
66244
|
+
mkdirSync5(path34.dirname(file), { recursive: true });
|
|
66205
66245
|
const staged = `${file}.workit-new`;
|
|
66206
66246
|
try {
|
|
66207
66247
|
writeFileSync6(staged, content, { mode: 493 });
|
|
@@ -66264,13 +66304,13 @@ import {
|
|
|
66264
66304
|
writeFileSync as writeFileSync7
|
|
66265
66305
|
} from "node:fs";
|
|
66266
66306
|
import os9 from "node:os";
|
|
66267
|
-
import
|
|
66307
|
+
import path35 from "node:path";
|
|
66268
66308
|
var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
66269
|
-
let dir =
|
|
66309
|
+
let dir = path35.resolve(cwd);
|
|
66270
66310
|
while (true) {
|
|
66271
|
-
if (existsSync14(
|
|
66311
|
+
if (existsSync14(path35.join(dir, "packages", "workit-core", "package.json")))
|
|
66272
66312
|
return dir;
|
|
66273
|
-
const parent =
|
|
66313
|
+
const parent = path35.dirname(dir);
|
|
66274
66314
|
if (parent === dir)
|
|
66275
66315
|
return null;
|
|
66276
66316
|
dir = parent;
|
|
@@ -66278,8 +66318,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66278
66318
|
}, resolve = (options) => {
|
|
66279
66319
|
const env = options.env ?? process.env;
|
|
66280
66320
|
const home = options.home ?? env.HOME ?? os9.homedir();
|
|
66281
|
-
const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
66282
|
-
const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ??
|
|
66321
|
+
const configDir = options.configDir ?? env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path35.join(home, ".config", "workit");
|
|
66322
|
+
const stateDir = options.stateDir ?? env.WORKFLOW_TOOLKIT_STATE ?? path35.join(home, ".local", "state", "workit");
|
|
66283
66323
|
const cwd = options.cwd ?? process.cwd();
|
|
66284
66324
|
const dev = options.dev?.trim() || env.WORKFLOW_TOOLKIT_DEV?.trim() || findDevFromCwd(cwd);
|
|
66285
66325
|
return {
|
|
@@ -66290,11 +66330,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66290
66330
|
cwd,
|
|
66291
66331
|
workspaceRoot: options.workspaceRoot ?? env.WORKFLOW_WORKSPACE_ROOT ?? cwd,
|
|
66292
66332
|
dev,
|
|
66293
|
-
opencodeConfig: options.opencodeConfig ??
|
|
66333
|
+
opencodeConfig: options.opencodeConfig ?? path35.join(home, ".config", "opencode", "opencode.json"),
|
|
66294
66334
|
opencodePackageCacheDir: options.opencodePackageCacheDir ?? null,
|
|
66295
|
-
cursorSettings: options.cursorSettings ??
|
|
66296
|
-
cursorMcp: options.cursorMcp ??
|
|
66297
|
-
cursorPluginDir: options.cursorPluginDir ??
|
|
66335
|
+
cursorSettings: options.cursorSettings ?? path35.join(home, ".cursor", "settings.json"),
|
|
66336
|
+
cursorMcp: options.cursorMcp ?? path35.join(home, ".cursor", "mcp.json"),
|
|
66337
|
+
cursorPluginDir: options.cursorPluginDir ?? path35.join(home, ".cursor", "plugins", "local", "workit"),
|
|
66298
66338
|
cursorHeartbeatDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
|
|
66299
66339
|
hookStateDir: options.stateDir ?? (env.WORKFLOW_TOOLKIT_STATE || resolveStateDir()),
|
|
66300
66340
|
codexHome: options.codexHome,
|
|
@@ -66323,12 +66363,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66323
66363
|
...new Set(entries.filter((entry) => typeof entry === "string" && isWorkitPlugin(entry)))
|
|
66324
66364
|
];
|
|
66325
66365
|
}, commandOnPath = (name, env) => findOnPath(process.platform === "win32" ? [name, `${name}.exe`] : [name], env) !== null, pathextNames = (name, env) => process.platform === "win32" ? (env.PATHEXT ?? process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean).map((ext) => `${name}${ext.toLowerCase()}`) : [name], findOnPath = (names, env) => {
|
|
66326
|
-
const dirs = (env.PATH ?? process.env.PATH ?? "").split(
|
|
66366
|
+
const dirs = (env.PATH ?? process.env.PATH ?? "").split(path35.delimiter);
|
|
66327
66367
|
for (const dir of dirs) {
|
|
66328
66368
|
if (!dir)
|
|
66329
66369
|
continue;
|
|
66330
66370
|
for (const candidateName of names) {
|
|
66331
|
-
const candidate =
|
|
66371
|
+
const candidate = path35.join(dir, candidateName);
|
|
66332
66372
|
try {
|
|
66333
66373
|
const st = statSync5(candidate);
|
|
66334
66374
|
if (process.platform !== "win32" && (st.mode & 73) === 0)
|
|
@@ -66357,7 +66397,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66357
66397
|
if (env.BUN && existsSync14(env.BUN))
|
|
66358
66398
|
return env.BUN;
|
|
66359
66399
|
for (const candidate of [
|
|
66360
|
-
|
|
66400
|
+
path35.join(env.HOME || os9.homedir(), ".bun/bin/bun"),
|
|
66361
66401
|
"/usr/local/bin/bun",
|
|
66362
66402
|
"/usr/bin/bun"
|
|
66363
66403
|
]) {
|
|
@@ -66412,7 +66452,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66412
66452
|
detail: "installed package, not a dev checkout — version parity applies to checkouts only"
|
|
66413
66453
|
};
|
|
66414
66454
|
}
|
|
66415
|
-
const corePkg = readJson(
|
|
66455
|
+
const corePkg = readJson(path35.join(res.dev, "packages/workit-core/package.json"));
|
|
66416
66456
|
if (!corePkg) {
|
|
66417
66457
|
return {
|
|
66418
66458
|
id: "versions",
|
|
@@ -66422,7 +66462,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66422
66462
|
}
|
|
66423
66463
|
const refs = new Set;
|
|
66424
66464
|
for (const name of ["workit-opencode", "workit-cursor", "workit-cli"]) {
|
|
66425
|
-
const pkg = readJson(
|
|
66465
|
+
const pkg = readJson(path35.join(res.dev, "packages", name, "package.json"));
|
|
66426
66466
|
const dep = pkg?.dependencies?.["@brainervirus/workit-core"] ?? pkg?.devDependencies?.["@brainervirus/workit-core"];
|
|
66427
66467
|
if (typeof dep === "string")
|
|
66428
66468
|
refs.add(dep);
|
|
@@ -66438,7 +66478,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66438
66478
|
if (refs.size > 1) {
|
|
66439
66479
|
problems.push(`adapters pin different core versions: ${[...refs].join(", ")}`);
|
|
66440
66480
|
}
|
|
66441
|
-
const opencodePkg = readJson(
|
|
66481
|
+
const opencodePkg = readJson(path35.join(res.dev, "packages/workit-opencode/package.json"));
|
|
66442
66482
|
const sdk = opencodePkg?.dependencies?.["@opencode/plugin"] ?? opencodePkg?.devDependencies?.["@opencode/plugin"];
|
|
66443
66483
|
const sdkVersion = typeof sdk === "string" ? (sdk.match(/^\d+(?:\.\d+){0,2}/) ?? [])[0] : null;
|
|
66444
66484
|
if (sdkVersion && !semverAtLeast(sdkVersion, SUPPORT_MATRIX.opencode.minimum)) {
|
|
@@ -66465,14 +66505,14 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66465
66505
|
status: "pass",
|
|
66466
66506
|
detail: "opencode CLI not on PATH — skipping version check"
|
|
66467
66507
|
};
|
|
66468
|
-
const scratch = mkdtempSync(
|
|
66508
|
+
const scratch = mkdtempSync(path35.join(os9.tmpdir(), "workit-doctor-opencode-"));
|
|
66469
66509
|
let raw;
|
|
66470
66510
|
try {
|
|
66471
66511
|
raw = versionOf("opencode", {
|
|
66472
66512
|
...res.env,
|
|
66473
|
-
XDG_DATA_HOME:
|
|
66474
|
-
XDG_STATE_HOME:
|
|
66475
|
-
XDG_CACHE_HOME:
|
|
66513
|
+
XDG_DATA_HOME: path35.join(scratch, "data"),
|
|
66514
|
+
XDG_STATE_HOME: path35.join(scratch, "state"),
|
|
66515
|
+
XDG_CACHE_HOME: path35.join(scratch, "cache")
|
|
66476
66516
|
}, 5000);
|
|
66477
66517
|
} finally {
|
|
66478
66518
|
rmSync3(scratch, { recursive: true, force: true });
|
|
@@ -66574,19 +66614,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66574
66614
|
current[unquote(pair[1])] = value === "true" ? true : value === "false" ? false : unquote(value);
|
|
66575
66615
|
}
|
|
66576
66616
|
return tables;
|
|
66577
|
-
}, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME ||
|
|
66617
|
+
}, codexHomeOf = (res) => res.codexHome ?? (res.env.CODEX_HOME || path35.join(res.home, ".codex")), codexWorkitInstalls = (res) => {
|
|
66578
66618
|
const codexHome = codexHomeOf(res);
|
|
66579
|
-
const configFile =
|
|
66619
|
+
const configFile = path35.join(codexHome, "config.toml");
|
|
66580
66620
|
const installs = [];
|
|
66581
66621
|
for (const [key, table] of readTomlTables(configFile)) {
|
|
66582
66622
|
const [kind, id, ...rest] = key.split("\x00");
|
|
66583
66623
|
if (kind !== "plugins" || rest.length > 0 || !id?.startsWith("workit@") || table.enabled === false)
|
|
66584
66624
|
continue;
|
|
66585
66625
|
const marketplace = id.slice("workit@".length);
|
|
66586
|
-
const dir =
|
|
66626
|
+
const dir = path35.join(codexHome, "plugins", "cache", marketplace, "workit");
|
|
66587
66627
|
let versions = [];
|
|
66588
66628
|
try {
|
|
66589
|
-
versions = readdirSync8(dir).filter((v) => existsSync14(
|
|
66629
|
+
versions = readdirSync8(dir).filter((v) => existsSync14(path35.join(dir, v, ".codex-plugin")));
|
|
66590
66630
|
} catch {
|
|
66591
66631
|
versions = [];
|
|
66592
66632
|
}
|
|
@@ -66594,7 +66634,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66594
66634
|
installs.push({
|
|
66595
66635
|
id,
|
|
66596
66636
|
marketplace,
|
|
66597
|
-
root: version ?
|
|
66637
|
+
root: version ? path35.join(dir, version) : null,
|
|
66598
66638
|
version,
|
|
66599
66639
|
configFile
|
|
66600
66640
|
});
|
|
@@ -66616,7 +66656,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66616
66656
|
};
|
|
66617
66657
|
return `sha256:${createHash14("sha256").update(JSON.stringify(body)).digest("hex")}`;
|
|
66618
66658
|
}, codexHookTrust = (install, tables) => {
|
|
66619
|
-
const hooks = install.root ? readJson(
|
|
66659
|
+
const hooks = install.root ? readJson(path35.join(install.root, "hooks", "hooks.json"))?.hooks : null;
|
|
66620
66660
|
if (!hooks || typeof hooks !== "object")
|
|
66621
66661
|
return null;
|
|
66622
66662
|
const result = [];
|
|
@@ -66689,25 +66729,25 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66689
66729
|
status: "pass",
|
|
66690
66730
|
detail: "no Workit Codex plugin enabled — skipping"
|
|
66691
66731
|
};
|
|
66692
|
-
const agentsDir =
|
|
66732
|
+
const agentsDir = path35.join(codexHomeOf(res), "agents");
|
|
66693
66733
|
const problems = [];
|
|
66694
66734
|
const fixes = [];
|
|
66695
66735
|
const installed = [];
|
|
66696
66736
|
for (const install of installs) {
|
|
66697
|
-
const source = install.root ?
|
|
66737
|
+
const source = install.root ? path35.join(install.root, "agents") : null;
|
|
66698
66738
|
const files = source && existsSync14(source) ? readdirSync8(source).filter((f) => f.endsWith(".toml")).toSorted() : [];
|
|
66699
66739
|
if (files.length === 0) {
|
|
66700
66740
|
problems.push(`${install.id} ${install.version ?? "?"} bundles no agents`);
|
|
66701
66741
|
fixes.push(`codex plugin remove ${install.id} && codex plugin add ${install.id}`);
|
|
66702
66742
|
continue;
|
|
66703
66743
|
}
|
|
66704
|
-
const install_fix = `node ${JSON.stringify(
|
|
66705
|
-
const pluginVersion = readJson(
|
|
66744
|
+
const install_fix = `node ${JSON.stringify(path35.join(install.root, "dist", "launch-mcp.js"))} --install-agents, then start a new Codex session`;
|
|
66745
|
+
const pluginVersion = readJson(path35.join(install.root, "package.json"))?.version;
|
|
66706
66746
|
const version = typeof pluginVersion === "string" ? pluginVersion.match(SEMVER)?.[0] ?? null : null;
|
|
66707
66747
|
let stale = false;
|
|
66708
66748
|
for (const file of files) {
|
|
66709
|
-
const dest =
|
|
66710
|
-
const want = stampCodexAgent(readFileSync14(
|
|
66749
|
+
const dest = path35.join(agentsDir, file);
|
|
66750
|
+
const want = stampCodexAgent(readFileSync14(path35.join(source, file), "utf8"), version);
|
|
66711
66751
|
let link = false;
|
|
66712
66752
|
try {
|
|
66713
66753
|
link = lstatSync5(dest).isSymbolicLink();
|
|
@@ -66760,7 +66800,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66760
66800
|
const env = res.env.PI_CODING_AGENT_DIR;
|
|
66761
66801
|
if (env)
|
|
66762
66802
|
return env === "~" ? res.home : env.replace(/^~(?=\/|\\)/, res.home);
|
|
66763
|
-
return
|
|
66803
|
+
return path35.join(res.home, ".pi", "agent");
|
|
66764
66804
|
}, npmSpecName = (spec) => {
|
|
66765
66805
|
const at = spec.indexOf("@", spec.startsWith("@") ? 1 : 0);
|
|
66766
66806
|
return at > 0 ? { name: spec.slice(0, at), pinned: true } : { name: spec, pinned: false };
|
|
@@ -66768,10 +66808,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66768
66808
|
const scopes = [
|
|
66769
66809
|
{
|
|
66770
66810
|
scope: "project",
|
|
66771
|
-
settingsFile:
|
|
66772
|
-
base:
|
|
66811
|
+
settingsFile: path35.join(res.cwd, ".pi", "settings.json"),
|
|
66812
|
+
base: path35.join(res.cwd, ".pi")
|
|
66773
66813
|
},
|
|
66774
|
-
{ scope: "user", settingsFile:
|
|
66814
|
+
{ scope: "user", settingsFile: path35.join(agentDir, "settings.json"), base: agentDir }
|
|
66775
66815
|
];
|
|
66776
66816
|
for (const { scope, settingsFile, base } of scopes) {
|
|
66777
66817
|
const packages = readJson(settingsFile)?.packages;
|
|
@@ -66786,13 +66826,13 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66786
66826
|
const spec = npmSpecName(source.slice(4).trim());
|
|
66787
66827
|
if (spec.name !== PI_PACKAGE)
|
|
66788
66828
|
continue;
|
|
66789
|
-
const root =
|
|
66829
|
+
const root = path35.join(base, "npm", "node_modules", ...PI_PACKAGE.split("/"));
|
|
66790
66830
|
return { scope, settingsFile, source, filter, root, npm: { pinned: spec.pinned } };
|
|
66791
66831
|
}
|
|
66792
66832
|
if (/^(git:|https?:|ssh:|git@)/.test(source))
|
|
66793
66833
|
continue;
|
|
66794
|
-
const local =
|
|
66795
|
-
if (readJson(
|
|
66834
|
+
const local = path35.resolve(base, source.replace(/^~(?=\/|\\)/, res.home));
|
|
66835
|
+
if (readJson(path35.join(local, "package.json"))?.name === PI_PACKAGE)
|
|
66796
66836
|
return { scope, settingsFile, source, filter, root: local, npm: null };
|
|
66797
66837
|
}
|
|
66798
66838
|
}
|
|
@@ -66803,7 +66843,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66803
66843
|
const list = patterns.filter((p) => typeof p === "string");
|
|
66804
66844
|
if (list.length === 0)
|
|
66805
66845
|
return false;
|
|
66806
|
-
const name =
|
|
66846
|
+
const name = path35.posix.basename(file);
|
|
66807
66847
|
const matches = (p) => {
|
|
66808
66848
|
const re = globToRegExp3(p);
|
|
66809
66849
|
return re.test(file) || re.test(name);
|
|
@@ -66828,12 +66868,12 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66828
66868
|
return {
|
|
66829
66869
|
id: "pi_extension",
|
|
66830
66870
|
status: "warn",
|
|
66831
|
-
detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${
|
|
66871
|
+
detail: `Workit Pi extension missing: no ${PI_PACKAGE} entry in ${path35.join(agentDir, "settings.json")} or ${path35.join(res.cwd, ".pi", "settings.json")}`,
|
|
66832
66872
|
fix: installCmd("user")
|
|
66833
66873
|
};
|
|
66834
66874
|
const where = `${entry.source} (${entry.scope}, ${entry.settingsFile})`;
|
|
66835
66875
|
const rebuild = `cd ${JSON.stringify(entry.root)} && bun run build`;
|
|
66836
|
-
const pkg = readJson(
|
|
66876
|
+
const pkg = readJson(path35.join(entry.root, "package.json"));
|
|
66837
66877
|
if (!pkg)
|
|
66838
66878
|
return {
|
|
66839
66879
|
id: "pi_extension",
|
|
@@ -66842,7 +66882,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66842
66882
|
fix: entry.npm ? installCmd(entry.scope, entry.source) : `restore ${entry.root}, then ${rebuild}`
|
|
66843
66883
|
};
|
|
66844
66884
|
const declared = Array.isArray(pkg.pi?.extensions) ? pkg.pi.extensions.some((e) => typeof e === "string" && e.replace(/^\.\//, "") === PI_EXTENSION) : false;
|
|
66845
|
-
if (!declared || !existsSync14(
|
|
66885
|
+
if (!declared || !existsSync14(path35.join(entry.root, PI_EXTENSION)))
|
|
66846
66886
|
return {
|
|
66847
66887
|
id: "pi_extension",
|
|
66848
66888
|
status: "warn",
|
|
@@ -66895,21 +66935,21 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66895
66935
|
detail: `Workit Pi extension ${version ?? "?"} from ${where} loads ${PI_EXTENSION}`
|
|
66896
66936
|
};
|
|
66897
66937
|
}, assetPathsFor = (host, dev) => {
|
|
66898
|
-
const pkg =
|
|
66938
|
+
const pkg = path35.join(dev, "packages", `workit-${host}`);
|
|
66899
66939
|
switch (host) {
|
|
66900
66940
|
case "opencode": {
|
|
66901
|
-
const packaged =
|
|
66902
|
-
const root = existsSync14(packaged) ? packaged :
|
|
66903
|
-
return WORKIT_METHOD_SKILLS.map((skill) =>
|
|
66941
|
+
const packaged = path35.join(pkg, "assets", "skills");
|
|
66942
|
+
const root = existsSync14(packaged) ? packaged : path35.join(dev, "packages", "workit-core", "skills");
|
|
66943
|
+
return WORKIT_METHOD_SKILLS.map((skill) => path35.join(root, skill, "SKILL.md"));
|
|
66904
66944
|
}
|
|
66905
66945
|
case "cursor":
|
|
66906
66946
|
return [
|
|
66907
|
-
|
|
66908
|
-
|
|
66909
|
-
|
|
66947
|
+
path35.join(pkg, "assets", "templates", "workit-contract.md"),
|
|
66948
|
+
path35.join(pkg, "mcp.json"),
|
|
66949
|
+
path35.join(pkg, ".cursor-plugin")
|
|
66910
66950
|
];
|
|
66911
66951
|
case "cli":
|
|
66912
|
-
return [
|
|
66952
|
+
return [path35.join(pkg, "assets", "templates", "spec-template.md")];
|
|
66913
66953
|
}
|
|
66914
66954
|
}, hostsFor = (host) => host === "cli" ? ["opencode", "cursor", "cli"] : [host], checkAssets = (res) => {
|
|
66915
66955
|
const dev = res.dev;
|
|
@@ -66940,17 +66980,17 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66940
66980
|
fix: "Reinstall or rebuild the workit package (missing assets under packages/workit-<host>)"
|
|
66941
66981
|
};
|
|
66942
66982
|
}, launcherSlotsFor = (host, dev) => {
|
|
66943
|
-
const pkg =
|
|
66983
|
+
const pkg = path35.join(dev, "packages", `workit-${host}`);
|
|
66944
66984
|
switch (host) {
|
|
66945
66985
|
case "opencode":
|
|
66946
|
-
return [[
|
|
66986
|
+
return [[path35.join(pkg, "src", "plugin.ts"), path35.join(pkg, "dist", "plugin.js")]];
|
|
66947
66987
|
case "cursor":
|
|
66948
66988
|
return [
|
|
66949
|
-
[
|
|
66950
|
-
[
|
|
66989
|
+
[path35.join(pkg, "dist", "mcp-server.js")],
|
|
66990
|
+
[path35.join(pkg, "dist", "cursor-session-start.js")]
|
|
66951
66991
|
];
|
|
66952
66992
|
case "cli":
|
|
66953
|
-
return [[
|
|
66993
|
+
return [[path35.join(pkg, "src", "index.tsx"), path35.join(pkg, "dist", "index.js")]];
|
|
66954
66994
|
}
|
|
66955
66995
|
}, validNodeEntry = (entry, runtime, env) => {
|
|
66956
66996
|
try {
|
|
@@ -66977,7 +67017,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66977
67017
|
if (typeof command !== "string" || !Array.isArray(args) || typeof args[0] !== "string") {
|
|
66978
67018
|
return "invalid";
|
|
66979
67019
|
}
|
|
66980
|
-
const executable =
|
|
67020
|
+
const executable = path35.basename(command).toLowerCase();
|
|
66981
67021
|
const canonical = cursorMcpServerEntry("").args;
|
|
66982
67022
|
if (executable === "npx" || executable === "npx.exe" || executable === "npx.cmd") {
|
|
66983
67023
|
if (args.length !== canonical.length || args.some((a, i) => a !== canonical[i]))
|
|
@@ -66989,10 +67029,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
66989
67029
|
return {
|
|
66990
67030
|
kind: "node",
|
|
66991
67031
|
runtime: command,
|
|
66992
|
-
entry:
|
|
67032
|
+
entry: path35.isAbsolute(args[0]) ? args[0] : path35.resolve(path35.dirname(res.cursorMcp), args[0])
|
|
66993
67033
|
};
|
|
66994
67034
|
}, canonicalCursorHook, isCanonicalCursorHook = (command, res) => command === canonicalCursorHook || command === cursorHooksEntry(res.cursorPluginDir).command, registeredCursorHook = (res) => {
|
|
66995
|
-
const hooksFile =
|
|
67035
|
+
const hooksFile = path35.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
|
|
66996
67036
|
if (!existsSync14(hooksFile))
|
|
66997
67037
|
return "invalid";
|
|
66998
67038
|
const config = readJson(hooksFile);
|
|
@@ -67010,9 +67050,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67010
67050
|
if (!m)
|
|
67011
67051
|
return false;
|
|
67012
67052
|
const entry = m[1].trim();
|
|
67013
|
-
if (!
|
|
67053
|
+
if (!path35.isAbsolute(entry))
|
|
67014
67054
|
return false;
|
|
67015
|
-
if (
|
|
67055
|
+
if (path35.resolve(entry) !== path35.resolve(path35.join(res.cursorPluginDir, "dist", "cursor-session-start.js"))) {
|
|
67016
67056
|
return false;
|
|
67017
67057
|
}
|
|
67018
67058
|
return validNodeEntry(entry, "node", res.env);
|
|
@@ -67021,7 +67061,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67021
67061
|
const hosts = hostsFor(res.host);
|
|
67022
67062
|
const registered = hosts.includes("cursor") ? registeredCursorLauncher(res) : null;
|
|
67023
67063
|
const runtime = registered && registered !== "invalid" && registered.kind === "node" ? registered.runtime : "node";
|
|
67024
|
-
const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) =>
|
|
67064
|
+
const missing = hosts.includes("cursor") ? ["dist/mcp-server.js", "dist/cursor-session-start.js"].map((rel) => path35.join(res.cursorPluginDir, rel)).filter((p) => !validNodeEntry(p, runtime, res.env)).map((p) => `cursor: ${p}`) : [];
|
|
67025
67065
|
if (hosts.includes("cursor")) {
|
|
67026
67066
|
if (registered === "invalid") {
|
|
67027
67067
|
missing.push(`cursor: canonical workit MCP launcher in ${res.cursorMcp}`);
|
|
@@ -67030,9 +67070,9 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67030
67070
|
}
|
|
67031
67071
|
const hook = registeredCursorHook(res);
|
|
67032
67072
|
if (hook === "invalid") {
|
|
67033
|
-
missing.push(`cursor: canonical session-start hook in ${
|
|
67073
|
+
missing.push(`cursor: canonical session-start hook in ${path35.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")}`);
|
|
67034
67074
|
} else if (hook !== null && !isCanonicalCursorHook(hook, res) && !validLocalDistHook(hook, res)) {
|
|
67035
|
-
missing.push(`cursor: canonical session-start hook in ${
|
|
67075
|
+
missing.push(`cursor: canonical session-start hook in ${path35.join(res.cursorPluginDir, "hooks", "hooks-cursor.json")} (registered ${hook})`);
|
|
67036
67076
|
}
|
|
67037
67077
|
}
|
|
67038
67078
|
if (dev) {
|
|
@@ -67067,7 +67107,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67067
67107
|
status: "pass",
|
|
67068
67108
|
detail: "no Cursor plugin install — hook launcher not inspected"
|
|
67069
67109
|
};
|
|
67070
|
-
const launcher =
|
|
67110
|
+
const launcher = path35.join(res.cursorPluginDir, "hooks", "launch.mjs");
|
|
67071
67111
|
if (!existsSync14(launcher))
|
|
67072
67112
|
return {
|
|
67073
67113
|
id: "cursor_hook",
|
|
@@ -67075,7 +67115,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67075
67115
|
detail: `cursor hook launcher mode: missing — ${launcher} is absent (an install from before the pinned launcher)`,
|
|
67076
67116
|
fix: CURSOR_HOOK_FIX
|
|
67077
67117
|
};
|
|
67078
|
-
const hooksFile =
|
|
67118
|
+
const hooksFile = path35.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
|
|
67079
67119
|
const registered = readJson(hooksFile);
|
|
67080
67120
|
const sessionCommand = registered?.hooks?.sessionStart?.[0]?.command;
|
|
67081
67121
|
const offLauncher = [
|
|
@@ -67142,10 +67182,10 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67142
67182
|
return null;
|
|
67143
67183
|
}
|
|
67144
67184
|
}, silentCursorHooks = (res) => {
|
|
67145
|
-
const session = mtimeMs(
|
|
67185
|
+
const session = mtimeMs(path35.join(res.cursorHeartbeatDir, "cursor-session-last-start"));
|
|
67146
67186
|
if (session === null || Date.now() - session < SILENT_HOOK_GRACE_MS)
|
|
67147
67187
|
return null;
|
|
67148
|
-
const hook = mtimeMs(
|
|
67188
|
+
const hook = mtimeMs(path35.join(res.cursorHeartbeatDir, "cursor-hook-last-run"));
|
|
67149
67189
|
if (hook !== null && hook >= session)
|
|
67150
67190
|
return null;
|
|
67151
67191
|
return `Cursor started the Workit MCP server at ${new Date(session).toISOString()} but no Workit hook has run since${hook === null ? " (none ever)" : ""} — if the agent ran in that window, Cursor is not running the plugin hooks and Workit enforcement is off`;
|
|
@@ -67241,7 +67281,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67241
67281
|
}
|
|
67242
67282
|
return { id: "stale_pin", status: "pass", detail: "opencode pin resolves" };
|
|
67243
67283
|
}, pluginMcpSelectors = (res) => {
|
|
67244
|
-
const p =
|
|
67284
|
+
const p = path35.join(res.cursorPluginDir, "mcp.json");
|
|
67245
67285
|
if (!existsSync14(p))
|
|
67246
67286
|
return null;
|
|
67247
67287
|
const cfg = readJson(p);
|
|
@@ -67275,19 +67315,19 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67275
67315
|
return null;
|
|
67276
67316
|
}
|
|
67277
67317
|
}, installedPluginVersion = (res) => {
|
|
67278
|
-
const pkg = readJson(
|
|
67318
|
+
const pkg = readJson(path35.join(res.cursorPluginDir, "package.json"));
|
|
67279
67319
|
return typeof pkg?.version === "string" && pkg.version ? pkg.version : null;
|
|
67280
67320
|
}, installedOpenCodeCache = (res) => {
|
|
67281
67321
|
if (res.opencodePackageCacheDir !== null) {
|
|
67282
|
-
const pkg = readJson(
|
|
67322
|
+
const pkg = readJson(path35.join(res.opencodePackageCacheDir, "node_modules", "@brainervirus", "workit-opencode", "package.json"));
|
|
67283
67323
|
return typeof pkg?.version === "string" && pkg.version ? { version: pkg.version, dir: res.opencodePackageCacheDir } : null;
|
|
67284
67324
|
}
|
|
67285
67325
|
const found = openCodeInstalledPlugin(res.home, res.env);
|
|
67286
67326
|
if (!found)
|
|
67287
67327
|
return null;
|
|
67288
|
-
let dir =
|
|
67289
|
-
if (
|
|
67290
|
-
dir =
|
|
67328
|
+
let dir = path35.dirname(path35.dirname(path35.dirname(found.root)));
|
|
67329
|
+
if (path35.basename(dir) !== "workit-opencode@latest")
|
|
67330
|
+
dir = path35.dirname(dir);
|
|
67291
67331
|
return { version: found.version, dir };
|
|
67292
67332
|
}, checkOpenCodePackageCache = (res) => {
|
|
67293
67333
|
if (!existsSync14(res.opencodeConfig)) {
|
|
@@ -67391,7 +67431,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67391
67431
|
fix: "Re-run install-cursor-plugin.sh — it rewrites the workit MCP entry to the canonical @latest selector"
|
|
67392
67432
|
};
|
|
67393
67433
|
}
|
|
67394
|
-
const hooksFile =
|
|
67434
|
+
const hooksFile = path35.join(res.cursorPluginDir, "hooks", "hooks-cursor.json");
|
|
67395
67435
|
const hookCmd = readJson(hooksFile)?.hooks?.sessionStart?.[0]?.command ?? null;
|
|
67396
67436
|
const canonicalHook = canonicalCursorHook;
|
|
67397
67437
|
const staleHook = hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && !hookCmd.startsWith("node ") && hookCmd.includes("@brainervirus/workit-cursor@");
|
|
@@ -67413,7 +67453,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67413
67453
|
};
|
|
67414
67454
|
}
|
|
67415
67455
|
const installed = installedPluginVersion(res);
|
|
67416
|
-
const source = res.dev ? readJson(
|
|
67456
|
+
const source = res.dev ? readJson(path35.join(res.dev, "packages/workit-cursor/package.json"))?.version ?? null : readJson(path35.join(packageRoot(), "package.json"))?.version ?? null;
|
|
67417
67457
|
const localDist = mcpSelectors === null && hookCmd !== null && !isCanonicalCursorHook(hookCmd, res) && hookCmd.startsWith("node ");
|
|
67418
67458
|
if (localDist && installed !== null && source !== null && !semverAtLeast(installed, source)) {
|
|
67419
67459
|
return {
|
|
@@ -67425,7 +67465,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67425
67465
|
}
|
|
67426
67466
|
if (localDist && installed !== null && source !== null && res.dev) {
|
|
67427
67467
|
const entry = /^node\s+(.+)$/.exec((hookCmd ?? "").trim())?.[1]?.trim() ?? "";
|
|
67428
|
-
const sourceBundle = entry &&
|
|
67468
|
+
const sourceBundle = entry && path35.isAbsolute(entry) ? path35.join(res.dev, "packages", "workit-cursor", "dist", path35.basename(entry)) : "";
|
|
67429
67469
|
if (entry && sourceBundle) {
|
|
67430
67470
|
const installedHash = bundleHashOfFile(entry);
|
|
67431
67471
|
const sourceHash = bundleHashOfFile(sourceBundle);
|
|
@@ -67433,7 +67473,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67433
67473
|
return {
|
|
67434
67474
|
id: "stale_install",
|
|
67435
67475
|
status: "fail",
|
|
67436
|
-
detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${
|
|
67476
|
+
detail: `stale_install: installed workit-cursor ${installed} runs different bytes than the current runtime build (${path35.basename(entry)} hash mismatch)`,
|
|
67437
67477
|
fix: "Re-run install-cursor-plugin.sh — it refreshes the plugin directory with the current build"
|
|
67438
67478
|
};
|
|
67439
67479
|
}
|
|
@@ -67533,7 +67573,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67533
67573
|
}, checkMalformedConfig = (res) => {
|
|
67534
67574
|
const files = [];
|
|
67535
67575
|
for (const name of ["config.json", "youtrack.json", "vcs.json", "workspaces.json"]) {
|
|
67536
|
-
const p =
|
|
67576
|
+
const p = path35.join(res.configDir, name);
|
|
67537
67577
|
if (existsSync14(p))
|
|
67538
67578
|
files.push(p);
|
|
67539
67579
|
}
|
|
@@ -67731,11 +67771,11 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67731
67771
|
}
|
|
67732
67772
|
}, checkCredentialMetadata = (res) => {
|
|
67733
67773
|
const tokenPaths = [];
|
|
67734
|
-
const youtrackJson = readJson(
|
|
67774
|
+
const youtrackJson = readJson(path35.join(res.configDir, "youtrack.json"));
|
|
67735
67775
|
if (youtrackJson) {
|
|
67736
|
-
tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile :
|
|
67737
|
-
} else if (existsSync14(
|
|
67738
|
-
tokenPaths.push(
|
|
67776
|
+
tokenPaths.push(typeof youtrackJson.tokenFile === "string" ? youtrackJson.tokenFile : path35.join(res.configDir, "youtrack.token"));
|
|
67777
|
+
} else if (existsSync14(path35.join(res.configDir, "youtrack.token"))) {
|
|
67778
|
+
tokenPaths.push(path35.join(res.configDir, "youtrack.token"));
|
|
67739
67779
|
}
|
|
67740
67780
|
if (tokenPaths.length === 0) {
|
|
67741
67781
|
return {
|
|
@@ -67746,7 +67786,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67746
67786
|
}
|
|
67747
67787
|
const problems = [];
|
|
67748
67788
|
for (const raw of tokenPaths) {
|
|
67749
|
-
const p =
|
|
67789
|
+
const p = path35.isAbsolute(raw) ? raw : path35.resolve(res.configDir, raw);
|
|
67750
67790
|
if (!existsSync14(p)) {
|
|
67751
67791
|
problems.push(`${p} is missing`);
|
|
67752
67792
|
continue;
|
|
@@ -67862,7 +67902,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67862
67902
|
const remoteHost = githubHostFromRemote(probes.origin(res.cwd) ?? "");
|
|
67863
67903
|
if (!remoteHost)
|
|
67864
67904
|
return { id: "github_identity", status: "pass", detail: "no GitHub remote configured" };
|
|
67865
|
-
const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ??
|
|
67905
|
+
const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path35.join(res.configDir, "vcs.json"));
|
|
67866
67906
|
const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
|
|
67867
67907
|
if (workspace.error)
|
|
67868
67908
|
return {
|
|
@@ -67890,7 +67930,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67890
67930
|
const remoteHost = githubHostFromRemote(probes.origin(res.cwd) ?? "");
|
|
67891
67931
|
if (!remoteHost)
|
|
67892
67932
|
return { id: "gitlab_identity", status: "pass", detail: "no GitLab remote configured" };
|
|
67893
|
-
const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ??
|
|
67933
|
+
const vcsJson = readJson(res.env.WORKFLOW_VCS_CONFIG ?? path35.join(res.configDir, "vcs.json"));
|
|
67894
67934
|
const workspace = workspaceProviderForIdentity(res.cwd, res.configDir, res.env);
|
|
67895
67935
|
if (workspace.error)
|
|
67896
67936
|
return {
|
|
@@ -67916,8 +67956,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67916
67956
|
{ surface: "SSH", login: probes.sshLogin(remoteHost) }
|
|
67917
67957
|
]);
|
|
67918
67958
|
}, checkLogWritable = (res) => {
|
|
67919
|
-
const logsDir =
|
|
67920
|
-
const probe =
|
|
67959
|
+
const logsDir = path35.join(res.stateDir, "logs");
|
|
67960
|
+
const probe = path35.join(logsDir, "doctor-probe.tmp");
|
|
67921
67961
|
try {
|
|
67922
67962
|
mkdirSync6(logsDir, { recursive: true, mode: 448 });
|
|
67923
67963
|
writeFileSync7(probe, `{"probe":true}
|
|
@@ -67995,7 +68035,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
67995
68035
|
const counts = { skip: 0, late: 0 };
|
|
67996
68036
|
let text = "";
|
|
67997
68037
|
try {
|
|
67998
|
-
text = readFileSync14(
|
|
68038
|
+
text = readFileSync14(path35.join(stateDir, HOOK_SKIPS_FILE), "utf8");
|
|
67999
68039
|
} catch {
|
|
68000
68040
|
return counts;
|
|
68001
68041
|
}
|
|
@@ -68013,7 +68053,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68013
68053
|
}
|
|
68014
68054
|
return counts;
|
|
68015
68055
|
}, checkHookDeadline = (res) => {
|
|
68016
|
-
const file =
|
|
68056
|
+
const file = path35.join(res.hookStateDir, HOOK_SKIPS_FILE);
|
|
68017
68057
|
const { skip, late } = countHookSkips(res.hookStateDir, Date.now() - DAY_MS);
|
|
68018
68058
|
const lateText = late > 0 ? `; ${late} answered past it in full` : "";
|
|
68019
68059
|
if (skip > 0)
|
|
@@ -68036,8 +68076,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68036
68076
|
};
|
|
68037
68077
|
}, checkChecksConfig = (res) => {
|
|
68038
68078
|
const root = checkRoot(res.cwd);
|
|
68039
|
-
const current = existsSync14(
|
|
68040
|
-
const legacy = existsSync14(
|
|
68079
|
+
const current = existsSync14(path35.join(root, CHECKS_FILE));
|
|
68080
|
+
const legacy = existsSync14(path35.join(root, LEGACY_CHECKS_FILE));
|
|
68041
68081
|
if (!legacy)
|
|
68042
68082
|
return {
|
|
68043
68083
|
id: "checks_config",
|
|
@@ -68052,8 +68092,8 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68052
68092
|
};
|
|
68053
68093
|
}, fixChecksConfig = (options = {}) => {
|
|
68054
68094
|
const root = checkRoot(resolve(options).cwd);
|
|
68055
|
-
const from =
|
|
68056
|
-
const to =
|
|
68095
|
+
const from = path35.join(root, LEGACY_CHECKS_FILE);
|
|
68096
|
+
const to = path35.join(root, CHECKS_FILE);
|
|
68057
68097
|
if (!existsSync14(from))
|
|
68058
68098
|
return { action: "none", detail: `no ${LEGACY_CHECKS_FILE} at ${root}` };
|
|
68059
68099
|
if (existsSync14(to))
|
|
@@ -68101,7 +68141,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68101
68141
|
}, HOOK_ISSUED_MARKER = "workit-issued-sessions/3", hookRecordsIssued = (root) => {
|
|
68102
68142
|
let files;
|
|
68103
68143
|
try {
|
|
68104
|
-
files = readdirSync8(
|
|
68144
|
+
files = readdirSync8(path35.join(root, "dist")).filter((f) => f.endsWith(".js"));
|
|
68105
68145
|
} catch {
|
|
68106
68146
|
return null;
|
|
68107
68147
|
}
|
|
@@ -68109,7 +68149,7 @@ var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE", findDevFromCwd = (cwd) => {
|
|
|
68109
68149
|
return null;
|
|
68110
68150
|
return files.some((file) => {
|
|
68111
68151
|
try {
|
|
68112
|
-
return readFileSync14(
|
|
68152
|
+
return readFileSync14(path35.join(root, "dist", file), "utf8").includes(HOOK_ISSUED_MARKER);
|
|
68113
68153
|
} catch {
|
|
68114
68154
|
return false;
|
|
68115
68155
|
}
|
|
@@ -68325,7 +68365,7 @@ import {
|
|
|
68325
68365
|
} from "node:fs";
|
|
68326
68366
|
import { createRequire as createRequire2 } from "node:module";
|
|
68327
68367
|
import os10 from "node:os";
|
|
68328
|
-
import
|
|
68368
|
+
import path36 from "node:path";
|
|
68329
68369
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
68330
68370
|
function parseList(raw) {
|
|
68331
68371
|
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -68370,7 +68410,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68370
68410
|
const current = readConfigFromDir(state.configDir);
|
|
68371
68411
|
mutations.push({
|
|
68372
68412
|
type: "merge-json",
|
|
68373
|
-
path:
|
|
68413
|
+
path: path36.join(state.configDir, "config.json"),
|
|
68374
68414
|
value: {
|
|
68375
68415
|
locale: values.locale,
|
|
68376
68416
|
localeOptions: current.localeOptions,
|
|
@@ -68396,17 +68436,17 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68396
68436
|
if (blocked.length === 0) {
|
|
68397
68437
|
mutations.push({
|
|
68398
68438
|
type: "update-workspaces",
|
|
68399
|
-
path:
|
|
68439
|
+
path: path36.join(state.configDir, "workspaces.json"),
|
|
68400
68440
|
entries: values.workspaces,
|
|
68401
68441
|
expectedRevision: diskWorkspaceResult.revision
|
|
68402
68442
|
});
|
|
68403
68443
|
}
|
|
68404
68444
|
}
|
|
68405
68445
|
if (values.baseUrl.trim()) {
|
|
68406
|
-
const ytPath =
|
|
68446
|
+
const ytPath = path36.join(state.configDir, "youtrack.json");
|
|
68407
68447
|
const ytExisting = readConfigRecord(ytPath);
|
|
68408
68448
|
const ytConfigured = configuredTokenPath(ytExisting, "tokenFile");
|
|
68409
|
-
const tokenPath = resolveTokenPath(ytConfigured,
|
|
68449
|
+
const tokenPath = resolveTokenPath(ytConfigured, path36.join(state.configDir, "youtrack.token"), values.tokenPaths?.youtrack);
|
|
68410
68450
|
const draft = youtrackDraft(values, tokenPath);
|
|
68411
68451
|
if (ytConfigured !== null && tokenPath !== ytConfigured) {
|
|
68412
68452
|
delete draft.tokenFile;
|
|
@@ -68434,7 +68474,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68434
68474
|
});
|
|
68435
68475
|
}
|
|
68436
68476
|
if (values.vcsProvider !== "skip") {
|
|
68437
|
-
const vcsPath =
|
|
68477
|
+
const vcsPath = path36.join(state.configDir, "vcs.json");
|
|
68438
68478
|
mutations.push({
|
|
68439
68479
|
type: "merge-json",
|
|
68440
68480
|
path: vcsPath,
|
|
@@ -68463,7 +68503,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68463
68503
|
mutations.push({
|
|
68464
68504
|
type: "install-host",
|
|
68465
68505
|
platform: "cursor",
|
|
68466
|
-
path:
|
|
68506
|
+
path: path36.join(paths.home, ".cursor", "plugins", "local", ".workit-package-bootstrap"),
|
|
68467
68507
|
commands
|
|
68468
68508
|
});
|
|
68469
68509
|
}
|
|
@@ -68476,7 +68516,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68476
68516
|
mutations.push({
|
|
68477
68517
|
type: "install-host",
|
|
68478
68518
|
platform,
|
|
68479
|
-
path: platform === "claude-code" ? claudeInstallRecord(paths.home, env) : platform === "codex" ?
|
|
68519
|
+
path: platform === "claude-code" ? claudeInstallRecord(paths.home, env) : platform === "codex" ? path36.join(env.CODEX_HOME ?? path36.join(paths.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : path36.join(env.PI_CODING_AGENT_DIR ?? path36.join(paths.home, ".pi", "agent"), "settings.json"),
|
|
68480
68520
|
commands
|
|
68481
68521
|
});
|
|
68482
68522
|
}
|
|
@@ -68488,7 +68528,7 @@ function buildSetupPreview(values, opts = {}) {
|
|
|
68488
68528
|
projectRefused = target.refused;
|
|
68489
68529
|
if (target?.ok) {
|
|
68490
68530
|
const root = target.root;
|
|
68491
|
-
const gitignorePath =
|
|
68531
|
+
const gitignorePath = path36.join(root, ".gitignore");
|
|
68492
68532
|
const existing = existsSync15(gitignorePath) ? readFileSync15(gitignorePath, "utf8") : "";
|
|
68493
68533
|
const existingLines = new Set(existing.split(`
|
|
68494
68534
|
`).map((l) => l.trim()).filter(Boolean));
|
|
@@ -68526,7 +68566,7 @@ function deepMerge(base, patch) {
|
|
|
68526
68566
|
return out;
|
|
68527
68567
|
}
|
|
68528
68568
|
function applyMutation(m) {
|
|
68529
|
-
const dir =
|
|
68569
|
+
const dir = path36.dirname(m.path);
|
|
68530
68570
|
switch (m.type) {
|
|
68531
68571
|
case "create-file": {
|
|
68532
68572
|
mkdirSync7(dir, { recursive: true });
|
|
@@ -68675,7 +68715,7 @@ function applyMutation(m) {
|
|
|
68675
68715
|
detail: "already configured"
|
|
68676
68716
|
};
|
|
68677
68717
|
}
|
|
68678
|
-
mkdirSync7(
|
|
68718
|
+
mkdirSync7(path36.dirname(m.path), { recursive: true });
|
|
68679
68719
|
writeFileSync8(m.path, JSON.stringify(merged, null, 2) + `
|
|
68680
68720
|
`, "utf8");
|
|
68681
68721
|
return existing.kind === "record" ? { platform: "core", file: m.path, status: "Configured" } : { platform: "core", file: m.path, status: "Installed" };
|
|
@@ -68684,11 +68724,11 @@ function applyMutation(m) {
|
|
|
68684
68724
|
}
|
|
68685
68725
|
function adapterRoot(platform, res, preferInstalledAdapter = false) {
|
|
68686
68726
|
const candidates = [];
|
|
68687
|
-
const stagedCursor =
|
|
68727
|
+
const stagedCursor = path36.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap", "node_modules", "@brainervirus", "workit-cursor");
|
|
68688
68728
|
if (platform === "cursor" && preferInstalledAdapter)
|
|
68689
68729
|
candidates.push(stagedCursor);
|
|
68690
68730
|
if (res.dev) {
|
|
68691
|
-
candidates.push(
|
|
68731
|
+
candidates.push(path36.join(res.dev, "packages", `workit-${platform}`));
|
|
68692
68732
|
} else {
|
|
68693
68733
|
candidates.push(...nodeResolvedAdapters(platform));
|
|
68694
68734
|
if (platform === "cursor")
|
|
@@ -68698,10 +68738,10 @@ function adapterRoot(platform, res, preferInstalledAdapter = false) {
|
|
|
68698
68738
|
if (cached)
|
|
68699
68739
|
candidates.push(cached.root);
|
|
68700
68740
|
}
|
|
68701
|
-
let dir =
|
|
68741
|
+
let dir = path36.resolve(res.cwd);
|
|
68702
68742
|
while (true) {
|
|
68703
|
-
candidates.push(
|
|
68704
|
-
const parent =
|
|
68743
|
+
candidates.push(path36.join(dir, "packages", `workit-${platform}`));
|
|
68744
|
+
const parent = path36.dirname(dir);
|
|
68705
68745
|
if (parent === dir)
|
|
68706
68746
|
break;
|
|
68707
68747
|
dir = parent;
|
|
@@ -68723,7 +68763,7 @@ function applyOpenCode(root, res) {
|
|
|
68723
68763
|
detail: "workit-opencode package has no loadable plugin entry (src/plugin.ts or dist/plugin.js)"
|
|
68724
68764
|
};
|
|
68725
68765
|
}
|
|
68726
|
-
mkdirSync7(
|
|
68766
|
+
mkdirSync7(path36.dirname(res.opencodeConfig), { recursive: true });
|
|
68727
68767
|
const existing = readExisting(res.opencodeConfig);
|
|
68728
68768
|
if (existing.kind === "malformed") {
|
|
68729
68769
|
return {
|
|
@@ -68768,31 +68808,31 @@ function applyOpenCode(root, res) {
|
|
|
68768
68808
|
}
|
|
68769
68809
|
function copyPluginDir(src, dest) {
|
|
68770
68810
|
const realSrc = realpathSync7(src);
|
|
68771
|
-
const marker =
|
|
68811
|
+
const marker = path36.join(dest, ".workit-root");
|
|
68772
68812
|
const destIsLink = existsSync15(dest) && lstatSync6(dest).isSymbolicLink();
|
|
68773
68813
|
const synced = !destIsLink && readFileSafe(marker)?.trim() === realSrc && samePluginContent(realSrc, dest, dest);
|
|
68774
68814
|
if (synced)
|
|
68775
68815
|
return "Skipped";
|
|
68776
68816
|
const hadDir = existsSync15(dest);
|
|
68777
68817
|
const rules = preservedCursorRules(realSrc, dest);
|
|
68778
|
-
const parent =
|
|
68818
|
+
const parent = path36.dirname(dest);
|
|
68779
68819
|
mkdirSync7(parent, { recursive: true });
|
|
68780
|
-
const swap = mkdtempSync2(
|
|
68781
|
-
const stage =
|
|
68782
|
-
const backup =
|
|
68820
|
+
const swap = mkdtempSync2(path36.join(parent, `.${path36.basename(dest)}.swap-`));
|
|
68821
|
+
const stage = path36.join(swap, "stage");
|
|
68822
|
+
const backup = path36.join(swap, "backup");
|
|
68783
68823
|
try {
|
|
68784
68824
|
cpSync4(realSrc, stage, {
|
|
68785
68825
|
recursive: true,
|
|
68786
|
-
filter: (entry) => !
|
|
68826
|
+
filter: (entry) => !path36.relative(realSrc, entry).split(path36.sep).includes("node_modules")
|
|
68787
68827
|
});
|
|
68788
|
-
const stagedHooks =
|
|
68828
|
+
const stagedHooks = path36.join(stage, CURSOR_HOOKS_FILE);
|
|
68789
68829
|
if (existsSync15(stagedHooks))
|
|
68790
68830
|
writeFileSync8(stagedHooks, localizedCursorHooks(readFileSync15(stagedHooks), dest));
|
|
68791
68831
|
for (const [name, content] of rules) {
|
|
68792
|
-
mkdirSync7(
|
|
68793
|
-
writeFileSync8(
|
|
68832
|
+
mkdirSync7(path36.join(stage, "rules"), { recursive: true });
|
|
68833
|
+
writeFileSync8(path36.join(stage, "rules", name), content);
|
|
68794
68834
|
}
|
|
68795
|
-
writeFileSync8(
|
|
68835
|
+
writeFileSync8(path36.join(stage, ".workit-root"), realSrc + `
|
|
68796
68836
|
`, "utf8");
|
|
68797
68837
|
if (!samePluginContent(realSrc, stage, dest))
|
|
68798
68838
|
throw new Error("staged adapter content is incomplete");
|
|
@@ -68815,7 +68855,7 @@ function copyPluginDir(src, dest) {
|
|
|
68815
68855
|
return hadDir ? "Configured" : "Installed";
|
|
68816
68856
|
}
|
|
68817
68857
|
function applyCursorSettings(root, res) {
|
|
68818
|
-
mkdirSync7(
|
|
68858
|
+
mkdirSync7(path36.dirname(res.cursorSettings), { recursive: true });
|
|
68819
68859
|
const settingsExisting = readExisting(res.cursorSettings);
|
|
68820
68860
|
if (settingsExisting.kind === "malformed") {
|
|
68821
68861
|
return {
|
|
@@ -68843,7 +68883,7 @@ function applyCursorSettings(root, res) {
|
|
|
68843
68883
|
};
|
|
68844
68884
|
}
|
|
68845
68885
|
function applyCursorMcp(root, res) {
|
|
68846
|
-
mkdirSync7(
|
|
68886
|
+
mkdirSync7(path36.dirname(res.cursorMcp), { recursive: true });
|
|
68847
68887
|
const mcpExisting = readExisting(res.cursorMcp);
|
|
68848
68888
|
if (mcpExisting.kind === "malformed") {
|
|
68849
68889
|
return {
|
|
@@ -68949,7 +68989,7 @@ function applySetupPreview(preview, options = {}) {
|
|
|
68949
68989
|
let cursorCopyOk = false;
|
|
68950
68990
|
for (const mutation of preview.mutations) {
|
|
68951
68991
|
if (mutation.type === "install-host") {
|
|
68952
|
-
const expectedPath = mutation.platform === "cursor" ?
|
|
68992
|
+
const expectedPath = mutation.platform === "cursor" ? path36.join(res.home, ".cursor", "plugins", "local", ".workit-package-bootstrap") : mutation.platform === "codex" ? path36.join(res.env.CODEX_HOME ?? path36.join(res.home, ".codex"), "plugins", "cache", "workflow-toolkit", "workit") : mutation.platform === "pi" ? path36.join(res.env.PI_CODING_AGENT_DIR ?? path36.join(res.home, ".pi", "agent"), "settings.json") : mutation.platform === "claude-code" ? claudeInstallRecord(res.home, res.env) : "";
|
|
68953
68993
|
if (mutation.path !== expectedPath) {
|
|
68954
68994
|
entries.push({
|
|
68955
68995
|
platform: mutation.platform,
|
|
@@ -69061,7 +69101,7 @@ function applySetupPreview(preview, options = {}) {
|
|
|
69061
69101
|
if (preview.projectRefused) {
|
|
69062
69102
|
entries.push({
|
|
69063
69103
|
platform: "core",
|
|
69064
|
-
file:
|
|
69104
|
+
file: path36.resolve(res.cwd),
|
|
69065
69105
|
status: "Skipped",
|
|
69066
69106
|
detail: preview.projectRefused
|
|
69067
69107
|
});
|
|
@@ -69147,7 +69187,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69147
69187
|
} catch {
|
|
69148
69188
|
return null;
|
|
69149
69189
|
}
|
|
69150
|
-
}, claudeInstallRecord = (home, env) =>
|
|
69190
|
+
}, claudeInstallRecord = (home, env) => path36.join(claudeConfigDir(home, env), "plugins", "installed_plugins.json"), resolveSetupPaths = (options, resolvedConfigDir) => {
|
|
69151
69191
|
const env = options.env ?? process.env;
|
|
69152
69192
|
const home = options.home ?? env.HOME ?? os10.homedir();
|
|
69153
69193
|
return {
|
|
@@ -69155,10 +69195,10 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69155
69195
|
configDir: resolvedConfigDir,
|
|
69156
69196
|
cwd: options.cwd ?? process.cwd(),
|
|
69157
69197
|
env,
|
|
69158
|
-
opencodeConfig: options.opencodeConfig ??
|
|
69159
|
-
cursorSettings: options.cursorSettings ??
|
|
69160
|
-
cursorMcp: options.cursorMcp ??
|
|
69161
|
-
cursorPluginDir: options.cursorPluginDir ??
|
|
69198
|
+
opencodeConfig: options.opencodeConfig ?? path36.join(home, ".config", "opencode", "opencode.json"),
|
|
69199
|
+
cursorSettings: options.cursorSettings ?? path36.join(home, ".cursor", "settings.json"),
|
|
69200
|
+
cursorMcp: options.cursorMcp ?? path36.join(home, ".cursor", "mcp.json"),
|
|
69201
|
+
cursorPluginDir: options.cursorPluginDir ?? path36.join(home, ".cursor", "plugins", "local", "workit")
|
|
69162
69202
|
};
|
|
69163
69203
|
}, isRecord5 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readExisting = (p) => {
|
|
69164
69204
|
let raw;
|
|
@@ -69195,15 +69235,15 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69195
69235
|
}
|
|
69196
69236
|
}, isAdapter = (root, platform) => {
|
|
69197
69237
|
try {
|
|
69198
|
-
const pkg = JSON.parse(readFileSync15(
|
|
69238
|
+
const pkg = JSON.parse(readFileSync15(path36.join(root, "package.json"), "utf8"));
|
|
69199
69239
|
return pkg.name === `@brainervirus/workit-${platform}`;
|
|
69200
69240
|
} catch {
|
|
69201
69241
|
return false;
|
|
69202
69242
|
}
|
|
69203
69243
|
}, nodeResolvedAdapters = (platform) => {
|
|
69204
69244
|
const name = `@brainervirus/workit-${platform}`;
|
|
69205
|
-
const require2 = createRequire2(
|
|
69206
|
-
return (require2.resolve.paths(name) ?? []).map((dir) =>
|
|
69245
|
+
const require2 = createRequire2(path36.join(packageRoot(), "package.json"));
|
|
69246
|
+
return (require2.resolve.paths(name) ?? []).map((dir) => path36.join(dir, name));
|
|
69207
69247
|
}, realRoot = (root) => {
|
|
69208
69248
|
try {
|
|
69209
69249
|
return realpathSync7(root);
|
|
@@ -69219,7 +69259,7 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69219
69259
|
if (!isDevOpenCodeAdapterRoot(root, opts.dev))
|
|
69220
69260
|
return OPENCODE_NPM_PIN;
|
|
69221
69261
|
for (const rel of ["src/plugin.ts", "dist/plugin.js"]) {
|
|
69222
|
-
const entry =
|
|
69262
|
+
const entry = path36.join(root, rel);
|
|
69223
69263
|
if (existsSync15(entry))
|
|
69224
69264
|
return `file://${entry}`;
|
|
69225
69265
|
}
|
|
@@ -69237,9 +69277,9 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69237
69277
|
for (const entry of readdirSync9(src, { withFileTypes: true })) {
|
|
69238
69278
|
if (entry.name === "node_modules")
|
|
69239
69279
|
continue;
|
|
69240
|
-
const source =
|
|
69241
|
-
const installed =
|
|
69242
|
-
const rel =
|
|
69280
|
+
const source = path36.join(src, entry.name);
|
|
69281
|
+
const installed = path36.join(dest, entry.name);
|
|
69282
|
+
const rel = path36.join(relative, entry.name);
|
|
69243
69283
|
if (entry.isDirectory()) {
|
|
69244
69284
|
if (!statSync6(installed).isDirectory() || !samePluginContent(source, installed, pluginDir, rel))
|
|
69245
69285
|
return false;
|
|
@@ -69250,9 +69290,9 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69250
69290
|
}
|
|
69251
69291
|
}
|
|
69252
69292
|
for (const entry of readdirSync9(dest, { withFileTypes: true })) {
|
|
69253
|
-
if (existsSync15(
|
|
69293
|
+
if (existsSync15(path36.join(src, entry.name)))
|
|
69254
69294
|
continue;
|
|
69255
|
-
const rel =
|
|
69295
|
+
const rel = path36.join(relative, entry.name);
|
|
69256
69296
|
if (rel === ".workit-root")
|
|
69257
69297
|
continue;
|
|
69258
69298
|
if (relative === "rules" && entry.isFile() && entry.name.endsWith(".mdc"))
|
|
@@ -69265,32 +69305,32 @@ var TOKEN_PLACEHOLDER3 = "YOUR_TOKEN_HERE", YT_OVERRIDES, VCS_OVERRIDES, SETUP_O
|
|
|
69265
69305
|
}
|
|
69266
69306
|
}, preservedCursorRules = (src, dest) => {
|
|
69267
69307
|
const preserved = new Map;
|
|
69268
|
-
const sourceRules =
|
|
69269
|
-
const installedRules =
|
|
69308
|
+
const sourceRules = path36.join(src, "rules");
|
|
69309
|
+
const installedRules = path36.join(dest, "rules");
|
|
69270
69310
|
try {
|
|
69271
69311
|
for (const entry of readdirSync9(installedRules, { withFileTypes: true })) {
|
|
69272
69312
|
if (!entry.isFile() || !entry.name.endsWith(".mdc"))
|
|
69273
69313
|
continue;
|
|
69274
|
-
if (existsSync15(
|
|
69314
|
+
if (existsSync15(path36.join(sourceRules, entry.name)))
|
|
69275
69315
|
continue;
|
|
69276
|
-
preserved.set(entry.name, readFileSync15(
|
|
69316
|
+
preserved.set(entry.name, readFileSync15(path36.join(installedRules, entry.name)));
|
|
69277
69317
|
}
|
|
69278
69318
|
} catch {}
|
|
69279
69319
|
return preserved;
|
|
69280
69320
|
}, removeLegacyCursorDir = (res) => {
|
|
69281
|
-
const legacy =
|
|
69321
|
+
const legacy = path36.join(res.home, ".cursor", "plugins", "local", "workflow-toolkit");
|
|
69282
69322
|
if (legacy === res.cursorPluginDir || !existsSync15(legacy))
|
|
69283
69323
|
return;
|
|
69284
|
-
const legacyRules =
|
|
69324
|
+
const legacyRules = path36.join(legacy, "rules");
|
|
69285
69325
|
if (existsSync15(legacyRules)) {
|
|
69286
69326
|
try {
|
|
69287
|
-
mkdirSync7(
|
|
69327
|
+
mkdirSync7(path36.join(res.cursorPluginDir, "rules"), { recursive: true });
|
|
69288
69328
|
for (const entry of readdirSync9(legacyRules, { withFileTypes: true })) {
|
|
69289
69329
|
if (!entry.isFile() || !entry.name.endsWith(".mdc"))
|
|
69290
69330
|
continue;
|
|
69291
|
-
const target =
|
|
69331
|
+
const target = path36.join(res.cursorPluginDir, "rules", entry.name);
|
|
69292
69332
|
if (!existsSync15(target))
|
|
69293
|
-
copyFileSync4(
|
|
69333
|
+
copyFileSync4(path36.join(legacyRules, entry.name), target);
|
|
69294
69334
|
}
|
|
69295
69335
|
} catch {}
|
|
69296
69336
|
}
|
|
@@ -69324,16 +69364,16 @@ var init_setup = __esm(() => {
|
|
|
69324
69364
|
{ envKey: "WORKFLOW_GITHUB_HOST", affects: "vcs.json github.host" }
|
|
69325
69365
|
];
|
|
69326
69366
|
SETUP_OVERRIDES = [...YT_OVERRIDES, ...VCS_OVERRIDES];
|
|
69327
|
-
CURSOR_HOOKS_FILE =
|
|
69367
|
+
CURSOR_HOOKS_FILE = path36.join("hooks", "hooks-cursor.json");
|
|
69328
69368
|
});
|
|
69329
69369
|
|
|
69330
69370
|
// packages/workit-core/src/core/workspace-branch-policy.ts
|
|
69331
69371
|
import { mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as renameSync6, rmSync as rmSync5, writeFileSync as writeFileSync9 } from "node:fs";
|
|
69332
|
-
import
|
|
69372
|
+
import path37 from "node:path";
|
|
69333
69373
|
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
69334
69374
|
function applyWorkspaceBranchPolicy(opts) {
|
|
69335
69375
|
const { workspace_root, env = process.env } = opts;
|
|
69336
|
-
const dir =
|
|
69376
|
+
const dir = path37.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
69337
69377
|
const {
|
|
69338
69378
|
status,
|
|
69339
69379
|
path: wsPath,
|
|
@@ -69345,7 +69385,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
69345
69385
|
if (status === "malformed" || status === "invalid")
|
|
69346
69386
|
return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
|
|
69347
69387
|
const detection = detectBranchPolicy(workspace_root);
|
|
69348
|
-
const name = String(env.WORKFLOW_BP_NAME ??
|
|
69388
|
+
const name = String(env.WORKFLOW_BP_NAME ?? path37.basename(workspace_root));
|
|
69349
69389
|
const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
|
|
69350
69390
|
const policy = {
|
|
69351
69391
|
preset: detection.preset,
|
|
@@ -69394,7 +69434,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
69394
69434
|
ok: false,
|
|
69395
69435
|
error: `workspaces.json changed while applying the branch policy: ${wsPath}`
|
|
69396
69436
|
};
|
|
69397
|
-
mkdirSync8(
|
|
69437
|
+
mkdirSync8(path37.dirname(wsPath), { recursive: true });
|
|
69398
69438
|
const tmp = `${wsPath}.${process.pid}.tmp`;
|
|
69399
69439
|
try {
|
|
69400
69440
|
writeFileSync9(tmp, JSON.stringify({ ...document2, workspaces: next }, null, 2) + `
|
|
@@ -69679,7 +69719,7 @@ var init_logic = __esm(() => {
|
|
|
69679
69719
|
|
|
69680
69720
|
// packages/workit-cli/src/wizard-state.ts
|
|
69681
69721
|
import { existsSync as existsSync16, statSync as statSync7 } from "node:fs";
|
|
69682
|
-
import
|
|
69722
|
+
import path38 from "node:path";
|
|
69683
69723
|
import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
|
|
69684
69724
|
function resolveBasePath(values, env = process.env) {
|
|
69685
69725
|
return env.WORKFLOW_WORKSPACE_ROOT?.trim() || values.basePath.trim();
|
|
@@ -70206,8 +70246,8 @@ var NEXT, PREV, skipsCustomBranch = (screen, preset) => (screen === "branchAllow
|
|
|
70206
70246
|
const p = value.trim();
|
|
70207
70247
|
if (!p)
|
|
70208
70248
|
return "workspace root path is required";
|
|
70209
|
-
return !
|
|
70210
|
-
}, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync16(
|
|
70249
|
+
return !path38.isAbsolute(p) || !isDirectory(p) ? `invalid workspace root "${p}" — enter an existing absolute directory` : null;
|
|
70250
|
+
}, skipsBranchPolicy = (screen, basePath) => (screen === "branchPolicy" || screen === "branchPolicyDevelop") && !existsSync16(path38.join(basePath, ".git")), decodeBranchPreset = (value, fallback) => value === "gitflow" || value === "github-flow" || value === "trunk-based" || value === "custom" ? value : fallback, decodeVcsProvider = (value, fallback) => value === "gitlab" || value === "github" || value === "skip" ? value : fallback, decodeIssueTracker = (value, fallback) => value === "youtrack" || value === "github" || value === "gitlab" || value === "none" ? value : fallback, GITHUB_ISSUES, withGithubIssues = (draft, tracker) => tracker === "github" ? { ...draft, issues: { ...GITHUB_ISSUES } } : draft;
|
|
70211
70251
|
var init_wizard_state = __esm(() => {
|
|
70212
70252
|
init_config();
|
|
70213
70253
|
init_workspaces();
|
|
@@ -70268,7 +70308,7 @@ var init_wizard_state = __esm(() => {
|
|
|
70268
70308
|
// packages/workit-cli/src/admin/uninstall.ts
|
|
70269
70309
|
import { existsSync as existsSync17, readFileSync as readFileSync17, realpathSync as realpathSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "node:fs";
|
|
70270
70310
|
import os11 from "node:os";
|
|
70271
|
-
import
|
|
70311
|
+
import path39 from "node:path";
|
|
70272
70312
|
function cleanCursorSettings(settings, pluginDir) {
|
|
70273
70313
|
const next = { ...settings };
|
|
70274
70314
|
let changed = false;
|
|
@@ -70443,8 +70483,8 @@ function applyUninstall(plan, paths = {}) {
|
|
|
70443
70483
|
status = outcome.status;
|
|
70444
70484
|
detail = outcome.detail;
|
|
70445
70485
|
} else if (action.kind === "remove-dir") {
|
|
70446
|
-
const resolved =
|
|
70447
|
-
const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved ===
|
|
70486
|
+
const resolved = path39.resolve(action.path);
|
|
70487
|
+
const allowed = canonicalRemoveDirAllowed(resolved, res) || resolved === path39.resolve(res.codexPluginDir) && path39.basename(resolved) === "workit" && path39.basename(path39.dirname(resolved)) === "plugins";
|
|
70448
70488
|
if (!allowed) {
|
|
70449
70489
|
status = "failed";
|
|
70450
70490
|
detail = `refusing to remove non-canonical plugin directory: ${resolved}`;
|
|
@@ -70479,12 +70519,12 @@ function applyUninstall(plan, paths = {}) {
|
|
|
70479
70519
|
var resolveUninstallPaths = (options = {}) => {
|
|
70480
70520
|
const home = options.home ?? options.env?.HOME ?? os11.homedir();
|
|
70481
70521
|
return {
|
|
70482
|
-
opencodeConfig: options.opencodeConfig ??
|
|
70483
|
-
cursorSettings: options.cursorSettings ??
|
|
70484
|
-
cursorMcp: options.cursorMcp ??
|
|
70485
|
-
cursorPluginDir: options.cursorPluginDir ??
|
|
70486
|
-
codexPluginDir:
|
|
70487
|
-
piConfig:
|
|
70522
|
+
opencodeConfig: options.opencodeConfig ?? path39.join(home, ".config", "opencode", "opencode.json"),
|
|
70523
|
+
cursorSettings: options.cursorSettings ?? path39.join(home, ".cursor", "settings.json"),
|
|
70524
|
+
cursorMcp: options.cursorMcp ?? path39.join(home, ".cursor", "mcp.json"),
|
|
70525
|
+
cursorPluginDir: options.cursorPluginDir ?? path39.join(home, ".cursor", "plugins", "local", "workit"),
|
|
70526
|
+
codexPluginDir: path39.join(home, ".codex", "plugins", "workit"),
|
|
70527
|
+
piConfig: path39.join(home, ".pi", "config.json")
|
|
70488
70528
|
};
|
|
70489
70529
|
}, isRecord6 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), readJsonRecord = (file) => {
|
|
70490
70530
|
let raw;
|
|
@@ -70502,8 +70542,8 @@ var resolveUninstallPaths = (options = {}) => {
|
|
|
70502
70542
|
return { kind: "malformed", error: `${file} is not valid JSON` };
|
|
70503
70543
|
}
|
|
70504
70544
|
}, stripTrailingSep = (p) => {
|
|
70505
|
-
const j =
|
|
70506
|
-
return
|
|
70545
|
+
const j = path39.join(p);
|
|
70546
|
+
return path39.dirname(j) === j ? j : j.replace(/[\\/]+$/, "");
|
|
70507
70547
|
}, CURSOR_LEGACY_IDENTITIES, jsonCleanerFor = (target, res) => {
|
|
70508
70548
|
if (target === res.opencodeConfig)
|
|
70509
70549
|
return cleanOpenCodeConfig;
|
|
@@ -70515,8 +70555,8 @@ var resolveUninstallPaths = (options = {}) => {
|
|
|
70515
70555
|
return cleanPiConfig;
|
|
70516
70556
|
return null;
|
|
70517
70557
|
}, canonicalRemoveDirAllowed = (actionPath, res) => {
|
|
70518
|
-
const expected =
|
|
70519
|
-
if (!(actionPath === expected &&
|
|
70558
|
+
const expected = path39.resolve(res.cursorPluginDir);
|
|
70559
|
+
if (!(actionPath === expected && path39.basename(expected) === "workit" && path39.basename(path39.dirname(expected)) === "local" && path39.basename(path39.dirname(path39.dirname(expected))) === "plugins")) {
|
|
70520
70560
|
return false;
|
|
70521
70561
|
}
|
|
70522
70562
|
try {
|
|
@@ -70568,7 +70608,7 @@ var resolveUninstallPaths = (options = {}) => {
|
|
|
70568
70608
|
};
|
|
70569
70609
|
const home = paths.home ?? paths.env?.HOME ?? os11.homedir();
|
|
70570
70610
|
const env = paths.env ?? process.env;
|
|
70571
|
-
const recorded = claudeWorkitInstalls(home, env, action.cwd).some((install) => install.id === id && install.scope === scope && (install.projectPath === null ? action.cwd === null :
|
|
70611
|
+
const recorded = claudeWorkitInstalls(home, env, action.cwd).some((install) => install.id === id && install.scope === scope && (install.projectPath === null ? action.cwd === null : path39.resolve(install.projectPath) === path39.resolve(action.cwd ?? "")));
|
|
70572
70612
|
if (!recorded)
|
|
70573
70613
|
return { status: "skipped", detail: `${id} (${scope} scope) is no longer installed` };
|
|
70574
70614
|
const executable = findHostExecutable("claude", { home, env });
|
|
@@ -73124,7 +73164,7 @@ import {
|
|
|
73124
73164
|
cpSync as cpSync5,
|
|
73125
73165
|
lstatSync as lstatSync7
|
|
73126
73166
|
} from "node:fs";
|
|
73127
|
-
import
|
|
73167
|
+
import path40 from "node:path";
|
|
73128
73168
|
import os13 from "node:os";
|
|
73129
73169
|
import { createHash as createHash15 } from "node:crypto";
|
|
73130
73170
|
function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
@@ -73148,9 +73188,9 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
|
73148
73188
|
for (const file of [
|
|
73149
73189
|
paths.opencodeConfig,
|
|
73150
73190
|
paths.opencodeConfig + "c",
|
|
73151
|
-
|
|
73152
|
-
|
|
73153
|
-
|
|
73191
|
+
path40.join(home, ".cursor/settings.json"),
|
|
73192
|
+
path40.join(home, ".cursor/mcp.json"),
|
|
73193
|
+
path40.join(home, ".cursor/plugins/local/workit/package.json"),
|
|
73154
73194
|
paths.codexConfig,
|
|
73155
73195
|
paths.piSettings
|
|
73156
73196
|
])
|
|
@@ -73165,16 +73205,16 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
|
73165
73205
|
});
|
|
73166
73206
|
const installedSources = sources(paths, run, hosts);
|
|
73167
73207
|
if (installedSources.some((source) => source.host === "opencode")) {
|
|
73168
|
-
const scratch = mkdtempSync3(
|
|
73208
|
+
const scratch = mkdtempSync3(path40.join(os13.tmpdir(), "workit-upgrade-opencode-"));
|
|
73169
73209
|
let probe;
|
|
73170
73210
|
try {
|
|
73171
73211
|
probe = runner({
|
|
73172
73212
|
...deps,
|
|
73173
73213
|
env: {
|
|
73174
73214
|
...deps.env,
|
|
73175
|
-
XDG_DATA_HOME:
|
|
73176
|
-
XDG_STATE_HOME:
|
|
73177
|
-
XDG_CACHE_HOME:
|
|
73215
|
+
XDG_DATA_HOME: path40.join(scratch, "data"),
|
|
73216
|
+
XDG_STATE_HOME: path40.join(scratch, "state"),
|
|
73217
|
+
XDG_CACHE_HOME: path40.join(scratch, "cache")
|
|
73178
73218
|
}
|
|
73179
73219
|
})("opencode", ["--version"]);
|
|
73180
73220
|
} finally {
|
|
@@ -73220,7 +73260,7 @@ function previewUpgrade(hosts = HOSTS2, deps = {}) {
|
|
|
73220
73260
|
env: deps.env,
|
|
73221
73261
|
cwd: home,
|
|
73222
73262
|
packageVersion: latest.stdout.trim(),
|
|
73223
|
-
targetDir:
|
|
73263
|
+
targetDir: path40.join(home, ".cursor/plugins/local/workit")
|
|
73224
73264
|
});
|
|
73225
73265
|
plan.entries.push({
|
|
73226
73266
|
host: source.host,
|
|
@@ -73250,11 +73290,11 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73250
73290
|
ok: false,
|
|
73251
73291
|
error: "Stop the selected running hosts before upgrading their loaded plugins"
|
|
73252
73292
|
};
|
|
73253
|
-
const backup =
|
|
73293
|
+
const backup = path40.join(home, ".local/state/workit/upgrades", new Date().toISOString().replaceAll(":", "-"));
|
|
73254
73294
|
mkdirSync9(backup, { recursive: true, mode: 448 });
|
|
73255
73295
|
for (const file of Object.keys(plan.configDigests))
|
|
73256
73296
|
if (existsSync18(file)) {
|
|
73257
|
-
const target =
|
|
73297
|
+
const target = path40.join(backup, createHash15("sha256").update(file).digest("hex").slice(0, 12) + "-" + path40.basename(file));
|
|
73258
73298
|
copyFileSync5(file, target);
|
|
73259
73299
|
chmodSync2(target, 384);
|
|
73260
73300
|
}
|
|
@@ -73271,9 +73311,9 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73271
73311
|
`, 384);
|
|
73272
73312
|
}
|
|
73273
73313
|
const run = runner(deps);
|
|
73274
|
-
const cursorRoot =
|
|
73314
|
+
const cursorRoot = path40.join(home, ".cursor/plugins/local/workit");
|
|
73275
73315
|
if (plan.entries.some((entry) => entry.host === "cursor") && existsSync18(cursorRoot))
|
|
73276
|
-
cpSync5(cursorRoot,
|
|
73316
|
+
cpSync5(cursorRoot, path40.join(backup, "cursor-package"), { recursive: true });
|
|
73277
73317
|
for (const entry of plan.entries) {
|
|
73278
73318
|
if (entry.host === "opencode")
|
|
73279
73319
|
return {
|
|
@@ -73293,7 +73333,7 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73293
73333
|
{
|
|
73294
73334
|
type: "install-host",
|
|
73295
73335
|
platform: "cursor",
|
|
73296
|
-
path:
|
|
73336
|
+
path: path40.join(home, ".cursor/plugins/local/.workit-package-bootstrap"),
|
|
73297
73337
|
commands: entry.commands.map((command) => ({
|
|
73298
73338
|
...command,
|
|
73299
73339
|
purpose: command.purpose ?? "Upgrade Cursor"
|
|
@@ -73302,7 +73342,7 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73302
73342
|
{
|
|
73303
73343
|
type: "install-adapter",
|
|
73304
73344
|
platform: "cursor",
|
|
73305
|
-
path:
|
|
73345
|
+
path: path40.join(home, ".cursor/plugins/local/workit")
|
|
73306
73346
|
}
|
|
73307
73347
|
]
|
|
73308
73348
|
};
|
|
@@ -73316,7 +73356,7 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73316
73356
|
return { exitCode: outcome.status ?? 1, stdout: outcome.stdout, stderr: "" };
|
|
73317
73357
|
}
|
|
73318
73358
|
});
|
|
73319
|
-
const pkg = object2(
|
|
73359
|
+
const pkg = object2(path40.join(home, ".cursor/plugins/local/workit/package.json"));
|
|
73320
73360
|
if (!result.ok || pkg?.version !== entry.latest)
|
|
73321
73361
|
return {
|
|
73322
73362
|
ok: false,
|
|
@@ -73350,15 +73390,15 @@ function applyUpgrade(plan, deps = {}) {
|
|
|
73350
73390
|
const currentRoot = run("npm", ["root", "--global"]);
|
|
73351
73391
|
if (currentRoot.status !== 0 || currentRoot.stdout.trim() !== plan.cli.root)
|
|
73352
73392
|
return { ok: false, backup, error: "Global npm location changed; preview again" };
|
|
73353
|
-
const cliBackup =
|
|
73354
|
-
cpSync5(
|
|
73393
|
+
const cliBackup = path40.join(backup, "cli-package");
|
|
73394
|
+
cpSync5(path40.join(plan.cli.root, "@brainervirus/workit-cli"), cliBackup, { recursive: true });
|
|
73355
73395
|
if (run("npm", ["install", "--global", `@brainervirus/workit-cli@${plan.cli.latest}`]).status !== 0)
|
|
73356
73396
|
return {
|
|
73357
73397
|
ok: false,
|
|
73358
73398
|
backup,
|
|
73359
|
-
error: `CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${
|
|
73399
|
+
error: `CLI update failed; preserved package at ${cliBackup}; use npm to repair or run node ${path40.join(cliBackup, "dist/index.js")}`
|
|
73360
73400
|
};
|
|
73361
|
-
const installed = object2(
|
|
73401
|
+
const installed = object2(path40.join(plan.cli.root, "@brainervirus/workit-cli/package.json"));
|
|
73362
73402
|
if (installed?.name !== "@brainervirus/workit-cli" || installed.version !== plan.cli.latest)
|
|
73363
73403
|
return {
|
|
73364
73404
|
ok: false,
|
|
@@ -73383,12 +73423,12 @@ async function runUpgradeCommand(argv, deps = {}) {
|
|
|
73383
73423
|
if (flags.has("--cli")) {
|
|
73384
73424
|
const run = runner(deps);
|
|
73385
73425
|
const root = run("npm", ["root", "--global"]);
|
|
73386
|
-
if (root.status !== 0 || !
|
|
73426
|
+
if (root.status !== 0 || !path40.isAbsolute(root.stdout.trim())) {
|
|
73387
73427
|
plan.blocked.push("Global npm location could not be verified");
|
|
73388
73428
|
} else {
|
|
73389
|
-
const packageFile =
|
|
73429
|
+
const packageFile = path40.join(root.stdout.trim(), "@brainervirus/workit-cli/package.json");
|
|
73390
73430
|
const pkg = object2(packageFile);
|
|
73391
|
-
if (pkg?.name !== "@brainervirus/workit-cli" || lstatSync7(
|
|
73431
|
+
if (pkg?.name !== "@brainervirus/workit-cli" || lstatSync7(path40.dirname(packageFile)).isSymbolicLink()) {
|
|
73392
73432
|
plan.skipped.push({
|
|
73393
73433
|
host: "cli",
|
|
73394
73434
|
reason: "No managed global CLI install (local links preserved); use npx @brainervirus/workit-cli@latest"
|
|
@@ -73479,23 +73519,23 @@ var HOSTS2, upgradePaths = (deps) => {
|
|
|
73479
73519
|
...process.env,
|
|
73480
73520
|
...deps.home || deps.env?.HOME ? {
|
|
73481
73521
|
HOME: home,
|
|
73482
|
-
CODEX_HOME:
|
|
73483
|
-
PI_CODING_AGENT_DIR:
|
|
73484
|
-
XDG_CONFIG_HOME:
|
|
73522
|
+
CODEX_HOME: path40.join(home, ".codex"),
|
|
73523
|
+
PI_CODING_AGENT_DIR: path40.join(home, ".pi/agent"),
|
|
73524
|
+
XDG_CONFIG_HOME: path40.join(home, ".config"),
|
|
73485
73525
|
WORKFLOW_TOOLKIT_CONFIG: undefined,
|
|
73486
73526
|
WORKFLOW_TOOLKIT_CONFIG_DIR: undefined
|
|
73487
73527
|
} : {},
|
|
73488
73528
|
...deps.env,
|
|
73489
73529
|
HOME: home
|
|
73490
73530
|
};
|
|
73491
|
-
const xdg = env.XDG_CONFIG_HOME ||
|
|
73531
|
+
const xdg = env.XDG_CONFIG_HOME || path40.join(home, ".config");
|
|
73492
73532
|
return {
|
|
73493
73533
|
home,
|
|
73494
73534
|
env,
|
|
73495
|
-
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
73496
|
-
opencodeConfig:
|
|
73497
|
-
piSettings:
|
|
73498
|
-
codexConfig:
|
|
73535
|
+
configDir: env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path40.join(xdg, "workit"),
|
|
73536
|
+
opencodeConfig: path40.join(xdg, "opencode/opencode.json"),
|
|
73537
|
+
piSettings: path40.join(env.PI_CODING_AGENT_DIR ?? path40.join(home, ".pi/agent"), "settings.json"),
|
|
73538
|
+
codexConfig: path40.join(env.CODEX_HOME ?? path40.join(home, ".codex"), "config.toml")
|
|
73499
73539
|
};
|
|
73500
73540
|
}, object2 = (file) => {
|
|
73501
73541
|
if (!existsSync18(file))
|
|
@@ -73535,9 +73575,9 @@ var HOSTS2, upgradePaths = (deps) => {
|
|
|
73535
73575
|
for (const pin of plugins)
|
|
73536
73576
|
if (typeof pin === "string" && isWorkitPlugin(pin))
|
|
73537
73577
|
result.push(classify("opencode", pin));
|
|
73538
|
-
const cursor = hosts.includes("cursor") ? object2(
|
|
73578
|
+
const cursor = hosts.includes("cursor") ? object2(path40.join(home, ".cursor/plugins/local/workit/package.json")) : null;
|
|
73539
73579
|
if (cursor?.name === "@brainervirus/workit-cursor") {
|
|
73540
|
-
const mcp = object2(
|
|
73580
|
+
const mcp = object2(path40.join(home, ".cursor/mcp.json"));
|
|
73541
73581
|
const args = mcp?.mcpServers?.workit?.args ?? [];
|
|
73542
73582
|
const selector = args.find((arg) => typeof arg === "string" && arg.startsWith("--package="));
|
|
73543
73583
|
result.push(classify("cursor", typeof selector === "string" ? selector.slice(10) : "local"));
|
|
@@ -73550,7 +73590,7 @@ var HOSTS2, upgradePaths = (deps) => {
|
|
|
73550
73590
|
if (typeof source !== "string")
|
|
73551
73591
|
continue;
|
|
73552
73592
|
const npm = /^(?:npm:)?@brainervirus\/workit-pi(?:@[^/]+)?$/.test(source);
|
|
73553
|
-
const local =
|
|
73593
|
+
const local = path40.isAbsolute(source) && source.replaceAll("\\", "/").endsWith("/packages/workit-pi") && object2(path40.join(source, "package.json"))?.name === "@brainervirus/workit-pi";
|
|
73554
73594
|
if (npm || local)
|
|
73555
73595
|
result.push(classify("pi", source));
|
|
73556
73596
|
}
|
|
@@ -73597,9 +73637,9 @@ var HOSTS2, upgradePaths = (deps) => {
|
|
|
73597
73637
|
}, piInstalledVersion = (listing, selector) => {
|
|
73598
73638
|
const lines = listing.split(/\r?\n/).map((line) => line.trim());
|
|
73599
73639
|
const index = lines.indexOf(selector);
|
|
73600
|
-
if (index < 0 || !lines[index + 1] || !
|
|
73640
|
+
if (index < 0 || !lines[index + 1] || !path40.isAbsolute(lines[index + 1]))
|
|
73601
73641
|
return;
|
|
73602
|
-
const pkg = object2(
|
|
73642
|
+
const pkg = object2(path40.join(lines[index + 1], "package.json"));
|
|
73603
73643
|
return pkg?.name === "@brainervirus/workit-pi" ? pkg.version : undefined;
|
|
73604
73644
|
}, versionAtLeast = (installed, latest) => {
|
|
73605
73645
|
if (!/^\d+\.\d+\.\d+$/.test(installed))
|
|
@@ -73651,8 +73691,8 @@ var init_launch = __esm(() => {
|
|
|
73651
73691
|
|
|
73652
73692
|
// packages/workit-core/src/knowledge.ts
|
|
73653
73693
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
73654
|
-
import
|
|
73655
|
-
import
|
|
73694
|
+
import fs20 from "node:fs";
|
|
73695
|
+
import path41 from "node:path";
|
|
73656
73696
|
function lintKnowledge(root) {
|
|
73657
73697
|
const seen = new Set;
|
|
73658
73698
|
const unreadable = [];
|
|
@@ -73756,17 +73796,17 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
73756
73796
|
const end = lines.indexOf("---", 1);
|
|
73757
73797
|
return end === -1 ? lines : [...lines.slice(0, end + 1).map(() => ""), ...lines.slice(end + 1)];
|
|
73758
73798
|
}, read = (root, file) => {
|
|
73759
|
-
const full =
|
|
73799
|
+
const full = path41.join(root, file);
|
|
73760
73800
|
try {
|
|
73761
|
-
|
|
73801
|
+
fs20.lstatSync(full);
|
|
73762
73802
|
} catch {
|
|
73763
73803
|
return null;
|
|
73764
73804
|
}
|
|
73765
73805
|
try {
|
|
73766
|
-
if (!
|
|
73806
|
+
if (!fs20.statSync(full).isFile())
|
|
73767
73807
|
return null;
|
|
73768
|
-
const text =
|
|
73769
|
-
return { file, text, lines: text.split(/\r?\n/), real:
|
|
73808
|
+
const text = fs20.readFileSync(full, "utf8");
|
|
73809
|
+
return { file, text, lines: text.split(/\r?\n/), real: fs20.realpathSync(full) };
|
|
73770
73810
|
} catch {
|
|
73771
73811
|
return "unreadable";
|
|
73772
73812
|
}
|
|
@@ -73783,7 +73823,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
73783
73823
|
return new Set(run.stdout.split("\x00").filter(Boolean).map((file) => file.split("/")[0]));
|
|
73784
73824
|
}, exists2 = (target) => {
|
|
73785
73825
|
try {
|
|
73786
|
-
|
|
73826
|
+
fs20.statSync(target);
|
|
73787
73827
|
return true;
|
|
73788
73828
|
} catch {
|
|
73789
73829
|
return false;
|
|
@@ -73797,7 +73837,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
73797
73837
|
}
|
|
73798
73838
|
}, brokenLinks = (root, doc, tracked) => {
|
|
73799
73839
|
const findings = [];
|
|
73800
|
-
const base =
|
|
73840
|
+
const base = path41.dirname(path41.join(root, doc.file));
|
|
73801
73841
|
const missing = (target, line, how) => findings.push({
|
|
73802
73842
|
rule: "broken-link",
|
|
73803
73843
|
file: doc.file,
|
|
@@ -73816,7 +73856,7 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
73816
73856
|
const local = localTarget(target);
|
|
73817
73857
|
if (!local)
|
|
73818
73858
|
continue;
|
|
73819
|
-
const resolved = local.startsWith("/") ?
|
|
73859
|
+
const resolved = local.startsWith("/") ? path41.join(root, local) : path41.resolve(base, local);
|
|
73820
73860
|
if (!exists2(resolved))
|
|
73821
73861
|
missing(target, index + 1, "link");
|
|
73822
73862
|
}
|
|
@@ -73826,9 +73866,9 @@ var AGENTS_BYTE_BUDGET, STEERING_FILES, NEED_BASED_FILES, STANDARDS_FILE = "CODI
|
|
|
73826
73866
|
continue;
|
|
73827
73867
|
const relative = /^\.\.?\//.test(candidate);
|
|
73828
73868
|
const first = candidate.split("/")[0];
|
|
73829
|
-
if (!relative && !(tracked ? tracked.has(first) : exists2(
|
|
73869
|
+
if (!relative && !(tracked ? tracked.has(first) : exists2(path41.join(root, first))))
|
|
73830
73870
|
continue;
|
|
73831
|
-
const resolved = relative ?
|
|
73871
|
+
const resolved = relative ? path41.resolve(base, candidate) : path41.join(root, candidate);
|
|
73832
73872
|
if (!exists2(resolved))
|
|
73833
73873
|
missing(span, index + 1, "pointer");
|
|
73834
73874
|
}
|
|
@@ -74190,9 +74230,9 @@ var init_redact = __esm(() => {
|
|
|
74190
74230
|
// packages/workit-core/src/checks.ts
|
|
74191
74231
|
import { spawn, spawnSync as spawnSync19 } from "node:child_process";
|
|
74192
74232
|
import { createHash as createHash16 } from "node:crypto";
|
|
74193
|
-
import
|
|
74233
|
+
import fs21 from "node:fs";
|
|
74194
74234
|
import os14 from "node:os";
|
|
74195
|
-
import
|
|
74235
|
+
import path42 from "node:path";
|
|
74196
74236
|
import { StringDecoder } from "node:string_decoder";
|
|
74197
74237
|
function tailLines(text, lines = TAIL_LINES) {
|
|
74198
74238
|
const all = text.replace(/\r\n?/gu, `
|
|
@@ -74312,10 +74352,10 @@ function planSpawn(argv, options) {
|
|
|
74312
74352
|
return { file: argv[0], args: [], verbatim: false, shell: true };
|
|
74313
74353
|
if (options.platform !== "win32")
|
|
74314
74354
|
return { file: argv[0], args: argv.slice(1), verbatim: false, shell: false };
|
|
74315
|
-
const win =
|
|
74355
|
+
const win = path42.win32;
|
|
74316
74356
|
const isFile = options.isFile ?? ((file) => {
|
|
74317
74357
|
try {
|
|
74318
|
-
return
|
|
74358
|
+
return fs21.statSync(file).isFile();
|
|
74319
74359
|
} catch {
|
|
74320
74360
|
return false;
|
|
74321
74361
|
}
|
|
@@ -74474,13 +74514,13 @@ function runCheckCommand(argv, options) {
|
|
|
74474
74514
|
function storeLog(storeRoot, log) {
|
|
74475
74515
|
const digest = logDigest(log);
|
|
74476
74516
|
const ref = `blobs/logs/${digest.slice("sha256:".length)}.log`;
|
|
74477
|
-
const file =
|
|
74517
|
+
const file = path42.join(storeRoot, ref);
|
|
74478
74518
|
try {
|
|
74479
|
-
if (!
|
|
74480
|
-
|
|
74519
|
+
if (!fs21.existsSync(file)) {
|
|
74520
|
+
fs21.mkdirSync(path42.dirname(file), { recursive: true });
|
|
74481
74521
|
const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
74482
|
-
|
|
74483
|
-
|
|
74522
|
+
fs21.writeFileSync(temp, log, { mode: 384 });
|
|
74523
|
+
fs21.renameSync(temp, file);
|
|
74484
74524
|
}
|
|
74485
74525
|
return { digest, ref };
|
|
74486
74526
|
} catch {
|
|
@@ -74490,17 +74530,17 @@ function storeLog(storeRoot, log) {
|
|
|
74490
74530
|
function pruneCheckLogs(storeRoot, options = {}) {
|
|
74491
74531
|
const limits = { ...LOG_RETENTION, ...options.retention };
|
|
74492
74532
|
const now = options.now ?? Date.now();
|
|
74493
|
-
const dir =
|
|
74533
|
+
const dir = path42.join(storeRoot, "blobs", "logs");
|
|
74494
74534
|
const report = { removed: 0, removedBytes: 0, kept: 0 };
|
|
74495
74535
|
let names;
|
|
74496
74536
|
try {
|
|
74497
|
-
names =
|
|
74537
|
+
names = fs21.readdirSync(dir);
|
|
74498
74538
|
} catch {
|
|
74499
74539
|
return report;
|
|
74500
74540
|
}
|
|
74501
74541
|
const files = names.flatMap((name) => {
|
|
74502
74542
|
try {
|
|
74503
|
-
const stat =
|
|
74543
|
+
const stat = fs21.statSync(path42.join(dir, name));
|
|
74504
74544
|
return stat.isFile() ? [{ name, size: stat.size, mtimeMs: stat.mtimeMs }] : [];
|
|
74505
74545
|
} catch {
|
|
74506
74546
|
return [];
|
|
@@ -74519,7 +74559,7 @@ function pruneCheckLogs(storeRoot, options = {}) {
|
|
|
74519
74559
|
continue;
|
|
74520
74560
|
if (!options.dryRun)
|
|
74521
74561
|
try {
|
|
74522
|
-
|
|
74562
|
+
fs21.rmSync(path42.join(dir, file.name), { force: true });
|
|
74523
74563
|
} catch {
|
|
74524
74564
|
continue;
|
|
74525
74565
|
}
|
|
@@ -74769,13 +74809,13 @@ var init_grant = __esm(() => {
|
|
|
74769
74809
|
});
|
|
74770
74810
|
|
|
74771
74811
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
74772
|
-
import
|
|
74773
|
-
import
|
|
74812
|
+
import fs22 from "node:fs";
|
|
74813
|
+
import path43 from "node:path";
|
|
74774
74814
|
function gitTop(cwd) {
|
|
74775
|
-
for (let dir =
|
|
74776
|
-
if (
|
|
74815
|
+
for (let dir = path43.resolve(cwd);; dir = path43.dirname(dir)) {
|
|
74816
|
+
if (fs22.existsSync(path43.join(dir, ".git")))
|
|
74777
74817
|
return dir;
|
|
74778
|
-
if (
|
|
74818
|
+
if (path43.dirname(dir) === dir)
|
|
74779
74819
|
return null;
|
|
74780
74820
|
}
|
|
74781
74821
|
}
|
|
@@ -74815,20 +74855,20 @@ var baseName = (word) => (word.split(/[\\/]/u).at(-1) ?? "").toLowerCase().repla
|
|
|
74815
74855
|
var init_heavy_rules = () => {};
|
|
74816
74856
|
|
|
74817
74857
|
// packages/workit-core/src/core/heavy.ts
|
|
74818
|
-
import
|
|
74858
|
+
import fs23 from "node:fs";
|
|
74819
74859
|
import os15 from "node:os";
|
|
74820
|
-
import
|
|
74860
|
+
import path44 from "node:path";
|
|
74821
74861
|
function stateDir(env, platform = process.platform) {
|
|
74822
74862
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
74823
74863
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
74824
74864
|
if (env.XDG_STATE_HOME)
|
|
74825
|
-
return
|
|
74865
|
+
return path44.join(env.XDG_STATE_HOME, "workit");
|
|
74826
74866
|
const home = env.HOME || os15.homedir();
|
|
74827
74867
|
if (platform === "darwin")
|
|
74828
|
-
return
|
|
74868
|
+
return path44.join(home, "Library", "Application Support", "workit");
|
|
74829
74869
|
if (platform === "win32")
|
|
74830
|
-
return
|
|
74831
|
-
return
|
|
74870
|
+
return path44.join(env.LOCALAPPDATA ?? path44.join(home, "AppData", "Local"), "workit");
|
|
74871
|
+
return path44.join(home, ".local", "state", "workit");
|
|
74832
74872
|
}
|
|
74833
74873
|
function positional(words, from, values = PM_VALUES) {
|
|
74834
74874
|
let index = from;
|
|
@@ -74968,7 +75008,7 @@ function machinePatterns(env) {
|
|
|
74968
75008
|
return isRecord7(value) ? stringList(value.patterns) : [];
|
|
74969
75009
|
}
|
|
74970
75010
|
function repoPatterns(cwd) {
|
|
74971
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
75011
|
+
return repoHeavyCommands(gitTop(cwd) ?? path44.resolve(cwd));
|
|
74972
75012
|
}
|
|
74973
75013
|
function heavyLines(lines, options) {
|
|
74974
75014
|
const found = [];
|
|
@@ -75047,9 +75087,9 @@ function leaseRewrite(command) {
|
|
|
75047
75087
|
return null;
|
|
75048
75088
|
return `${prefix}workit check --heavy -- ${rest}`;
|
|
75049
75089
|
}
|
|
75050
|
-
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) =>
|
|
75090
|
+
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path44.join(stateDir(env), HEAVY_COMMANDS_FILE), HEAVY_SCRIPT, INFO_FLAGS, WATCH_FLAG, WATCH_SCRIPT, sub = (...names) => new Set(names), TOOLS, PM_VALUES, baseName2 = (word) => (word?.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat|ps1)$/u, ""), WORKIT, PYTHONS, NPM_INSTALL, NPM_RUN, NPM_TEST, EXEC, globWord = (word) => new RegExp(`^${word.replace(/[.+?^${}()|[\]\\]/gu, "\\$&").replaceAll("*", ".*")}$`, "u"), matches2 = (matchers, words) => matchers.length <= words.length && matchers.every((matcher, index) => index === 0 ? matcher.test(words[0]) || matcher.test(baseName2(words[0])) : matcher.test(words[index])), readJson2 = (file) => {
|
|
75051
75091
|
try {
|
|
75052
|
-
return JSON.parse(
|
|
75092
|
+
return JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
75053
75093
|
} catch {
|
|
75054
75094
|
return;
|
|
75055
75095
|
}
|
|
@@ -75192,9 +75232,9 @@ var init_heavy = __esm(() => {
|
|
|
75192
75232
|
|
|
75193
75233
|
// packages/workit-core/src/core/resources.ts
|
|
75194
75234
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
75195
|
-
import
|
|
75235
|
+
import fs24 from "node:fs";
|
|
75196
75236
|
import os16 from "node:os";
|
|
75197
|
-
import
|
|
75237
|
+
import path45 from "node:path";
|
|
75198
75238
|
function memoryValue(value, host) {
|
|
75199
75239
|
const text = typeof value === "number" ? String(value) : typeof value === "string" ? value : "";
|
|
75200
75240
|
const percent = PERCENT.exec(text.trim());
|
|
@@ -75347,27 +75387,27 @@ function staleReason(lease, probe = {}) {
|
|
|
75347
75387
|
function reclaim(file, stale) {
|
|
75348
75388
|
const guard = `${file}.reclaim`;
|
|
75349
75389
|
try {
|
|
75350
|
-
|
|
75390
|
+
fs24.mkdirSync(guard);
|
|
75351
75391
|
} catch {
|
|
75352
75392
|
try {
|
|
75353
|
-
if (Date.now() -
|
|
75354
|
-
|
|
75393
|
+
if (Date.now() - fs24.statSync(guard).mtimeMs > GUARD_TTL_MS)
|
|
75394
|
+
fs24.rmSync(guard, { force: true, recursive: true });
|
|
75355
75395
|
} catch {}
|
|
75356
75396
|
return false;
|
|
75357
75397
|
}
|
|
75358
75398
|
try {
|
|
75359
75399
|
let ageMs = 0;
|
|
75360
75400
|
try {
|
|
75361
|
-
ageMs = Date.now() -
|
|
75401
|
+
ageMs = Date.now() - fs24.statSync(file).mtimeMs;
|
|
75362
75402
|
} catch {
|
|
75363
75403
|
return true;
|
|
75364
75404
|
}
|
|
75365
75405
|
if (!stale(parseLease(readText4(file)), ageMs))
|
|
75366
75406
|
return false;
|
|
75367
|
-
|
|
75407
|
+
fs24.rmSync(file, { force: true });
|
|
75368
75408
|
return true;
|
|
75369
75409
|
} finally {
|
|
75370
|
-
|
|
75410
|
+
fs24.rmSync(guard, { force: true, recursive: true });
|
|
75371
75411
|
}
|
|
75372
75412
|
}
|
|
75373
75413
|
function tryOnce(options, record, reclaimed) {
|
|
@@ -75375,14 +75415,14 @@ function tryOnce(options, record, reclaimed) {
|
|
|
75375
75415
|
const text = `${JSON.stringify(record)}
|
|
75376
75416
|
`;
|
|
75377
75417
|
for (let slot = 0;slot < options.slots; slot += 1) {
|
|
75378
|
-
const file =
|
|
75418
|
+
const file = path45.join(options.dir, `slot-${slot}.json`);
|
|
75379
75419
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
75380
75420
|
try {
|
|
75381
|
-
const fd =
|
|
75421
|
+
const fd = fs24.openSync(file, "wx", 384);
|
|
75382
75422
|
try {
|
|
75383
|
-
|
|
75423
|
+
fs24.writeSync(fd, text);
|
|
75384
75424
|
} finally {
|
|
75385
|
-
|
|
75425
|
+
fs24.closeSync(fd);
|
|
75386
75426
|
}
|
|
75387
75427
|
return { slot, file };
|
|
75388
75428
|
} catch (error) {
|
|
@@ -75409,7 +75449,7 @@ function tryOnce(options, record, reclaimed) {
|
|
|
75409
75449
|
}
|
|
75410
75450
|
function removeOwn(file, id) {
|
|
75411
75451
|
if (parseLease(readText4(file))?.id === id)
|
|
75412
|
-
|
|
75452
|
+
fs24.rmSync(file, { force: true });
|
|
75413
75453
|
}
|
|
75414
75454
|
async function acquireLease(options) {
|
|
75415
75455
|
const pid = options.pid ?? process.pid;
|
|
@@ -75429,7 +75469,7 @@ async function acquireLease(options) {
|
|
|
75429
75469
|
scope: null
|
|
75430
75470
|
};
|
|
75431
75471
|
try {
|
|
75432
|
-
|
|
75472
|
+
fs24.mkdirSync(options.dir, { recursive: true, mode: 448 });
|
|
75433
75473
|
} catch (error) {
|
|
75434
75474
|
return { ok: false, reason: "unavailable", error: error.message };
|
|
75435
75475
|
}
|
|
@@ -75483,9 +75523,9 @@ function updateLease(lease, patch) {
|
|
|
75483
75523
|
if (parseLease(readText4(lease.file))?.id !== lease.record.id)
|
|
75484
75524
|
return;
|
|
75485
75525
|
const temp = `${lease.file}.${process.pid}.tmp`;
|
|
75486
|
-
|
|
75526
|
+
fs24.writeFileSync(temp, `${JSON.stringify(lease.record)}
|
|
75487
75527
|
`, { mode: 384 });
|
|
75488
|
-
|
|
75528
|
+
fs24.renameSync(temp, lease.file);
|
|
75489
75529
|
} catch {}
|
|
75490
75530
|
}
|
|
75491
75531
|
function heldLease(dir, id, options = {}) {
|
|
@@ -75493,14 +75533,14 @@ function heldLease(dir, id, options = {}) {
|
|
|
75493
75533
|
return null;
|
|
75494
75534
|
let names;
|
|
75495
75535
|
try {
|
|
75496
|
-
names =
|
|
75536
|
+
names = fs24.readdirSync(dir);
|
|
75497
75537
|
} catch {
|
|
75498
75538
|
return null;
|
|
75499
75539
|
}
|
|
75500
75540
|
for (const name of names) {
|
|
75501
75541
|
if (!/^slot-\d+\.json$/u.test(name))
|
|
75502
75542
|
continue;
|
|
75503
|
-
const lease = parseLease(readText4(
|
|
75543
|
+
const lease = parseLease(readText4(path45.join(dir, name)));
|
|
75504
75544
|
if (lease?.id === id && !staleReason(lease, options.probe) && (options.ancestor ?? isAncestor)(lease.pid))
|
|
75505
75545
|
return lease;
|
|
75506
75546
|
}
|
|
@@ -75555,10 +75595,10 @@ async function runScoped(run, wrapper, sinks) {
|
|
|
75555
75595
|
}
|
|
75556
75596
|
function firstNotice(env, session, key, now = Date.now()) {
|
|
75557
75597
|
const id = (session ?? `ppid-${process.ppid}`).replace(/[^A-Za-z0-9_.-]/gu, "_").slice(0, 120);
|
|
75558
|
-
const dir =
|
|
75598
|
+
const dir = path45.join(stateDir(env), "notices");
|
|
75559
75599
|
try {
|
|
75560
|
-
|
|
75561
|
-
|
|
75600
|
+
fs24.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
75601
|
+
fs24.writeFileSync(path45.join(dir, `${key}-${id}`), `${new Date(now).toISOString()}
|
|
75562
75602
|
`, {
|
|
75563
75603
|
flag: "wx",
|
|
75564
75604
|
mode: 384
|
|
@@ -75567,10 +75607,10 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
75567
75607
|
return error.code !== "EEXIST";
|
|
75568
75608
|
}
|
|
75569
75609
|
try {
|
|
75570
|
-
for (const name of
|
|
75571
|
-
const file =
|
|
75572
|
-
if (now -
|
|
75573
|
-
|
|
75610
|
+
for (const name of fs24.readdirSync(dir)) {
|
|
75611
|
+
const file = path45.join(dir, name);
|
|
75612
|
+
if (now - fs24.statSync(file).mtimeMs > NOTICE_TTL_MS)
|
|
75613
|
+
fs24.rmSync(file, { force: true });
|
|
75574
75614
|
}
|
|
75575
75615
|
} catch {}
|
|
75576
75616
|
return true;
|
|
@@ -75578,7 +75618,7 @@ function firstNotice(env, session, key, now = Date.now()) {
|
|
|
75578
75618
|
function leaseSlots(dir, slots, probe = {}) {
|
|
75579
75619
|
const states = [];
|
|
75580
75620
|
for (let slot = 0;slot < slots; slot += 1) {
|
|
75581
|
-
const lease = parseLease(readText4(
|
|
75621
|
+
const lease = parseLease(readText4(path45.join(dir, `slot-${slot}.json`)));
|
|
75582
75622
|
states.push({
|
|
75583
75623
|
slot,
|
|
75584
75624
|
holder: lease ? holderOf(lease) : null,
|
|
@@ -75590,9 +75630,9 @@ function leaseSlots(dir, slots, probe = {}) {
|
|
|
75590
75630
|
var DEFAULT_HEAVY_CHECKS, DEFAULT_SLOTS = 1, DEFAULT_WAIT_S = 600, DEFAULT_MEMORY_SHARE = 0.4, DEFAULT_CPU_SHARE = 0.7, MAX_SLOTS = 64, UNREADABLE_TTL_MS = 30000, GUARD_TTL_MS = 30000, hostShape = () => ({
|
|
75591
75631
|
totalMemBytes: os16.totalmem(),
|
|
75592
75632
|
cpus: Math.max(1, os16.availableParallelism?.() ?? os16.cpus().length)
|
|
75593
|
-
}), isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) =>
|
|
75633
|
+
}), isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), SIZE, PERCENT, UNITS, leaseDir = (env) => path45.join(stateDir(env), "leases"), readText4 = (file) => {
|
|
75594
75634
|
try {
|
|
75595
|
-
return
|
|
75635
|
+
return fs24.readFileSync(file, "utf8");
|
|
75596
75636
|
} catch {
|
|
75597
75637
|
return null;
|
|
75598
75638
|
}
|
|
@@ -75643,7 +75683,7 @@ __export(exports_check, {
|
|
|
75643
75683
|
workspaceResources: () => workspaceResources
|
|
75644
75684
|
});
|
|
75645
75685
|
import os17 from "node:os";
|
|
75646
|
-
import
|
|
75686
|
+
import path46 from "node:path";
|
|
75647
75687
|
function parse5(argv) {
|
|
75648
75688
|
const split = argv.indexOf("--");
|
|
75649
75689
|
const head = split >= 0 ? argv.slice(0, split) : [...argv];
|
|
@@ -75822,7 +75862,7 @@ function hostToolWaitCapMs(env) {
|
|
|
75822
75862
|
}
|
|
75823
75863
|
async function workspaceResources(io) {
|
|
75824
75864
|
const env = io.env;
|
|
75825
|
-
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ??
|
|
75865
|
+
const dir = env.WORKFLOW_TOOLKIT_CONFIG ?? env.WORKFLOW_TOOLKIT_CONFIG_DIR ?? path46.join(env.XDG_CONFIG_HOME || path46.join(env.HOME || os17.homedir(), ".config"), "workit");
|
|
75826
75866
|
try {
|
|
75827
75867
|
await Promise.resolve().then(() => init_workspaces());
|
|
75828
75868
|
const workspace = resolveWorkspaceFrom(io.cwd, dir, env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
|
|
@@ -75941,7 +75981,7 @@ async function run10(argv, io) {
|
|
|
75941
75981
|
if (options.shell && command.length !== 1)
|
|
75942
75982
|
return emit(io, fail2("invalid_input", '--shell takes the command as one string: workit check --shell -- "<cmd>"'));
|
|
75943
75983
|
}
|
|
75944
|
-
const relCwd = posix(
|
|
75984
|
+
const relCwd = posix(path46.relative(top, runCwd));
|
|
75945
75985
|
const configured = !options.shell && matchesNamedCheck(config, name, command, relCwd);
|
|
75946
75986
|
const actor = actorFromEnv(io.env);
|
|
75947
75987
|
const branchKey = codeKey(io.cwd, { base: options.base });
|
|
@@ -76107,7 +76147,7 @@ async function run10(argv, io) {
|
|
|
76107
76147
|
return recordError.code === "busy" ? 4 : recordError.code === "invalid_input" ? 2 : 5;
|
|
76108
76148
|
return 0;
|
|
76109
76149
|
}
|
|
76110
|
-
var USAGE3 = 'workit check <name> [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--wait <s>] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(
|
|
76150
|
+
var USAGE3 = 'workit check <name> [--no-lease --reason "<why>"] | workit check [--name <n>] [--shell] [--heavy] [--wait <s>] [--timeout <s>] [--task <id>] [--json] -- <cmd…>', MAX_UNVERIFIED_RUN_MS, RECORD_TAIL_LINES = 20, RECORD_TAIL_CHARS = 200, posix = (value) => value.split(path46.sep).join("/") || ".", ENGINE_CODES2, FINGERPRINT_VARS, HOST_TOOL_WAIT_CAP_MS = 1e5;
|
|
76111
76151
|
var init_check = __esm(() => {
|
|
76112
76152
|
init_check_config();
|
|
76113
76153
|
init_checks3();
|
|
@@ -76132,8 +76172,8 @@ var exports_lock = {};
|
|
|
76132
76172
|
__export(exports_lock, {
|
|
76133
76173
|
run: () => run11
|
|
76134
76174
|
});
|
|
76135
|
-
import
|
|
76136
|
-
import
|
|
76175
|
+
import fs25 from "node:fs";
|
|
76176
|
+
import path47 from "node:path";
|
|
76137
76177
|
async function settingsFor(io) {
|
|
76138
76178
|
const workspace = await workspaceResources(io);
|
|
76139
76179
|
const config = loadCheckConfig(io.cwd);
|
|
@@ -76205,7 +76245,7 @@ async function runHeavy(args, io) {
|
|
|
76205
76245
|
}
|
|
76206
76246
|
function readPatterns(file) {
|
|
76207
76247
|
try {
|
|
76208
|
-
const value = JSON.parse(
|
|
76248
|
+
const value = JSON.parse(fs25.readFileSync(file, "utf8"));
|
|
76209
76249
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
76210
76250
|
const record = value;
|
|
76211
76251
|
const patterns = Array.isArray(record.patterns) ? record.patterns.filter((item) => typeof item === "string") : [];
|
|
@@ -76215,11 +76255,11 @@ function readPatterns(file) {
|
|
|
76215
76255
|
return { patterns: [] };
|
|
76216
76256
|
}
|
|
76217
76257
|
function writePatterns(file, value) {
|
|
76218
|
-
|
|
76258
|
+
fs25.mkdirSync(path47.dirname(file), { recursive: true, mode: 448 });
|
|
76219
76259
|
const temp = `${file}.${process.pid}.tmp`;
|
|
76220
|
-
|
|
76260
|
+
fs25.writeFileSync(temp, `${JSON.stringify(value, null, 2)}
|
|
76221
76261
|
`, { mode: 384 });
|
|
76222
|
-
|
|
76262
|
+
fs25.renameSync(temp, file);
|
|
76223
76263
|
}
|
|
76224
76264
|
async function heavy(args, io) {
|
|
76225
76265
|
const [action, ...rest] = args.filter((arg) => arg !== "--json");
|
|
@@ -76406,7 +76446,7 @@ var success2 = (data) => ({ ok: true, data }), failure3 = (code, error, unblock)
|
|
|
76406
76446
|
// packages/workit-core/src/git/ops.ts
|
|
76407
76447
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
76408
76448
|
import { existsSync as existsSync19, readFileSync as readFileSync19 } from "node:fs";
|
|
76409
|
-
import
|
|
76449
|
+
import path48 from "node:path";
|
|
76410
76450
|
function operationInProgress(cwd) {
|
|
76411
76451
|
const markers = [
|
|
76412
76452
|
["rebase-merge", "rebase"],
|
|
@@ -76419,18 +76459,18 @@ function operationInProgress(cwd) {
|
|
|
76419
76459
|
if (!run.ok)
|
|
76420
76460
|
return null;
|
|
76421
76461
|
const found = run.stdout.split(`
|
|
76422
|
-
`).map((line) =>
|
|
76462
|
+
`).map((line) => path48.resolve(cwd, line.trim()));
|
|
76423
76463
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
76424
76464
|
for (const [index, [, operation]] of markers.entries()) {
|
|
76425
76465
|
const marker = found[index];
|
|
76426
76466
|
if (!marker || !existsSync19(marker))
|
|
76427
76467
|
continue;
|
|
76428
|
-
if (index === 1 && existsSync19(
|
|
76468
|
+
if (index === 1 && existsSync19(path48.join(marker, "applying")))
|
|
76429
76469
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
76430
|
-
if (index === 0 && existsSync19(
|
|
76470
|
+
if (index === 0 && existsSync19(path48.join(marker, "amend")) && !conflicted()) {
|
|
76431
76471
|
let headName = "";
|
|
76432
76472
|
try {
|
|
76433
|
-
headName = readFileSync19(
|
|
76473
|
+
headName = readFileSync19(path48.join(marker, "head-name"), "utf8").trim();
|
|
76434
76474
|
} catch {}
|
|
76435
76475
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
76436
76476
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -76758,7 +76798,7 @@ function gitCommit(cwd, input) {
|
|
|
76758
76798
|
if (paths.some((value) => value.startsWith("-") || !value.trim()))
|
|
76759
76799
|
return failure3("invalid_input", "paths must not be empty or start with -");
|
|
76760
76800
|
const tracked = new Set(nulList(git5(cwd, ["ls-files", "-z", "--", ...paths]).stdout));
|
|
76761
|
-
const addable = paths.filter((value) => existsSync19(
|
|
76801
|
+
const addable = paths.filter((value) => existsSync19(path48.resolve(cwd, value)) || [...tracked].some((file) => file === value || file.startsWith(`${value}/`)));
|
|
76762
76802
|
if (addable.length) {
|
|
76763
76803
|
const added = git5(cwd, ["add", "-A", "--", ...addable]);
|
|
76764
76804
|
if (!added.ok)
|
|
@@ -77284,11 +77324,11 @@ var init_ops = __esm(() => {
|
|
|
77284
77324
|
});
|
|
77285
77325
|
|
|
77286
77326
|
// packages/workit-core/src/forge/reruns.ts
|
|
77287
|
-
import
|
|
77288
|
-
import
|
|
77327
|
+
import fs26 from "node:fs";
|
|
77328
|
+
import path49 from "node:path";
|
|
77289
77329
|
function rerunLogPath(cwd) {
|
|
77290
77330
|
const common = gitCommonDir(cwd);
|
|
77291
|
-
return common ?
|
|
77331
|
+
return common ? path49.join(common, "workit", "ci-reruns.jsonl") : null;
|
|
77292
77332
|
}
|
|
77293
77333
|
function rerunCounts(cwd, key) {
|
|
77294
77334
|
const counts = new Map;
|
|
@@ -77297,7 +77337,7 @@ function rerunCounts(cwd, key) {
|
|
|
77297
77337
|
return counts;
|
|
77298
77338
|
let text;
|
|
77299
77339
|
try {
|
|
77300
|
-
text =
|
|
77340
|
+
text = fs26.readFileSync(file, "utf8");
|
|
77301
77341
|
} catch {
|
|
77302
77342
|
return counts;
|
|
77303
77343
|
}
|
|
@@ -77323,8 +77363,8 @@ function recordReruns(cwd, rows) {
|
|
|
77323
77363
|
if (!file)
|
|
77324
77364
|
return false;
|
|
77325
77365
|
try {
|
|
77326
|
-
|
|
77327
|
-
|
|
77366
|
+
fs26.mkdirSync(path49.dirname(file), { recursive: true });
|
|
77367
|
+
fs26.appendFileSync(file, rows.map((row) => `${JSON.stringify(row)}
|
|
77328
77368
|
`).join(""));
|
|
77329
77369
|
return true;
|
|
77330
77370
|
} catch {
|
|
@@ -77336,18 +77376,18 @@ function withRerunLock(cwd, fn) {
|
|
|
77336
77376
|
if (!file)
|
|
77337
77377
|
return fn();
|
|
77338
77378
|
const lock = `${file.slice(0, -".jsonl".length)}.lock`;
|
|
77339
|
-
|
|
77379
|
+
fs26.mkdirSync(path49.dirname(lock), { recursive: true });
|
|
77340
77380
|
const until = Date.now() + LOCK_WAIT_MS2;
|
|
77341
77381
|
for (;; ) {
|
|
77342
77382
|
try {
|
|
77343
|
-
|
|
77383
|
+
fs26.closeSync(fs26.openSync(lock, "wx"));
|
|
77344
77384
|
break;
|
|
77345
77385
|
} catch (error) {
|
|
77346
77386
|
if (error.code !== "EEXIST")
|
|
77347
77387
|
throw error;
|
|
77348
77388
|
try {
|
|
77349
|
-
if (Date.now() -
|
|
77350
|
-
|
|
77389
|
+
if (Date.now() - fs26.statSync(lock).mtimeMs > LOCK_STALE_MS2) {
|
|
77390
|
+
fs26.rmSync(lock, { force: true });
|
|
77351
77391
|
continue;
|
|
77352
77392
|
}
|
|
77353
77393
|
} catch {
|
|
@@ -77361,7 +77401,7 @@ function withRerunLock(cwd, fn) {
|
|
|
77361
77401
|
try {
|
|
77362
77402
|
return fn();
|
|
77363
77403
|
} finally {
|
|
77364
|
-
|
|
77404
|
+
fs26.rmSync(lock, { force: true });
|
|
77365
77405
|
}
|
|
77366
77406
|
}
|
|
77367
77407
|
var isRow = (value) => {
|
|
@@ -78228,8 +78268,8 @@ var init_pr_ops = __esm(() => {
|
|
|
78228
78268
|
// packages/workit-core/src/stack.ts
|
|
78229
78269
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
78230
78270
|
import { createHash as createHash17, randomBytes as randomBytes4 } from "node:crypto";
|
|
78231
|
-
import
|
|
78232
|
-
import
|
|
78271
|
+
import fs27 from "node:fs";
|
|
78272
|
+
import path50 from "node:path";
|
|
78233
78273
|
function worktreeOf(cwd, branch) {
|
|
78234
78274
|
const list = gitRun3(cwd, ["worktree", "list", "--porcelain"]);
|
|
78235
78275
|
if (!list.ok)
|
|
@@ -78252,7 +78292,7 @@ function rebasingBranch2(dir) {
|
|
|
78252
78292
|
if (!found.ok)
|
|
78253
78293
|
continue;
|
|
78254
78294
|
try {
|
|
78255
|
-
return
|
|
78295
|
+
return fs27.readFileSync(found.stdout.trim(), "utf8").trim();
|
|
78256
78296
|
} catch {}
|
|
78257
78297
|
}
|
|
78258
78298
|
return null;
|
|
@@ -78260,7 +78300,7 @@ function rebasingBranch2(dir) {
|
|
|
78260
78300
|
function rebaseInProgress(dir) {
|
|
78261
78301
|
for (const name of ["rebase-merge", "rebase-apply"]) {
|
|
78262
78302
|
const found = gitRun3(dir, ["rev-parse", "--path-format=absolute", "--git-path", name]);
|
|
78263
|
-
if (found.ok &&
|
|
78303
|
+
if (found.ok && fs27.existsSync(found.stdout.trim()))
|
|
78264
78304
|
return true;
|
|
78265
78305
|
}
|
|
78266
78306
|
return false;
|
|
@@ -78272,8 +78312,8 @@ function gitRestack(cwd, input) {
|
|
|
78272
78312
|
const scratch = scratchDir(cwd);
|
|
78273
78313
|
if (!scratch)
|
|
78274
78314
|
return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
|
|
78275
|
-
|
|
78276
|
-
dir =
|
|
78315
|
+
fs27.mkdirSync(scratch, { recursive: true });
|
|
78316
|
+
dir = path50.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
78277
78317
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
78278
78318
|
if (!added.ok)
|
|
78279
78319
|
return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
|
|
@@ -78311,10 +78351,10 @@ function gitRestack(cwd, input) {
|
|
|
78311
78351
|
}
|
|
78312
78352
|
function pruneScratch(cwd) {
|
|
78313
78353
|
const scratch = scratchDir(cwd);
|
|
78314
|
-
if (!scratch || !
|
|
78354
|
+
if (!scratch || !fs27.existsSync(scratch))
|
|
78315
78355
|
return;
|
|
78316
|
-
for (const name of
|
|
78317
|
-
const dir =
|
|
78356
|
+
for (const name of fs27.readdirSync(scratch)) {
|
|
78357
|
+
const dir = path50.join(scratch, name);
|
|
78318
78358
|
if (!rebaseInProgress(dir) && !trackedDirt(dir))
|
|
78319
78359
|
gitRun3(cwd, ["worktree", "remove", "--force", dir]);
|
|
78320
78360
|
}
|
|
@@ -78324,7 +78364,7 @@ function stacksDir(cwd) {
|
|
|
78324
78364
|
const root = storeRoot(cwd);
|
|
78325
78365
|
if (!root.ok)
|
|
78326
78366
|
return stackFail(root.code, root.error, root.unblock);
|
|
78327
|
-
return { ok: true, data:
|
|
78367
|
+
return { ok: true, data: path50.join(root.value.root, "stacks") };
|
|
78328
78368
|
}
|
|
78329
78369
|
function parseStack(raw) {
|
|
78330
78370
|
if (!isRecord10(raw) || !Array.isArray(raw.branches))
|
|
@@ -78376,10 +78416,10 @@ function readStack(cwd, name) {
|
|
|
78376
78416
|
const dir = stacksDir(cwd);
|
|
78377
78417
|
if (!dir.ok)
|
|
78378
78418
|
return dir;
|
|
78379
|
-
const file =
|
|
78419
|
+
const file = path50.join(dir.data, fileFor(name));
|
|
78380
78420
|
let text;
|
|
78381
78421
|
try {
|
|
78382
|
-
text =
|
|
78422
|
+
text = fs27.readFileSync(file, "utf8");
|
|
78383
78423
|
} catch (error) {
|
|
78384
78424
|
if (error.code === "ENOENT")
|
|
78385
78425
|
return { ok: true, data: null };
|
|
@@ -78397,17 +78437,17 @@ function writeStack(cwd, stack, now = new Date) {
|
|
|
78397
78437
|
const dir = stacksDir(cwd);
|
|
78398
78438
|
if (!dir.ok)
|
|
78399
78439
|
return dir;
|
|
78400
|
-
const file =
|
|
78440
|
+
const file = path50.join(dir.data, fileFor(stack.name));
|
|
78401
78441
|
const temp = `${file}.${process.pid}.tmp`;
|
|
78402
78442
|
try {
|
|
78403
|
-
|
|
78443
|
+
fs27.mkdirSync(dir.data, { recursive: true });
|
|
78404
78444
|
stack.updatedAt = now.toISOString();
|
|
78405
|
-
|
|
78445
|
+
fs27.writeFileSync(temp, `${JSON.stringify(stack, null, 2)}
|
|
78406
78446
|
`);
|
|
78407
|
-
|
|
78447
|
+
fs27.renameSync(temp, file);
|
|
78408
78448
|
return { ok: true, data: undefined };
|
|
78409
78449
|
} catch (error) {
|
|
78410
|
-
|
|
78450
|
+
fs27.rmSync(temp, { force: true });
|
|
78411
78451
|
return stackFail("unavailable", `cannot write ${file}: ${error.message}`);
|
|
78412
78452
|
}
|
|
78413
78453
|
}
|
|
@@ -78417,7 +78457,7 @@ function listStacks(cwd) {
|
|
|
78417
78457
|
return dir;
|
|
78418
78458
|
let names = [];
|
|
78419
78459
|
try {
|
|
78420
|
-
names =
|
|
78460
|
+
names = fs27.readdirSync(dir.data).filter((name) => name.endsWith(".json"));
|
|
78421
78461
|
} catch {
|
|
78422
78462
|
return { ok: true, data: [] };
|
|
78423
78463
|
}
|
|
@@ -78425,7 +78465,7 @@ function listStacks(cwd) {
|
|
|
78425
78465
|
for (const name of names) {
|
|
78426
78466
|
let parsed = null;
|
|
78427
78467
|
try {
|
|
78428
|
-
parsed = parseStack(JSON.parse(
|
|
78468
|
+
parsed = parseStack(JSON.parse(fs27.readFileSync(path50.join(dir.data, name), "utf8")));
|
|
78429
78469
|
} catch {
|
|
78430
78470
|
parsed = null;
|
|
78431
78471
|
}
|
|
@@ -78472,7 +78512,7 @@ function stackLockStale(raw, age) {
|
|
|
78472
78512
|
}
|
|
78473
78513
|
function takeLock(lock) {
|
|
78474
78514
|
try {
|
|
78475
|
-
|
|
78515
|
+
fs27.mkdirSync(lock);
|
|
78476
78516
|
} catch (error) {
|
|
78477
78517
|
if (error.code === "EEXIST")
|
|
78478
78518
|
return null;
|
|
@@ -78484,24 +78524,24 @@ function takeLock(lock) {
|
|
|
78484
78524
|
host: localLockHost(),
|
|
78485
78525
|
nonce: randomBytes4(8).toString("hex")
|
|
78486
78526
|
};
|
|
78487
|
-
|
|
78527
|
+
fs27.writeFileSync(path50.join(lock, OWNER), JSON.stringify(owner));
|
|
78488
78528
|
return owner;
|
|
78489
78529
|
}
|
|
78490
78530
|
function reapLock(lock, observed) {
|
|
78491
78531
|
const tomb = `${lock}.reap-${randomBytes4(6).toString("hex")}`;
|
|
78492
78532
|
try {
|
|
78493
|
-
|
|
78533
|
+
fs27.renameSync(lock, tomb);
|
|
78494
78534
|
} catch {
|
|
78495
78535
|
return false;
|
|
78496
78536
|
}
|
|
78497
78537
|
if (readOwner(tomb).raw === observed) {
|
|
78498
|
-
|
|
78538
|
+
fs27.rmSync(tomb, { recursive: true, force: true });
|
|
78499
78539
|
return true;
|
|
78500
78540
|
}
|
|
78501
78541
|
try {
|
|
78502
|
-
|
|
78542
|
+
fs27.renameSync(tomb, lock);
|
|
78503
78543
|
} catch {
|
|
78504
|
-
|
|
78544
|
+
fs27.rmSync(tomb, { recursive: true, force: true });
|
|
78505
78545
|
}
|
|
78506
78546
|
return false;
|
|
78507
78547
|
}
|
|
@@ -78511,8 +78551,8 @@ function releaseLock(lock, owner) {
|
|
|
78511
78551
|
return;
|
|
78512
78552
|
const tomb = `${lock}.release-${randomBytes4(6).toString("hex")}`;
|
|
78513
78553
|
try {
|
|
78514
|
-
|
|
78515
|
-
|
|
78554
|
+
fs27.renameSync(lock, tomb);
|
|
78555
|
+
fs27.rmSync(tomb, { recursive: true, force: true });
|
|
78516
78556
|
} catch {}
|
|
78517
78557
|
}
|
|
78518
78558
|
async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
@@ -78521,9 +78561,9 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
78521
78561
|
return dir;
|
|
78522
78562
|
if (!validName(name))
|
|
78523
78563
|
return stackFail("invalid_input", "a stack name must be 1-200 printable characters");
|
|
78524
|
-
const lock =
|
|
78564
|
+
const lock = path50.join(dir.data, `${fileFor(name)}.lock`);
|
|
78525
78565
|
try {
|
|
78526
|
-
|
|
78566
|
+
fs27.mkdirSync(dir.data, { recursive: true });
|
|
78527
78567
|
} catch (error) {
|
|
78528
78568
|
return stackFail("unavailable", `cannot create ${dir.data}: ${error.message}`);
|
|
78529
78569
|
}
|
|
@@ -78551,7 +78591,7 @@ async function withStackLock(cwd, name, fn, waitMs = LOCK_WAIT_MS3) {
|
|
|
78551
78591
|
const touch = () => {
|
|
78552
78592
|
try {
|
|
78553
78593
|
const now = new Date;
|
|
78554
|
-
|
|
78594
|
+
fs27.utimesSync(path50.join(lock, OWNER), now, now);
|
|
78555
78595
|
} catch {}
|
|
78556
78596
|
};
|
|
78557
78597
|
const beat = setInterval(touch, HEARTBEAT_MS);
|
|
@@ -79391,7 +79431,7 @@ var STACK_VERSION = 1, stackFail = (code, error, unblock, data) => ({
|
|
|
79391
79431
|
return !status.ok || status.stdout.trim() !== "";
|
|
79392
79432
|
}, scratchDir = (cwd) => {
|
|
79393
79433
|
const dir = stacksDir(cwd);
|
|
79394
|
-
return dir.ok ?
|
|
79434
|
+
return dir.ok ? path50.join(dir.data, "worktrees") : null;
|
|
79395
79435
|
}, firstLine = (run) => (`${run.stderr}
|
|
79396
79436
|
${run.stdout}`.split(`
|
|
79397
79437
|
`).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) => {
|
|
@@ -79406,14 +79446,14 @@ ${run.stdout}`.split(`
|
|
|
79406
79446
|
}, isRecord10 = (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) => {
|
|
79407
79447
|
let raw = null;
|
|
79408
79448
|
try {
|
|
79409
|
-
raw =
|
|
79449
|
+
raw = fs27.readFileSync(path50.join(lock, OWNER), "utf8");
|
|
79410
79450
|
} catch {
|
|
79411
79451
|
raw = null;
|
|
79412
79452
|
}
|
|
79413
79453
|
let age = null;
|
|
79414
|
-
for (const target of [
|
|
79454
|
+
for (const target of [path50.join(lock, OWNER), lock])
|
|
79415
79455
|
try {
|
|
79416
|
-
age = Date.now() -
|
|
79456
|
+
age = Date.now() - fs27.statSync(target).mtimeMs;
|
|
79417
79457
|
break;
|
|
79418
79458
|
} catch {}
|
|
79419
79459
|
return { raw, age };
|
|
@@ -79446,8 +79486,8 @@ var init_stack = __esm(() => {
|
|
|
79446
79486
|
// packages/workit-core/src/fanout.ts
|
|
79447
79487
|
import { spawnSync as spawnSync23 } from "node:child_process";
|
|
79448
79488
|
import { createHash as createHash18 } from "node:crypto";
|
|
79449
|
-
import
|
|
79450
|
-
import
|
|
79489
|
+
import fs28 from "node:fs";
|
|
79490
|
+
import path51 from "node:path";
|
|
79451
79491
|
function expandBraces2(pattern, limit = 64) {
|
|
79452
79492
|
for (let index = 0;index < pattern.length; index += 1) {
|
|
79453
79493
|
if (pattern[index] === "\\") {
|
|
@@ -79693,7 +79733,7 @@ function parsePlan(raw, defaults, name) {
|
|
|
79693
79733
|
id,
|
|
79694
79734
|
branch,
|
|
79695
79735
|
base: optional("base") ?? "",
|
|
79696
|
-
worktree:
|
|
79736
|
+
worktree: path51.resolve(defaults.root, optional("worktree") ?? path51.join(defaults.worktreeRoot, id)),
|
|
79697
79737
|
tier,
|
|
79698
79738
|
reason,
|
|
79699
79739
|
dependsOn: [...new Set(dependsOn ?? [])],
|
|
@@ -79924,11 +79964,11 @@ function defaultTrunk(cwd) {
|
|
|
79924
79964
|
}
|
|
79925
79965
|
function mainCheckout(cwd) {
|
|
79926
79966
|
const common = gitCommonDir(cwd);
|
|
79927
|
-
return common &&
|
|
79967
|
+
return common && path51.basename(common) === ".git" ? path51.dirname(common) : path51.resolve(cwd);
|
|
79928
79968
|
}
|
|
79929
79969
|
function worktreeRoot(cwd) {
|
|
79930
79970
|
const main = mainCheckout(cwd);
|
|
79931
|
-
return
|
|
79971
|
+
return path51.join(path51.dirname(main), `${path51.basename(main)}-wt`);
|
|
79932
79972
|
}
|
|
79933
79973
|
function sliceHash(slice) {
|
|
79934
79974
|
const {
|
|
@@ -79948,7 +79988,7 @@ function fanoutsDir(cwd) {
|
|
|
79948
79988
|
const root = storeRoot(cwd);
|
|
79949
79989
|
if (!root.ok)
|
|
79950
79990
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
79951
|
-
return { ok: true, data:
|
|
79991
|
+
return { ok: true, data: path51.join(root.value.root, "fanouts") };
|
|
79952
79992
|
}
|
|
79953
79993
|
function parseStored(raw) {
|
|
79954
79994
|
if (!isRecord11(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -80016,10 +80056,10 @@ function readFanout(cwd, name) {
|
|
|
80016
80056
|
const dir = fanoutsDir(cwd);
|
|
80017
80057
|
if (!dir.ok)
|
|
80018
80058
|
return dir;
|
|
80019
|
-
const file =
|
|
80059
|
+
const file = path51.join(dir.data, stackFileName(name));
|
|
80020
80060
|
let parsed = null;
|
|
80021
80061
|
try {
|
|
80022
|
-
parsed = parseStored(JSON.parse(
|
|
80062
|
+
parsed = parseStored(JSON.parse(fs28.readFileSync(file, "utf8")));
|
|
80023
80063
|
} catch (error) {
|
|
80024
80064
|
if (error.code === "ENOENT")
|
|
80025
80065
|
return { ok: true, data: null };
|
|
@@ -80033,7 +80073,7 @@ function listFanouts(cwd) {
|
|
|
80033
80073
|
return dir;
|
|
80034
80074
|
let names = [];
|
|
80035
80075
|
try {
|
|
80036
|
-
names =
|
|
80076
|
+
names = fs28.readdirSync(dir.data).filter((entry) => entry.endsWith(".json"));
|
|
80037
80077
|
} catch {
|
|
80038
80078
|
return { ok: true, data: [] };
|
|
80039
80079
|
}
|
|
@@ -80041,7 +80081,7 @@ function listFanouts(cwd) {
|
|
|
80041
80081
|
for (const entry of names) {
|
|
80042
80082
|
let parsed = null;
|
|
80043
80083
|
try {
|
|
80044
|
-
parsed = parseStored(JSON.parse(
|
|
80084
|
+
parsed = parseStored(JSON.parse(fs28.readFileSync(path51.join(dir.data, entry), "utf8")));
|
|
80045
80085
|
} catch {
|
|
80046
80086
|
parsed = null;
|
|
80047
80087
|
}
|
|
@@ -80080,16 +80120,16 @@ function writeFanout(cwd, plan) {
|
|
|
80080
80120
|
const dir = fanoutsDir(cwd);
|
|
80081
80121
|
if (!dir.ok)
|
|
80082
80122
|
return dir;
|
|
80083
|
-
const file =
|
|
80123
|
+
const file = path51.join(dir.data, stackFileName(plan.name));
|
|
80084
80124
|
const temp = `${file}.${process.pid}.tmp`;
|
|
80085
80125
|
try {
|
|
80086
|
-
|
|
80087
|
-
|
|
80126
|
+
fs28.mkdirSync(dir.data, { recursive: true });
|
|
80127
|
+
fs28.writeFileSync(temp, `${JSON.stringify(plan, null, 2)}
|
|
80088
80128
|
`);
|
|
80089
|
-
|
|
80129
|
+
fs28.renameSync(temp, file);
|
|
80090
80130
|
return { ok: true, data: file };
|
|
80091
80131
|
} catch (error) {
|
|
80092
|
-
|
|
80132
|
+
fs28.rmSync(temp, { force: true });
|
|
80093
80133
|
return fanoutFail("unavailable", `cannot write ${file}: ${error.message}`);
|
|
80094
80134
|
}
|
|
80095
80135
|
}
|
|
@@ -80286,16 +80326,16 @@ var init_fanout = __esm(() => {
|
|
|
80286
80326
|
|
|
80287
80327
|
// packages/workit-core/src/forge/exec.ts
|
|
80288
80328
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
80289
|
-
import
|
|
80290
|
-
import
|
|
80329
|
+
import fs29 from "node:fs";
|
|
80330
|
+
import path52 from "node:path";
|
|
80291
80331
|
function findExecutable(bin, env) {
|
|
80292
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
80332
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path52.delimiter).filter(Boolean);
|
|
80293
80333
|
const exts = process.platform === "win32" ? [".exe"] : [""];
|
|
80294
80334
|
for (const dir of dirs)
|
|
80295
80335
|
for (const ext of exts) {
|
|
80296
|
-
const candidate =
|
|
80336
|
+
const candidate = path52.join(dir, `${bin}${ext}`);
|
|
80297
80337
|
try {
|
|
80298
|
-
const stat =
|
|
80338
|
+
const stat = fs29.statSync(candidate);
|
|
80299
80339
|
if (stat.isFile())
|
|
80300
80340
|
return candidate;
|
|
80301
80341
|
} catch {}
|
|
@@ -81767,7 +81807,7 @@ var init_pr_edit = __esm(() => {
|
|
|
81767
81807
|
});
|
|
81768
81808
|
|
|
81769
81809
|
// packages/workit-core/src/forge/resolve.ts
|
|
81770
|
-
import
|
|
81810
|
+
import fs30 from "node:fs";
|
|
81771
81811
|
function memo4(scope, key, compute, now = Date.now) {
|
|
81772
81812
|
let entries = memoScopes.get(scope.owner);
|
|
81773
81813
|
if (!entries)
|
|
@@ -81813,14 +81853,14 @@ function resolveCredential(workspace, derived, run, scope) {
|
|
|
81813
81853
|
if (process.platform !== "win32") {
|
|
81814
81854
|
let mode = 0;
|
|
81815
81855
|
try {
|
|
81816
|
-
mode =
|
|
81856
|
+
mode = fs30.statSync(tokenFile.trim()).mode;
|
|
81817
81857
|
} catch {}
|
|
81818
81858
|
if ((mode & 63) !== 0)
|
|
81819
81859
|
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile is readable by group or other (mode ${(mode & 511).toString(8).padStart(4, "0")})`, `chmod 600 ${tokenFile.trim()}`);
|
|
81820
81860
|
}
|
|
81821
81861
|
let token = "";
|
|
81822
81862
|
try {
|
|
81823
|
-
token =
|
|
81863
|
+
token = fs30.readFileSync(tokenFile.trim(), "utf8").trim();
|
|
81824
81864
|
} catch {
|
|
81825
81865
|
return failure3("blocked", `workspace ${workspace?.name ?? "?"} vcs.tokenFile cannot be read`, "fix vcs.tokenFile in ~/.config/workit/workspaces.json");
|
|
81826
81866
|
}
|
|
@@ -82193,11 +82233,11 @@ __export(exports_pr, {
|
|
|
82193
82233
|
run: () => run12
|
|
82194
82234
|
});
|
|
82195
82235
|
import { readFileSync as readFileSync21 } from "node:fs";
|
|
82196
|
-
import
|
|
82236
|
+
import path53 from "node:path";
|
|
82197
82237
|
function readBodyFile(io, file) {
|
|
82198
82238
|
try {
|
|
82199
82239
|
return {
|
|
82200
|
-
body: file === "-" ? forgeDeps.readStdin() : readFileSync21(
|
|
82240
|
+
body: file === "-" ? forgeDeps.readStdin() : readFileSync21(path53.resolve(io.cwd, file), "utf8")
|
|
82201
82241
|
};
|
|
82202
82242
|
} catch {
|
|
82203
82243
|
return `cannot read --body-file ${file}`;
|
|
@@ -82871,7 +82911,7 @@ __export(exports_git, {
|
|
|
82871
82911
|
run: () => run14
|
|
82872
82912
|
});
|
|
82873
82913
|
import { readFileSync as readFileSync22 } from "node:fs";
|
|
82874
|
-
import
|
|
82914
|
+
import path54 from "node:path";
|
|
82875
82915
|
function kindHint(cwd, kind) {
|
|
82876
82916
|
let kinds = [...BRANCH_KINDS];
|
|
82877
82917
|
try {
|
|
@@ -82975,7 +83015,7 @@ function commitMessage(parsed, io) {
|
|
|
82975
83015
|
|
|
82976
83016
|
`);
|
|
82977
83017
|
try {
|
|
82978
|
-
return file === "-" ? readFileSync22(0, "utf8") : readFileSync22(
|
|
83018
|
+
return file === "-" ? readFileSync22(0, "utf8") : readFileSync22(path54.resolve(io.cwd, file), "utf8");
|
|
82979
83019
|
} catch (error) {
|
|
82980
83020
|
return {
|
|
82981
83021
|
error: `cannot read -F ${file}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -84381,8 +84421,8 @@ var init_stack2 = __esm(() => {
|
|
|
84381
84421
|
|
|
84382
84422
|
// packages/workit-core/src/fanout-worktree.ts
|
|
84383
84423
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
84384
|
-
import
|
|
84385
|
-
import
|
|
84424
|
+
import fs31 from "node:fs";
|
|
84425
|
+
import path55 from "node:path";
|
|
84386
84426
|
function rowSample(lines) {
|
|
84387
84427
|
const out = [];
|
|
84388
84428
|
let bytes = 0;
|
|
@@ -84442,7 +84482,7 @@ function adminDir(worktree) {
|
|
|
84442
84482
|
const file = dir.stdout.trim();
|
|
84443
84483
|
let token = null;
|
|
84444
84484
|
try {
|
|
84445
|
-
token =
|
|
84485
|
+
token = fs31.readFileSync(path55.join(file, TOKEN_FILE), "utf8").trim() || null;
|
|
84446
84486
|
} catch {
|
|
84447
84487
|
token = null;
|
|
84448
84488
|
}
|
|
@@ -84450,7 +84490,7 @@ function adminDir(worktree) {
|
|
|
84450
84490
|
const stat = worktreeDeps.stat(file);
|
|
84451
84491
|
return {
|
|
84452
84492
|
path: file,
|
|
84453
|
-
id:
|
|
84493
|
+
id: path55.basename(file),
|
|
84454
84494
|
ino: stat.ino.toString(),
|
|
84455
84495
|
token,
|
|
84456
84496
|
birthMs: stat.birthtimeNs > 0n ? Number(stat.birthtimeMs) : null,
|
|
@@ -84466,7 +84506,7 @@ function markAdminDir(worktree) {
|
|
|
84466
84506
|
return null;
|
|
84467
84507
|
const token = randomBytes5(16).toString("hex");
|
|
84468
84508
|
try {
|
|
84469
|
-
|
|
84509
|
+
fs31.writeFileSync(path55.join(admin.path, TOKEN_FILE), `${token}
|
|
84470
84510
|
`);
|
|
84471
84511
|
} catch {
|
|
84472
84512
|
return null;
|
|
@@ -84481,25 +84521,25 @@ function excludeScratch(cwd) {
|
|
|
84481
84521
|
const common = gitCommonDir(cwd);
|
|
84482
84522
|
if (!common)
|
|
84483
84523
|
return;
|
|
84484
|
-
const file =
|
|
84524
|
+
const file = path55.join(common, "info", "exclude");
|
|
84485
84525
|
let text = "";
|
|
84486
84526
|
try {
|
|
84487
|
-
text =
|
|
84527
|
+
text = fs31.readFileSync(file, "utf8");
|
|
84488
84528
|
} catch {
|
|
84489
84529
|
text = "";
|
|
84490
84530
|
}
|
|
84491
84531
|
if (text.split(/\r?\n/u).includes(EXCLUDE_LINE))
|
|
84492
84532
|
return;
|
|
84493
|
-
|
|
84494
|
-
|
|
84533
|
+
fs31.mkdirSync(path55.dirname(file), { recursive: true });
|
|
84534
|
+
fs31.appendFileSync(file, `${text && !text.endsWith(`
|
|
84495
84535
|
`) ? `
|
|
84496
84536
|
` : ""}# workit fanout: per-worker scratch dirs
|
|
84497
84537
|
${EXCLUDE_LINE}
|
|
84498
84538
|
`);
|
|
84499
84539
|
}
|
|
84500
84540
|
function ensureScratch(worktree) {
|
|
84501
|
-
const scratch =
|
|
84502
|
-
|
|
84541
|
+
const scratch = path55.join(worktree, SCRATCH_DIR);
|
|
84542
|
+
fs31.mkdirSync(scratch, { recursive: true });
|
|
84503
84543
|
return scratch;
|
|
84504
84544
|
}
|
|
84505
84545
|
function createSliceWorktree(cwd, plan, input) {
|
|
@@ -84543,8 +84583,8 @@ function createSliceWorktree(cwd, plan, input) {
|
|
|
84543
84583
|
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})`);
|
|
84544
84584
|
let dirExisted = false;
|
|
84545
84585
|
try {
|
|
84546
|
-
const stat =
|
|
84547
|
-
if (!stat.isDirectory() ||
|
|
84586
|
+
const stat = fs31.statSync(target);
|
|
84587
|
+
if (!stat.isDirectory() || fs31.readdirSync(target).length > 0)
|
|
84548
84588
|
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`);
|
|
84549
84589
|
dirExisted = true;
|
|
84550
84590
|
} catch (error) {
|
|
@@ -84626,7 +84666,7 @@ function releaseSliceWorktree(cwd, plan, input) {
|
|
|
84626
84666
|
notes: []
|
|
84627
84667
|
};
|
|
84628
84668
|
if (index < 0) {
|
|
84629
|
-
if (
|
|
84669
|
+
if (fs31.existsSync(target))
|
|
84630
84670
|
return fanoutFail("blocked", `${target} is not a worktree of this repository; nothing was removed`, "remove it yourself once you know what it holds");
|
|
84631
84671
|
out.notes.push(`no worktree at ${target}; nothing to release`);
|
|
84632
84672
|
return { ok: true, data: out };
|
|
@@ -84688,7 +84728,7 @@ function releaseSliceWorktree(cwd, plan, input) {
|
|
|
84688
84728
|
`)[0]}`, entry.locked ? `git worktree unlock ${entry.path}, then release again` : undefined, { ...out });
|
|
84689
84729
|
out.removed = true;
|
|
84690
84730
|
if (made.dirExisted === true)
|
|
84691
|
-
|
|
84731
|
+
fs31.mkdirSync(entry.path, { recursive: true });
|
|
84692
84732
|
if (out.unpushed)
|
|
84693
84733
|
out.notes.push(`${slice.branch} is kept with ${out.unpushed} commit(s) not on the remote`);
|
|
84694
84734
|
return { ok: true, data: out };
|
|
@@ -84716,32 +84756,32 @@ function unpushedCount(cwd, branch) {
|
|
|
84716
84756
|
return count.ok ? Number(count.stdout.trim()) : null;
|
|
84717
84757
|
}
|
|
84718
84758
|
function removeScratch(worktree) {
|
|
84719
|
-
const scratch =
|
|
84759
|
+
const scratch = path55.join(worktree, SCRATCH_DIR);
|
|
84720
84760
|
let stat;
|
|
84721
84761
|
try {
|
|
84722
|
-
stat =
|
|
84762
|
+
stat = fs31.lstatSync(scratch);
|
|
84723
84763
|
} catch {
|
|
84724
84764
|
return;
|
|
84725
84765
|
}
|
|
84726
84766
|
if (stat.isSymbolicLink() || !stat.isDirectory())
|
|
84727
|
-
|
|
84767
|
+
fs31.unlinkSync(scratch);
|
|
84728
84768
|
else
|
|
84729
|
-
|
|
84769
|
+
fs31.rmSync(scratch, { recursive: true, force: true, maxRetries: 2 });
|
|
84730
84770
|
}
|
|
84731
84771
|
var SLOW, SCRATCH_DIR = ".workit-scratch", EXCLUDE_LINE, DIRTY_ROW_BYTES = 2000, canonical2 = (target) => {
|
|
84732
84772
|
try {
|
|
84733
|
-
return
|
|
84773
|
+
return fs31.realpathSync.native(target);
|
|
84734
84774
|
} catch {
|
|
84735
|
-
return
|
|
84775
|
+
return path55.resolve(target);
|
|
84736
84776
|
}
|
|
84737
84777
|
}, samePath = (a, b) => {
|
|
84738
84778
|
const left = canonical2(a);
|
|
84739
84779
|
const right = canonical2(b);
|
|
84740
84780
|
return process.platform === "win32" || process.platform === "darwin" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
84741
84781
|
}, inside3 = (child, parent) => {
|
|
84742
|
-
const relative =
|
|
84743
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
84744
|
-
}, slicePath = (cwd, slice) =>
|
|
84782
|
+
const relative = path55.relative(canonical2(parent), canonical2(child));
|
|
84783
|
+
return relative === "" || !relative.startsWith("..") && !path55.isAbsolute(relative);
|
|
84784
|
+
}, slicePath = (cwd, slice) => path55.isAbsolute(slice.worktree) ? slice.worktree : path55.resolve(mainCheckout(cwd), slice.worktree), CLOCK_SLACK_MS = 2000, TOKEN_FILE = "workit-fanout-token", worktreeDeps, worktreeFailed = (stderr) => fanoutFail("failed", `git worktree add failed: ${stderr.trim().split(`
|
|
84745
84785
|
`)[0] || "unknown error"}`);
|
|
84746
84786
|
var init_fanout_worktree = __esm(() => {
|
|
84747
84787
|
init_ops();
|
|
@@ -84751,7 +84791,7 @@ var init_fanout_worktree = __esm(() => {
|
|
|
84751
84791
|
SLOW = GIT_TIMEOUTS.worktree;
|
|
84752
84792
|
EXCLUDE_LINE = `/${SCRATCH_DIR}/`;
|
|
84753
84793
|
worktreeDeps = {
|
|
84754
|
-
stat: (file) =>
|
|
84794
|
+
stat: (file) => fs31.statSync(file, { bigint: true })
|
|
84755
84795
|
};
|
|
84756
84796
|
});
|
|
84757
84797
|
|
|
@@ -85565,8 +85605,8 @@ var exports_fanout = {};
|
|
|
85565
85605
|
__export(exports_fanout, {
|
|
85566
85606
|
run: () => run18
|
|
85567
85607
|
});
|
|
85568
|
-
import
|
|
85569
|
-
import
|
|
85608
|
+
import fs32 from "node:fs";
|
|
85609
|
+
import path56 from "node:path";
|
|
85570
85610
|
function forgeFor(io, offline) {
|
|
85571
85611
|
if (offline)
|
|
85572
85612
|
return { forge: null, error: "--offline" };
|
|
@@ -85627,10 +85667,10 @@ function plan2(argv, io) {
|
|
|
85627
85667
|
return usage3(io, "pass --trunk or --track, not both (--track picks the trunk)", PLAN_USAGE2);
|
|
85628
85668
|
if (flags.positionals.length !== 1)
|
|
85629
85669
|
return usage3(io, flags.positionals.length ? `unexpected argument ${flags.positionals[1]}` : "missing <plan.json>", PLAN_USAGE2);
|
|
85630
|
-
const file =
|
|
85670
|
+
const file = path56.resolve(io.cwd, flags.positionals[0]);
|
|
85631
85671
|
let raw;
|
|
85632
85672
|
try {
|
|
85633
|
-
raw = JSON.parse(
|
|
85673
|
+
raw = JSON.parse(fs32.readFileSync(file, "utf8"));
|
|
85634
85674
|
} catch (error) {
|
|
85635
85675
|
return usage3(io, `cannot read ${file} as JSON: ${error.message}`, PLAN_USAGE2);
|
|
85636
85676
|
}
|
|
@@ -86046,6 +86086,10 @@ async function standing(io, values, args) {
|
|
|
86046
86086
|
const [action, ...rest] = args;
|
|
86047
86087
|
if (action !== "add" && action !== "list" && action !== "clear")
|
|
86048
86088
|
return emit(io, fail2("invalid_input", action ? `unknown standing action "${action}"` : "missing add, list or clear", { unblock: STANDING_USAGE }));
|
|
86089
|
+
if ((values.stop || values.clear) && action !== "add")
|
|
86090
|
+
return usage4(io, `--stop and --clear go with standing add, not standing ${action}`);
|
|
86091
|
+
if (values.stop && values.clear)
|
|
86092
|
+
return usage4(io, "pass --stop or --clear, not both");
|
|
86049
86093
|
const target = standingFanout(io, values);
|
|
86050
86094
|
if (target instanceof Error)
|
|
86051
86095
|
return emit(io, fail2("invalid_input", target.message, { unblock: STANDING_USAGE }));
|
|
@@ -86080,13 +86124,18 @@ async function standing(io, values, args) {
|
|
|
86080
86124
|
return emit(io, fail2("not_found", `no fanout plan named ${fanout}`, {
|
|
86081
86125
|
unblock: "workit fanout plan <plan.json> first, or name an existing plan with --fanout"
|
|
86082
86126
|
}));
|
|
86127
|
+
if (action === "add" && values.clear) {
|
|
86128
|
+
if (rest.length)
|
|
86129
|
+
return usage4(io, `unexpected argument: ${rest[0]}`);
|
|
86130
|
+
return fromResult(io, liftStop(context, { fanout, lead, leads }), (rows) => `lifted the stop line for fanout ${fanout} (cleared ${rows.map((row) => row.target).join(", ")}); running workers are told on their next tool call`);
|
|
86131
|
+
}
|
|
86083
86132
|
if (action === "add")
|
|
86084
|
-
return fromResult(io, recordStanding(context, { fanout, lead, what: rest.join(" ") }), (row) => `recorded standing order ${row.id} for fanout ${fanout}`);
|
|
86133
|
+
return fromResult(io, recordStanding(context, { fanout, lead, what: rest.join(" "), stop: values.stop === true }), (row) => row.stop ? `recorded stop line ${row.id} for fanout ${fanout}; running workers stop and report on their next tool call` : `recorded standing order ${row.id} for fanout ${fanout}; running workers get it on their next tool call`);
|
|
86085
86134
|
if (rest.length > 1)
|
|
86086
86135
|
return usage4(io, `unexpected argument: ${rest[1]}`);
|
|
86087
86136
|
return fromResult(io, clearStanding(context, { fanout, lead, leads, target: rest[0] ?? null }), (row) => row.target ? `cleared standing order ${row.target} for fanout ${fanout}` : `cleared every standing order for fanout ${fanout}`);
|
|
86088
86137
|
}
|
|
86089
|
-
var USAGE11 = "workit ledger decision|ruling|verdict|standing|list|check ... (workit help ledger for the grammar)", STANDING_USAGE = 'workit ledger standing add "<order>" | list | clear [<id>] [--fanout <name>] [--json]', OPTIONS, SESSION_SAFE2, ROLE_SAFE, actorFor = (io, values) => {
|
|
86138
|
+
var USAGE11 = "workit ledger decision|ruling|verdict|standing|list|check ... (workit help ledger for the grammar)", STANDING_USAGE = 'workit ledger standing add "<order>" | add --stop ["<note>"] | add --clear | list | clear [<id>] [--fanout <name>] [--json]', OPTIONS, SESSION_SAFE2, ROLE_SAFE, actorFor = (io, values) => {
|
|
86090
86139
|
const actor = actorFromEnv(io.env);
|
|
86091
86140
|
if (values.session !== undefined && values.as !== undefined)
|
|
86092
86141
|
return new Error("pass --session or --as, not both");
|
|
@@ -86183,6 +86232,8 @@ var init_ledger2 = __esm(() => {
|
|
|
86183
86232
|
token: { type: "string" },
|
|
86184
86233
|
as: { type: "string" },
|
|
86185
86234
|
fanout: { type: "string" },
|
|
86235
|
+
stop: { type: "boolean" },
|
|
86236
|
+
clear: { type: "boolean" },
|
|
86186
86237
|
json: { type: "boolean" }
|
|
86187
86238
|
};
|
|
86188
86239
|
SESSION_SAFE2 = /^[A-Za-z0-9_.:@/+-]{1,128}$/;
|
|
@@ -101150,7 +101201,7 @@ var init_ast = __esm(() => {
|
|
|
101150
101201
|
|
|
101151
101202
|
// packages/workit-cli/src/test-audit/rules.ts
|
|
101152
101203
|
import { builtinModules } from "node:module";
|
|
101153
|
-
import
|
|
101204
|
+
import path57 from "node:path";
|
|
101154
101205
|
function testCallee(call) {
|
|
101155
101206
|
let callee = call.callee;
|
|
101156
101207
|
if (callee.type === "CallExpression")
|
|
@@ -101643,12 +101694,12 @@ function checkConstantsOnly(ctx, emit) {
|
|
|
101643
101694
|
}
|
|
101644
101695
|
function checkOverMocking(ctx, emit) {
|
|
101645
101696
|
const { program } = ctx.parsed;
|
|
101646
|
-
const unit =
|
|
101697
|
+
const unit = path57.basename(ctx.file).replace(/\.(?:[cm]?[jt]sx?)$/, "").replace(/\.(?:test|spec)$/, "");
|
|
101647
101698
|
const mocked = find2(program, (node) => node.type === "CallExpression" && MODULE_MOCK.test(calleeName(node.callee) ?? "") && node.arguments[0]?.type === "StringLiteral");
|
|
101648
101699
|
const internal = mocked.filter((call) => /^(?:\.|@\/|~\/)/.test(call.arguments[0].value));
|
|
101649
101700
|
for (const call of mocked) {
|
|
101650
101701
|
const spec = call.arguments[0].value;
|
|
101651
|
-
const base =
|
|
101702
|
+
const base = path57.basename(spec.replace(/\/index(?:\.[cm]?[jt]sx?)?$/, "")).replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
101652
101703
|
if (base === unit)
|
|
101653
101704
|
emit({
|
|
101654
101705
|
rule: "over-mocking",
|
|
@@ -102038,7 +102089,7 @@ var init_rules = __esm(() => {
|
|
|
102038
102089
|
// packages/workit-cli/src/test-audit/audit.ts
|
|
102039
102090
|
import { spawnSync as spawnSync28 } from "node:child_process";
|
|
102040
102091
|
import { existsSync as existsSync20, readdirSync as readdirSync10, readFileSync as readFileSync23, statSync as statSync8 } from "node:fs";
|
|
102041
|
-
import
|
|
102092
|
+
import path58 from "node:path";
|
|
102042
102093
|
function git7(cwd, args) {
|
|
102043
102094
|
const run = spawnSync28("git", ["-c", "core.quotepath=off", ...args], {
|
|
102044
102095
|
cwd,
|
|
@@ -102051,7 +102102,7 @@ function walkTests(dir, out) {
|
|
|
102051
102102
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
102052
102103
|
if (entry.name.startsWith(".") && entry.name !== "." && entry.isDirectory())
|
|
102053
102104
|
continue;
|
|
102054
|
-
const full =
|
|
102105
|
+
const full = path58.join(dir, entry.name);
|
|
102055
102106
|
if (entry.isDirectory()) {
|
|
102056
102107
|
if (!SKIP_DIRS.has(entry.name))
|
|
102057
102108
|
walkTests(full, out);
|
|
@@ -102063,7 +102114,7 @@ function expandPaths(cwd, inputs) {
|
|
|
102063
102114
|
const files = [];
|
|
102064
102115
|
const missing = [];
|
|
102065
102116
|
for (const input of inputs.length > 0 ? inputs : ["."]) {
|
|
102066
|
-
const full =
|
|
102117
|
+
const full = path58.resolve(cwd, input);
|
|
102067
102118
|
if (!existsSync20(full))
|
|
102068
102119
|
missing.push(input);
|
|
102069
102120
|
else if (statSync8(full).isDirectory())
|
|
@@ -102100,11 +102151,11 @@ function changedLines(cwd, base) {
|
|
|
102100
102151
|
for (let offset = 0;offset < count; offset += 1)
|
|
102101
102152
|
lines.add(start + offset);
|
|
102102
102153
|
}
|
|
102103
|
-
changed.set(
|
|
102154
|
+
changed.set(path58.join(root, file), lines);
|
|
102104
102155
|
}
|
|
102105
102156
|
const untracked = git7(root, ["ls-files", "--others", "--exclude-standard", "-z"]);
|
|
102106
102157
|
for (const file of untracked.stdout.split("\x00").filter(Boolean))
|
|
102107
|
-
changed.set(
|
|
102158
|
+
changed.set(path58.join(root, file), "all");
|
|
102108
102159
|
return changed;
|
|
102109
102160
|
}
|
|
102110
102161
|
function auditFiles(files, display) {
|
|
@@ -102166,7 +102217,7 @@ function auditFiles(files, display) {
|
|
|
102166
102217
|
durationMs: Math.round(performance.now() - started)
|
|
102167
102218
|
};
|
|
102168
102219
|
}
|
|
102169
|
-
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(
|
|
102220
|
+
var TEST_FILE, CODE_FILE, SKIP_DIRS, toPosix = (file) => file.split(path58.sep).join("/"), SEVERITY_ORDER, ruleIds;
|
|
102170
102221
|
var init_audit = __esm(() => {
|
|
102171
102222
|
init_ast();
|
|
102172
102223
|
init_rules();
|
|
@@ -102196,7 +102247,7 @@ import {
|
|
|
102196
102247
|
copyFileSync as copyFileSync6
|
|
102197
102248
|
} from "node:fs";
|
|
102198
102249
|
import os18 from "node:os";
|
|
102199
|
-
import
|
|
102250
|
+
import path59 from "node:path";
|
|
102200
102251
|
function mutantsFor(source, file, lines) {
|
|
102201
102252
|
const parsed = parseSource(source, file);
|
|
102202
102253
|
const out = [];
|
|
@@ -102269,7 +102320,7 @@ function relatedTests(source, testFiles) {
|
|
|
102269
102320
|
for (const match of text.matchAll(SPECIFIER)) {
|
|
102270
102321
|
const spec = match[1];
|
|
102271
102322
|
if (spec.startsWith(".")) {
|
|
102272
|
-
if (stripExt(
|
|
102323
|
+
if (stripExt(path59.posix.join(path59.posix.dirname(file), spec)) === target)
|
|
102273
102324
|
return true;
|
|
102274
102325
|
} else if (spec.includes("/") && stripExt(spec).split("/").slice(-2).join("/") === tail)
|
|
102275
102326
|
return true;
|
|
@@ -102289,12 +102340,12 @@ function removeStaleCopies(tmp = os18.tmpdir()) {
|
|
|
102289
102340
|
for (const name of names) {
|
|
102290
102341
|
if (!name.startsWith(TEMP_PREFIX))
|
|
102291
102342
|
continue;
|
|
102292
|
-
const dir =
|
|
102343
|
+
const dir = path59.join(tmp, name);
|
|
102293
102344
|
try {
|
|
102294
102345
|
const stat = lstatSync8(dir);
|
|
102295
102346
|
if (!stat.isDirectory() || uid !== undefined && stat.uid !== uid)
|
|
102296
102347
|
continue;
|
|
102297
|
-
const pid = Number(readFileSync24(
|
|
102348
|
+
const pid = Number(readFileSync24(path59.join(dir, PID_FILE), "utf8"));
|
|
102298
102349
|
if (Number.isInteger(pid) && pid > 0 && alive(pid))
|
|
102299
102350
|
continue;
|
|
102300
102351
|
} catch (error) {
|
|
@@ -102311,8 +102362,8 @@ function removeStaleCopies(tmp = os18.tmpdir()) {
|
|
|
102311
102362
|
function linkNodeModules(origin, target, repo, copy) {
|
|
102312
102363
|
mkdirSync10(target, { recursive: true });
|
|
102313
102364
|
for (const entry of readdirSync11(origin, { withFileTypes: true })) {
|
|
102314
|
-
const from =
|
|
102315
|
-
const to =
|
|
102365
|
+
const from = path59.join(origin, entry.name);
|
|
102366
|
+
const to = path59.join(target, entry.name);
|
|
102316
102367
|
if (entry.name.startsWith("@") && entry.isDirectory()) {
|
|
102317
102368
|
linkNodeModules(from, to, repo, copy);
|
|
102318
102369
|
continue;
|
|
@@ -102328,9 +102379,9 @@ function linkNodeModules(origin, target, repo, copy) {
|
|
|
102328
102379
|
} catch {
|
|
102329
102380
|
continue;
|
|
102330
102381
|
}
|
|
102331
|
-
const relative =
|
|
102332
|
-
if (!relative.startsWith("..") && !
|
|
102333
|
-
symlinkSync(
|
|
102382
|
+
const relative = path59.relative(repo, real);
|
|
102383
|
+
if (!relative.startsWith("..") && !path59.isAbsolute(relative) && !relative.split(path59.sep).includes("node_modules")) {
|
|
102384
|
+
symlinkSync(path59.join(copy, relative), to, "junction");
|
|
102334
102385
|
continue;
|
|
102335
102386
|
}
|
|
102336
102387
|
}
|
|
@@ -102346,7 +102397,7 @@ function copySymlink(repo, tree, from, to) {
|
|
|
102346
102397
|
}
|
|
102347
102398
|
const realRepo = realpathSync9(repo);
|
|
102348
102399
|
if (real && inside4(realRepo, real)) {
|
|
102349
|
-
symlinkSync(
|
|
102400
|
+
symlinkSync(path59.relative(path59.dirname(to), path59.join(tree, path59.relative(realRepo, real))), to);
|
|
102350
102401
|
return;
|
|
102351
102402
|
}
|
|
102352
102403
|
if (real && statSync9(real).isFile())
|
|
@@ -102355,10 +102406,10 @@ function copySymlink(repo, tree, from, to) {
|
|
|
102355
102406
|
symlinkSync(readlinkSync3(from), to);
|
|
102356
102407
|
}
|
|
102357
102408
|
function writeInside(copy, file, content) {
|
|
102358
|
-
const target =
|
|
102409
|
+
const target = path59.join(copy, file);
|
|
102359
102410
|
try {
|
|
102360
102411
|
const stat = lstatSync8(target);
|
|
102361
|
-
if (!stat.isFile() || !inside4(realpathSync9(copy), realpathSync9(
|
|
102412
|
+
if (!stat.isFile() || !inside4(realpathSync9(copy), realpathSync9(path59.dirname(target))))
|
|
102362
102413
|
return false;
|
|
102363
102414
|
} catch {
|
|
102364
102415
|
return false;
|
|
@@ -102369,9 +102420,9 @@ function writeInside(copy, file, content) {
|
|
|
102369
102420
|
return true;
|
|
102370
102421
|
}
|
|
102371
102422
|
function copyWorkingTree(repo) {
|
|
102372
|
-
const dir = mkdtempSync4(
|
|
102373
|
-
writeFileSync11(
|
|
102374
|
-
const tree =
|
|
102423
|
+
const dir = mkdtempSync4(path59.join(os18.tmpdir(), TEMP_PREFIX));
|
|
102424
|
+
writeFileSync11(path59.join(dir, PID_FILE), String(process.pid));
|
|
102425
|
+
const tree = path59.join(dir, "tree");
|
|
102375
102426
|
const head = git7(repo, ["rev-parse", "--verify", "--quiet", "HEAD"]).stdout.trim();
|
|
102376
102427
|
if (head && git7(dir, ["clone", "-q", "--shared", "--no-checkout", repo, tree]).ok) {
|
|
102377
102428
|
const branch = git7(repo, ["symbolic-ref", "--quiet", "--short", "HEAD"]).stdout.trim();
|
|
@@ -102388,29 +102439,29 @@ function copyWorkingTree(repo) {
|
|
|
102388
102439
|
for (const relative of listed) {
|
|
102389
102440
|
if (!relative)
|
|
102390
102441
|
continue;
|
|
102391
|
-
const from =
|
|
102442
|
+
const from = path59.join(repo, relative);
|
|
102392
102443
|
let stat;
|
|
102393
102444
|
try {
|
|
102394
102445
|
stat = lstatSync8(from);
|
|
102395
102446
|
} catch {
|
|
102396
102447
|
continue;
|
|
102397
102448
|
}
|
|
102398
|
-
const to =
|
|
102399
|
-
mkdirSync10(
|
|
102449
|
+
const to = path59.join(tree, relative);
|
|
102450
|
+
mkdirSync10(path59.dirname(to), { recursive: true });
|
|
102400
102451
|
if (stat.isSymbolicLink())
|
|
102401
102452
|
copySymlink(repo, tree, from, to);
|
|
102402
102453
|
else if (stat.isFile())
|
|
102403
102454
|
copyFileSync6(from, to);
|
|
102404
|
-
let parent =
|
|
102455
|
+
let parent = path59.dirname(relative);
|
|
102405
102456
|
while (parent !== "." && !dirs.has(parent)) {
|
|
102406
102457
|
dirs.add(parent);
|
|
102407
|
-
parent =
|
|
102458
|
+
parent = path59.dirname(parent);
|
|
102408
102459
|
}
|
|
102409
102460
|
}
|
|
102410
102461
|
for (const parent of dirs) {
|
|
102411
|
-
const modules =
|
|
102412
|
-
if (existsSync21(modules) && !existsSync21(
|
|
102413
|
-
linkNodeModules(modules,
|
|
102462
|
+
const modules = path59.join(repo, parent, "node_modules");
|
|
102463
|
+
if (existsSync21(modules) && !existsSync21(path59.join(tree, parent, "node_modules")))
|
|
102464
|
+
linkNodeModules(modules, path59.join(tree, parent, "node_modules"), repo, tree);
|
|
102414
102465
|
}
|
|
102415
102466
|
return { dir, tree };
|
|
102416
102467
|
}
|
|
@@ -102449,14 +102500,14 @@ async function runMutation(options) {
|
|
|
102449
102500
|
const tracked = git7(repo, ["ls-files", "-co", "--exclude-standard", "-z"]).stdout.split("\x00").filter(Boolean);
|
|
102450
102501
|
const testFiles = tracked.filter((file) => TEST_FILE.test(file)).map((file) => {
|
|
102451
102502
|
try {
|
|
102452
|
-
return { file, text: readFileSync24(
|
|
102503
|
+
return { file, text: readFileSync24(path59.join(repo, file), "utf8") };
|
|
102453
102504
|
} catch {
|
|
102454
102505
|
return { file, text: "" };
|
|
102455
102506
|
}
|
|
102456
102507
|
});
|
|
102457
102508
|
const candidates = [];
|
|
102458
102509
|
for (const [absolute, lines] of [...options.changed].toSorted(([a], [b]) => a.localeCompare(b))) {
|
|
102459
|
-
const relative = toPosix(
|
|
102510
|
+
const relative = toPosix(path59.relative(repo, absolute));
|
|
102460
102511
|
if (!CODE_FILE.test(relative) || TEST_FILE.test(relative) || relative.endsWith(".d.ts"))
|
|
102461
102512
|
continue;
|
|
102462
102513
|
if (NOT_SOURCE.test(relative) || !existsSync21(absolute))
|
|
@@ -102470,9 +102521,9 @@ async function runMutation(options) {
|
|
|
102470
102521
|
for (const mutant of mutants)
|
|
102471
102522
|
if (!related.has(mutant.file))
|
|
102472
102523
|
related.set(mutant.file, relatedTests(mutant.file, testFiles));
|
|
102473
|
-
const cwdRelative =
|
|
102524
|
+
const cwdRelative = path59.relative(repo, options.cwd);
|
|
102474
102525
|
const asArg = (file) => {
|
|
102475
|
-
const relative = toPosix(
|
|
102526
|
+
const relative = toPosix(path59.relative(cwdRelative, file));
|
|
102476
102527
|
return shellQuote(relative.startsWith(".") ? relative : `./${relative}`);
|
|
102477
102528
|
};
|
|
102478
102529
|
const commandFor = (tests) => options.command.replaceAll("{files}", () => tests.map(asArg).join(" "));
|
|
@@ -102507,7 +102558,7 @@ async function runMutation(options) {
|
|
|
102507
102558
|
return finish3(options, 0, results, counts, started);
|
|
102508
102559
|
removeStaleCopies();
|
|
102509
102560
|
const { dir: copyDir, tree: copy } = copyWorkingTree(repo);
|
|
102510
|
-
const copyCwd =
|
|
102561
|
+
const copyCwd = path59.join(copy, cwdRelative);
|
|
102511
102562
|
let current = null;
|
|
102512
102563
|
const restore = () => {
|
|
102513
102564
|
if (current)
|
|
@@ -102542,7 +102593,7 @@ async function runMutation(options) {
|
|
|
102542
102593
|
record({ ...mutant, status: "skipped", durationMs: 0, tests, reason: "budget" });
|
|
102543
102594
|
continue;
|
|
102544
102595
|
}
|
|
102545
|
-
const original = readFileSync24(
|
|
102596
|
+
const original = readFileSync24(path59.join(copy, mutant.file), "utf8");
|
|
102546
102597
|
const mutated = original.slice(0, mutant.start) + mutant.replacement + original.slice(mutant.end);
|
|
102547
102598
|
current = { file: mutant.file, original };
|
|
102548
102599
|
if (!writeInside(copy, mutant.file, mutated)) {
|
|
@@ -102599,8 +102650,8 @@ var NOT_SOURCE, FLIPS, isStringy = (node) => node.type === "StringLiteral" || no
|
|
|
102599
102650
|
return error.code === "EPERM";
|
|
102600
102651
|
}
|
|
102601
102652
|
}, inside4 = (root, file) => {
|
|
102602
|
-
const relative =
|
|
102603
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
102653
|
+
const relative = path59.relative(root, file);
|
|
102654
|
+
return relative === "" || !relative.startsWith("..") && !path59.isAbsolute(relative);
|
|
102604
102655
|
}, active, killTree = (child) => {
|
|
102605
102656
|
try {
|
|
102606
102657
|
if (child.pid && process.platform !== "win32")
|
|
@@ -102649,7 +102700,7 @@ __export(exports_test_audit, {
|
|
|
102649
102700
|
run: () => run20
|
|
102650
102701
|
});
|
|
102651
102702
|
import { existsSync as existsSync22 } from "node:fs";
|
|
102652
|
-
import
|
|
102703
|
+
import path60 from "node:path";
|
|
102653
102704
|
function parse7(argv) {
|
|
102654
102705
|
const options = {
|
|
102655
102706
|
paths: [],
|
|
@@ -102753,8 +102804,8 @@ async function run20(argv, io) {
|
|
|
102753
102804
|
return emit(io, fail2("invalid_input", `${options}
|
|
102754
102805
|
usage: ${USAGE12}`));
|
|
102755
102806
|
const top = git7(io.cwd, ["rev-parse", "--show-toplevel"]);
|
|
102756
|
-
const repo = top.ok ?
|
|
102757
|
-
const display = (file) => toPosix(
|
|
102807
|
+
const repo = top.ok ? path60.resolve(top.stdout.trim()) : null;
|
|
102808
|
+
const display = (file) => toPosix(path60.relative(io.cwd, file) || file);
|
|
102758
102809
|
let base = null;
|
|
102759
102810
|
let changed = null;
|
|
102760
102811
|
if (options.diff || options.mutate) {
|
|
@@ -102893,7 +102944,7 @@ __export(exports_youtrack, {
|
|
|
102893
102944
|
run: () => run22
|
|
102894
102945
|
});
|
|
102895
102946
|
import { readFileSync as readFileSync25 } from "node:fs";
|
|
102896
|
-
import
|
|
102947
|
+
import path61 from "node:path";
|
|
102897
102948
|
async function run22(argv, io) {
|
|
102898
102949
|
const [sub, ...rest] = argv;
|
|
102899
102950
|
if (sub !== "note" && sub !== "time" && sub !== "meeting")
|
|
@@ -102939,7 +102990,7 @@ async function run22(argv, io) {
|
|
|
102939
102990
|
let markdown = flags.values.markdown ?? "";
|
|
102940
102991
|
if (flags.values.file)
|
|
102941
102992
|
try {
|
|
102942
|
-
markdown = readFileSync25(
|
|
102993
|
+
markdown = readFileSync25(path61.resolve(io.cwd, flags.values.file), "utf8");
|
|
102943
102994
|
} catch (error) {
|
|
102944
102995
|
return usage3(io, `cannot read ${flags.values.file}: ${String(error)}`, USAGE14);
|
|
102945
102996
|
}
|
|
@@ -103008,7 +103059,7 @@ __export(exports_changelog, {
|
|
|
103008
103059
|
run: () => run23
|
|
103009
103060
|
});
|
|
103010
103061
|
import { readFileSync as readFileSync26 } from "node:fs";
|
|
103011
|
-
import
|
|
103062
|
+
import path62 from "node:path";
|
|
103012
103063
|
async function run23(argv, io) {
|
|
103013
103064
|
const [sub, ...rest] = argv;
|
|
103014
103065
|
if (sub !== "apply")
|
|
@@ -103054,7 +103105,7 @@ async function run23(argv, io) {
|
|
|
103054
103105
|
]);
|
|
103055
103106
|
}
|
|
103056
103107
|
var USAGE15 = "workit changelog apply (--entries <JSON|@file|-> | --normalize-only) [--path CHANGELOG.md] [--preview]", readEntries = (raw, cwd) => {
|
|
103057
|
-
const text = raw === "-" ? readFileSync26(0, "utf8") : raw.startsWith("@") ? readFileSync26(
|
|
103108
|
+
const text = raw === "-" ? readFileSync26(0, "utf8") : raw.startsWith("@") ? readFileSync26(path62.resolve(cwd, raw.slice(1)), "utf8") : raw;
|
|
103058
103109
|
return JSON.parse(text);
|
|
103059
103110
|
};
|
|
103060
103111
|
var init_changelog2 = __esm(() => {
|
|
@@ -103150,7 +103201,7 @@ var init_handoff = __esm(() => {
|
|
|
103150
103201
|
|
|
103151
103202
|
// packages/workit-cli/src/main.ts
|
|
103152
103203
|
init_package();
|
|
103153
|
-
import
|
|
103204
|
+
import path63 from "node:path";
|
|
103154
103205
|
|
|
103155
103206
|
// packages/workit-cli/src/verbs/registry.ts
|
|
103156
103207
|
var TASK_FAMILY_NAMES = [
|
|
@@ -103648,8 +103699,8 @@ var VERBS = [
|
|
|
103648
103699
|
{
|
|
103649
103700
|
name: "standing",
|
|
103650
103701
|
flagAliases: { name: "fanout" },
|
|
103651
|
-
usage: `workit ledger standing add "<order>" | standing list | standing clear [<id>] [--fanout <name>] [--supersedes <id>] [--session <id> [--token <t>] | --as <role>]`,
|
|
103652
|
-
summary: "The lead's standing orders for a fanout's workers"
|
|
103702
|
+
usage: `workit ledger standing add "<order>" | standing add --stop ["<note>"] | standing add --clear | standing list | standing clear [<id>] [--fanout <name>] [--supersedes <id>] [--session <id> [--token <t>] | --as <role>]`,
|
|
103703
|
+
summary: "The lead's standing orders for a fanout's workers; running workers get each change on their next tool call, and --stop tells them to stop and report"
|
|
103653
103704
|
},
|
|
103654
103705
|
{
|
|
103655
103706
|
name: "add",
|
|
@@ -103979,7 +104030,7 @@ var defaultIo = (json) => ({
|
|
|
103979
104030
|
});
|
|
103980
104031
|
async function main(argv, overrides = {}, options = {}) {
|
|
103981
104032
|
const parsed = parseGlobals(argv);
|
|
103982
|
-
const cwd =
|
|
104033
|
+
const cwd = path63.resolve(overrides.cwd ?? process.cwd(), parsed.cwd ?? ".");
|
|
103983
104034
|
const io = { ...defaultIo(parsed.json), ...overrides, json: parsed.json, cwd };
|
|
103984
104035
|
if (parsed.error)
|
|
103985
104036
|
return emit(io, fail2("invalid_input", parsed.error));
|