@brainervirus/workit-codex 8.36.0 → 8.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/launch-mcp.js
CHANGED
|
@@ -6621,14 +6621,14 @@ var require_dist = __commonJS(function(exports, module) {
|
|
|
6621
6621
|
});
|
|
6622
6622
|
|
|
6623
6623
|
// packages/workit-codex/scripts/launch-mcp.ts
|
|
6624
|
-
import { existsSync as
|
|
6625
|
-
import
|
|
6624
|
+
import { existsSync as existsSync12, realpathSync as realpathSync8, statSync as statSync4 } from "node:fs";
|
|
6625
|
+
import path29 from "node:path";
|
|
6626
6626
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
6627
6627
|
|
|
6628
6628
|
// packages/workit-core/src/core.ts
|
|
6629
6629
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
6630
6630
|
import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
6631
|
-
import
|
|
6631
|
+
import path23 from "node:path";
|
|
6632
6632
|
|
|
6633
6633
|
// packages/workit-core/src/core/task-contract.ts
|
|
6634
6634
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -19194,9 +19194,9 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
|
|
|
19194
19194
|
|
|
19195
19195
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
19196
19196
|
import { createHash as createHash10 } from "node:crypto";
|
|
19197
|
-
import * as
|
|
19197
|
+
import * as fs14 from "node:fs";
|
|
19198
19198
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
19199
|
-
import
|
|
19199
|
+
import path18 from "node:path";
|
|
19200
19200
|
|
|
19201
19201
|
// packages/workit-core/src/check-config.ts
|
|
19202
19202
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
@@ -19430,13 +19430,13 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
19430
19430
|
|
|
19431
19431
|
// packages/workit-core/src/core/policy/derive.ts
|
|
19432
19432
|
import { existsSync as existsSync5 } from "node:fs";
|
|
19433
|
-
import
|
|
19433
|
+
import path17 from "node:path";
|
|
19434
19434
|
|
|
19435
19435
|
// packages/workit-core/src/ledger.ts
|
|
19436
19436
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
19437
19437
|
import { createHash as createHash9, randomBytes as randomBytes3 } from "node:crypto";
|
|
19438
|
-
import
|
|
19439
|
-
import
|
|
19438
|
+
import fs13 from "node:fs";
|
|
19439
|
+
import path16 from "node:path";
|
|
19440
19440
|
|
|
19441
19441
|
// packages/workit-core/src/core/policy/lane.ts
|
|
19442
19442
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
@@ -20179,6 +20179,34 @@ function verdictDrift(cwd, input) {
|
|
|
20179
20179
|
return stale(lane.reasons[0] ?? `lane ${lane.lane}`, paths, lane.lane === "self");
|
|
20180
20180
|
}
|
|
20181
20181
|
|
|
20182
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
20183
|
+
import fs12 from "node:fs";
|
|
20184
|
+
import path15 from "node:path";
|
|
20185
|
+
var gitStoreDir = (cwd) => {
|
|
20186
|
+
try {
|
|
20187
|
+
for (let dir = path15.resolve(cwd);; dir = path15.dirname(dir)) {
|
|
20188
|
+
const dotGit = path15.join(dir, ".git");
|
|
20189
|
+
if (fs12.existsSync(dotGit)) {
|
|
20190
|
+
let gitDir = dotGit;
|
|
20191
|
+
if (fs12.statSync(dotGit).isFile()) {
|
|
20192
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs12.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
20193
|
+
if (!target)
|
|
20194
|
+
return null;
|
|
20195
|
+
gitDir = path15.resolve(dir, target);
|
|
20196
|
+
const common = path15.join(gitDir, "commondir");
|
|
20197
|
+
if (fs12.existsSync(common))
|
|
20198
|
+
gitDir = path15.resolve(gitDir, fs12.readFileSync(common, "utf8").trim());
|
|
20199
|
+
}
|
|
20200
|
+
return path15.join(gitDir, "workit");
|
|
20201
|
+
}
|
|
20202
|
+
if (path15.dirname(dir) === dir)
|
|
20203
|
+
return null;
|
|
20204
|
+
}
|
|
20205
|
+
} catch {
|
|
20206
|
+
return null;
|
|
20207
|
+
}
|
|
20208
|
+
};
|
|
20209
|
+
|
|
20182
20210
|
// packages/workit-core/src/ledger.ts
|
|
20183
20211
|
var LEDGER_VERSION = 1;
|
|
20184
20212
|
var MAX_LINE_BYTES = 4096;
|
|
@@ -20280,14 +20308,14 @@ function cleanRebase(cwd, range) {
|
|
|
20280
20308
|
return Boolean(tree) && tree === git4(cwd, ["rev-parse", "--verify", "-q", `${range.to}^{tree}`]);
|
|
20281
20309
|
}
|
|
20282
20310
|
function storeRoot(cwd) {
|
|
20283
|
-
const location = resolveStore(
|
|
20311
|
+
const location = resolveStore(path16.resolve(cwd));
|
|
20284
20312
|
if (location instanceof Error)
|
|
20285
20313
|
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");
|
|
20286
20314
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
20287
20315
|
}
|
|
20288
20316
|
function ledgerPath(cwd) {
|
|
20289
20317
|
const root = storeRoot(cwd);
|
|
20290
|
-
return root.ok ? { ok: true, value:
|
|
20318
|
+
return root.ok ? { ok: true, value: path16.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
20291
20319
|
}
|
|
20292
20320
|
var newId2 = () => `${Date.now().toString(36)}-${randomBytes3(6).toString("hex")}`;
|
|
20293
20321
|
var NETWORK_FS_TYPES = new Set([
|
|
@@ -20307,7 +20335,7 @@ var onNetworkFs = (dir) => {
|
|
|
20307
20335
|
if (process.platform !== "linux")
|
|
20308
20336
|
return false;
|
|
20309
20337
|
try {
|
|
20310
|
-
return isNetworkFsType(
|
|
20338
|
+
return isNetworkFsType(fs13.statfsSync(dir).type);
|
|
20311
20339
|
} catch {
|
|
20312
20340
|
return false;
|
|
20313
20341
|
}
|
|
@@ -20317,15 +20345,15 @@ var LOCK_STALE_MS = 30000;
|
|
|
20317
20345
|
var LOCK_OWNER = "owner";
|
|
20318
20346
|
var lockToken = (lock) => {
|
|
20319
20347
|
try {
|
|
20320
|
-
return
|
|
20348
|
+
return fs13.readFileSync(path16.join(lock, LOCK_OWNER), "utf8");
|
|
20321
20349
|
} catch {
|
|
20322
20350
|
return null;
|
|
20323
20351
|
}
|
|
20324
20352
|
};
|
|
20325
20353
|
var lockAgeMs = (lock) => {
|
|
20326
|
-
for (const target of [
|
|
20354
|
+
for (const target of [path16.join(lock, LOCK_OWNER), lock]) {
|
|
20327
20355
|
try {
|
|
20328
|
-
return Date.now() -
|
|
20356
|
+
return Date.now() - fs13.statSync(target).mtimeMs;
|
|
20329
20357
|
} catch {}
|
|
20330
20358
|
}
|
|
20331
20359
|
return null;
|
|
@@ -20333,14 +20361,14 @@ var lockAgeMs = (lock) => {
|
|
|
20333
20361
|
var ledgerLock = {
|
|
20334
20362
|
acquire(lock) {
|
|
20335
20363
|
try {
|
|
20336
|
-
|
|
20364
|
+
fs13.mkdirSync(lock);
|
|
20337
20365
|
} catch (error) {
|
|
20338
20366
|
if (error.code === "EEXIST")
|
|
20339
20367
|
return null;
|
|
20340
20368
|
throw error;
|
|
20341
20369
|
}
|
|
20342
20370
|
const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
|
|
20343
|
-
|
|
20371
|
+
fs13.writeFileSync(path16.join(lock, LOCK_OWNER), token);
|
|
20344
20372
|
return token;
|
|
20345
20373
|
},
|
|
20346
20374
|
release(lock, token) {
|
|
@@ -20348,35 +20376,35 @@ var ledgerLock = {
|
|
|
20348
20376
|
return false;
|
|
20349
20377
|
const tomb = `${lock}.release-${randomBytes3(6).toString("hex")}`;
|
|
20350
20378
|
try {
|
|
20351
|
-
|
|
20379
|
+
fs13.renameSync(lock, tomb);
|
|
20352
20380
|
} catch {
|
|
20353
20381
|
return false;
|
|
20354
20382
|
}
|
|
20355
20383
|
if (lockToken(tomb) !== token) {
|
|
20356
20384
|
try {
|
|
20357
|
-
|
|
20385
|
+
fs13.renameSync(tomb, lock);
|
|
20358
20386
|
} catch {}
|
|
20359
20387
|
return false;
|
|
20360
20388
|
}
|
|
20361
|
-
|
|
20389
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
20362
20390
|
return true;
|
|
20363
20391
|
},
|
|
20364
20392
|
token: lockToken,
|
|
20365
20393
|
reap(lock, observed) {
|
|
20366
20394
|
const tomb = `${lock}.reap-${randomBytes3(6).toString("hex")}`;
|
|
20367
20395
|
try {
|
|
20368
|
-
|
|
20396
|
+
fs13.renameSync(lock, tomb);
|
|
20369
20397
|
} catch {
|
|
20370
20398
|
return false;
|
|
20371
20399
|
}
|
|
20372
20400
|
if (lockToken(tomb) === observed) {
|
|
20373
|
-
|
|
20401
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
20374
20402
|
return true;
|
|
20375
20403
|
}
|
|
20376
20404
|
try {
|
|
20377
|
-
|
|
20405
|
+
fs13.renameSync(tomb, lock);
|
|
20378
20406
|
} catch {
|
|
20379
|
-
|
|
20407
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
20380
20408
|
}
|
|
20381
20409
|
return false;
|
|
20382
20410
|
}
|
|
@@ -20410,7 +20438,7 @@ var TAIL_BYTES = 64 * 1024;
|
|
|
20410
20438
|
var lastLine = (fd, size) => {
|
|
20411
20439
|
for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
|
|
20412
20440
|
const buffer = Buffer.alloc(span);
|
|
20413
|
-
|
|
20441
|
+
fs13.readSync(fd, buffer, 0, span, size - span);
|
|
20414
20442
|
const end = buffer.lastIndexOf(10);
|
|
20415
20443
|
if (end < 0) {
|
|
20416
20444
|
if (span === size)
|
|
@@ -20441,21 +20469,21 @@ var lastLine = (fd, size) => {
|
|
|
20441
20469
|
};
|
|
20442
20470
|
var tighten = (fd) => {
|
|
20443
20471
|
try {
|
|
20444
|
-
if ((
|
|
20445
|
-
|
|
20472
|
+
if ((fs13.fstatSync(fd).mode & 63) !== 0)
|
|
20473
|
+
fs13.fchmodSync(fd, 384);
|
|
20446
20474
|
} catch {}
|
|
20447
20475
|
};
|
|
20448
20476
|
function appendLine(file, build, options) {
|
|
20449
20477
|
const write = () => {
|
|
20450
|
-
const fd =
|
|
20478
|
+
const fd = fs13.openSync(file, "a+", 384);
|
|
20451
20479
|
try {
|
|
20452
20480
|
if (process.platform !== "win32")
|
|
20453
20481
|
tighten(fd);
|
|
20454
|
-
const size =
|
|
20482
|
+
const size = fs13.fstatSync(fd).size;
|
|
20455
20483
|
let fence = "";
|
|
20456
20484
|
if (size > 0) {
|
|
20457
20485
|
const last = Buffer.alloc(1);
|
|
20458
|
-
|
|
20486
|
+
fs13.readSync(fd, last, 0, 1, size - 1);
|
|
20459
20487
|
if (last[0] !== 10)
|
|
20460
20488
|
fence = `
|
|
20461
20489
|
`;
|
|
@@ -20464,17 +20492,17 @@ function appendLine(file, build, options) {
|
|
|
20464
20492
|
if (!line.ok)
|
|
20465
20493
|
return line;
|
|
20466
20494
|
const bytes = Buffer.from(fence + line.value);
|
|
20467
|
-
const written =
|
|
20495
|
+
const written = fs13.writeSync(fd, bytes);
|
|
20468
20496
|
if (written !== bytes.length)
|
|
20469
20497
|
return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
|
|
20470
20498
|
return { ok: true, value: undefined };
|
|
20471
20499
|
} finally {
|
|
20472
|
-
|
|
20500
|
+
fs13.closeSync(fd);
|
|
20473
20501
|
}
|
|
20474
20502
|
};
|
|
20475
20503
|
try {
|
|
20476
|
-
|
|
20477
|
-
if (!options.forceLock && !onNetworkFs(
|
|
20504
|
+
fs13.mkdirSync(path16.dirname(file), { recursive: true });
|
|
20505
|
+
if (!options.forceLock && !onNetworkFs(path16.dirname(file)))
|
|
20478
20506
|
return write();
|
|
20479
20507
|
const locked = withLedgerLock(file, write);
|
|
20480
20508
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -20544,8 +20572,8 @@ function readLedger(cwd, options = {}) {
|
|
|
20544
20572
|
let text = "";
|
|
20545
20573
|
let stat = null;
|
|
20546
20574
|
try {
|
|
20547
|
-
stat =
|
|
20548
|
-
text =
|
|
20575
|
+
stat = fs13.statSync(file.value);
|
|
20576
|
+
text = fs13.readFileSync(file.value, "utf8");
|
|
20549
20577
|
} catch (error) {
|
|
20550
20578
|
if (error.code === "ENOENT")
|
|
20551
20579
|
return {
|
|
@@ -20685,7 +20713,7 @@ function ledgerTampering(cwd) {
|
|
|
20685
20713
|
if (!file.ok)
|
|
20686
20714
|
return [];
|
|
20687
20715
|
try {
|
|
20688
|
-
const stat =
|
|
20716
|
+
const stat = fs13.statSync(file.value);
|
|
20689
20717
|
const cached = tamperCache.get(file.value);
|
|
20690
20718
|
if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
|
|
20691
20719
|
return cached.breaks;
|
|
@@ -21267,7 +21295,7 @@ var productDecision = (task, ledger) => {
|
|
|
21267
21295
|
};
|
|
21268
21296
|
};
|
|
21269
21297
|
var planRecorded = (task, root) => {
|
|
21270
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(
|
|
21298
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync5(path17.resolve(root, ref.path)));
|
|
21271
21299
|
if (cited)
|
|
21272
21300
|
return {
|
|
21273
21301
|
met: true,
|
|
@@ -21334,14 +21362,14 @@ function derivedRuleStatus(task, requirement, root, ledger) {
|
|
|
21334
21362
|
|
|
21335
21363
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
21336
21364
|
var digestBytes = (value) => createHash10("sha256").update(value).digest("hex");
|
|
21337
|
-
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
21338
|
-
var relative = (root, candidate) =>
|
|
21365
|
+
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`);
|
|
21366
|
+
var relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".";
|
|
21339
21367
|
var canonicalPath = (value) => {
|
|
21340
21368
|
if (typeof value !== "string" || !value)
|
|
21341
21369
|
return null;
|
|
21342
21370
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
21343
21371
|
return null;
|
|
21344
|
-
const normalized =
|
|
21372
|
+
const normalized = path18.posix.normalize(value);
|
|
21345
21373
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
21346
21374
|
return null;
|
|
21347
21375
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -21389,21 +21417,21 @@ var gitPaths = (root) => {
|
|
|
21389
21417
|
git: !/not a git repository/i.test(stderr)
|
|
21390
21418
|
};
|
|
21391
21419
|
}
|
|
21392
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
21420
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
|
|
21393
21421
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
21394
21422
|
if (stagedDeleted.status !== 0) {
|
|
21395
21423
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
21396
21424
|
if (!/not a git repository/i.test(stderr))
|
|
21397
21425
|
return { paths, uncertain: true, git: true };
|
|
21398
21426
|
} else if (stagedDeleted.stdout) {
|
|
21399
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
21427
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
|
|
21400
21428
|
}
|
|
21401
21429
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
21402
21430
|
};
|
|
21403
21431
|
var walk = (root, directory, output) => {
|
|
21404
21432
|
let names;
|
|
21405
21433
|
try {
|
|
21406
|
-
names =
|
|
21434
|
+
names = fs14.readdirSync(directory);
|
|
21407
21435
|
} catch {
|
|
21408
21436
|
return true;
|
|
21409
21437
|
}
|
|
@@ -21411,10 +21439,10 @@ var walk = (root, directory, output) => {
|
|
|
21411
21439
|
for (const name of names) {
|
|
21412
21440
|
if (name === ".git" || name === ".workit")
|
|
21413
21441
|
continue;
|
|
21414
|
-
const target =
|
|
21442
|
+
const target = path18.join(directory, name);
|
|
21415
21443
|
let stat;
|
|
21416
21444
|
try {
|
|
21417
|
-
stat =
|
|
21445
|
+
stat = fs14.lstatSync(target);
|
|
21418
21446
|
} catch {
|
|
21419
21447
|
uncertain = true;
|
|
21420
21448
|
continue;
|
|
@@ -21429,14 +21457,14 @@ var walk = (root, directory, output) => {
|
|
|
21429
21457
|
var scopeRoots = (root, scope) => {
|
|
21430
21458
|
const roots = [];
|
|
21431
21459
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
21432
|
-
const target =
|
|
21460
|
+
const target = path18.resolve(root, item);
|
|
21433
21461
|
if (!inside(root, target))
|
|
21434
21462
|
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` }] });
|
|
21435
21463
|
let ancestor = target;
|
|
21436
|
-
while (!
|
|
21437
|
-
ancestor =
|
|
21464
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
21465
|
+
ancestor = path18.dirname(ancestor);
|
|
21438
21466
|
try {
|
|
21439
|
-
if (!inside(root,
|
|
21467
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
21440
21468
|
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` }] });
|
|
21441
21469
|
} catch {
|
|
21442
21470
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -21448,7 +21476,7 @@ var scopeRoots = (root, scope) => {
|
|
|
21448
21476
|
function captureCandidate(root, scope, environment = []) {
|
|
21449
21477
|
let checkout;
|
|
21450
21478
|
try {
|
|
21451
|
-
checkout =
|
|
21479
|
+
checkout = fs14.realpathSync(root);
|
|
21452
21480
|
} catch {
|
|
21453
21481
|
return failure2("invalid_input", "candidate root does not exist");
|
|
21454
21482
|
}
|
|
@@ -21466,11 +21494,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
21466
21494
|
if (item === ".git" || item === ".workit")
|
|
21467
21495
|
continue;
|
|
21468
21496
|
names.add(item);
|
|
21469
|
-
if (!
|
|
21497
|
+
if (!fs14.existsSync(target))
|
|
21470
21498
|
continue;
|
|
21471
21499
|
let stat;
|
|
21472
21500
|
try {
|
|
21473
|
-
stat =
|
|
21501
|
+
stat = fs14.lstatSync(target);
|
|
21474
21502
|
} catch {
|
|
21475
21503
|
uncertain = true;
|
|
21476
21504
|
continue;
|
|
@@ -21486,17 +21514,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
21486
21514
|
for (const item of [...names].toSorted()) {
|
|
21487
21515
|
if (!scopeMatches(item, normalizedScope))
|
|
21488
21516
|
continue;
|
|
21489
|
-
const target =
|
|
21517
|
+
const target = path18.join(checkout, item);
|
|
21490
21518
|
try {
|
|
21491
|
-
const stat =
|
|
21519
|
+
const stat = fs14.lstatSync(target);
|
|
21492
21520
|
if (stat.isSymbolicLink()) {
|
|
21493
|
-
const link =
|
|
21521
|
+
const link = fs14.readlinkSync(target);
|
|
21494
21522
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
21495
21523
|
} else if (stat.isFile()) {
|
|
21496
21524
|
files.push({
|
|
21497
21525
|
path: item,
|
|
21498
21526
|
kind: "file",
|
|
21499
|
-
digest: digestBytes(
|
|
21527
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
21500
21528
|
executable: (stat.mode & 73) !== 0
|
|
21501
21529
|
});
|
|
21502
21530
|
} else if (!stat.isDirectory()) {
|
|
@@ -21661,7 +21689,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
|
|
|
21661
21689
|
var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
21662
21690
|
let root;
|
|
21663
21691
|
try {
|
|
21664
|
-
root =
|
|
21692
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
21665
21693
|
} catch {
|
|
21666
21694
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
21667
21695
|
}
|
|
@@ -21670,23 +21698,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
21670
21698
|
continue;
|
|
21671
21699
|
if (!reference.digest)
|
|
21672
21700
|
return failure2("invalid_input", "document references require a byte digest");
|
|
21673
|
-
const target =
|
|
21674
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
21701
|
+
const target = path18.resolve(root, reference.path);
|
|
21702
|
+
if (target !== root && !target.startsWith(`${root}${path18.sep}`))
|
|
21675
21703
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
21676
21704
|
fields: [
|
|
21677
21705
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
21678
21706
|
]
|
|
21679
21707
|
});
|
|
21680
21708
|
try {
|
|
21681
|
-
const below =
|
|
21709
|
+
const below = path18.relative(root, target);
|
|
21682
21710
|
let current = root;
|
|
21683
|
-
for (const segment of below.split(
|
|
21711
|
+
for (const segment of below.split(path18.sep)) {
|
|
21684
21712
|
if (!segment)
|
|
21685
21713
|
continue;
|
|
21686
|
-
current =
|
|
21687
|
-
const stat =
|
|
21688
|
-
const real =
|
|
21689
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
21714
|
+
current = path18.join(current, segment);
|
|
21715
|
+
const stat = fs14.lstatSync(current);
|
|
21716
|
+
const real = fs14.realpathSync(current);
|
|
21717
|
+
if (real !== root && !real.startsWith(`${root}${path18.sep}`))
|
|
21690
21718
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
21691
21719
|
fields: [
|
|
21692
21720
|
{
|
|
@@ -21702,7 +21730,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
21702
21730
|
if (current !== target && !stat.isDirectory())
|
|
21703
21731
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
21704
21732
|
}
|
|
21705
|
-
if (digestBytes(
|
|
21733
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
21706
21734
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
21707
21735
|
} catch {
|
|
21708
21736
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -22546,7 +22574,7 @@ var judgeInputSummary = (raw) => {
|
|
|
22546
22574
|
|
|
22547
22575
|
// packages/workit-core/src/autonomy.ts
|
|
22548
22576
|
import os4 from "node:os";
|
|
22549
|
-
import
|
|
22577
|
+
import path19 from "node:path";
|
|
22550
22578
|
var accountHome = () => {
|
|
22551
22579
|
try {
|
|
22552
22580
|
return os4.userInfo().homedir;
|
|
@@ -22555,10 +22583,10 @@ var accountHome = () => {
|
|
|
22555
22583
|
}
|
|
22556
22584
|
};
|
|
22557
22585
|
var grantsHome = { resolve: accountHome };
|
|
22558
|
-
var grantsDir = () =>
|
|
22586
|
+
var grantsDir = () => path19.join(grantsHome.resolve(), ".config", "workit");
|
|
22559
22587
|
var grantsOverride = () => {
|
|
22560
|
-
const configured =
|
|
22561
|
-
return configured ===
|
|
22588
|
+
const configured = path19.resolve(resolveConfigDir());
|
|
22589
|
+
return configured === path19.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 ${path19.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
22562
22590
|
};
|
|
22563
22591
|
var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
|
|
22564
22592
|
var DEFAULT_GRANTS = Object.freeze({
|
|
@@ -24369,7 +24397,7 @@ class WorkitCore {
|
|
|
24369
24397
|
// packages/workit-core/src/core/repo-context.ts
|
|
24370
24398
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
24371
24399
|
import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4 } from "node:fs";
|
|
24372
|
-
import
|
|
24400
|
+
import path20 from "node:path";
|
|
24373
24401
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
24374
24402
|
try {
|
|
24375
24403
|
gitRevisionParts(value);
|
|
@@ -24503,7 +24531,7 @@ var findPrTemplate = (cwd) => {
|
|
|
24503
24531
|
]) {
|
|
24504
24532
|
const parts = rel.split("/");
|
|
24505
24533
|
const base = parts[parts.length - 1];
|
|
24506
|
-
const dir = parts.length > 1 ?
|
|
24534
|
+
const dir = parts.length > 1 ? path20.join(cwd, ...parts.slice(0, -1)) : cwd;
|
|
24507
24535
|
const actual = probeCaseInsensitive(dir, base);
|
|
24508
24536
|
if (actual)
|
|
24509
24537
|
return [...parts.slice(0, -1), actual].join("/");
|
|
@@ -24534,7 +24562,7 @@ var diffStatForRange = (cwd, range) => {
|
|
|
24534
24562
|
return runGit(cwd, ["diff", "--stat", "--"]).stdout;
|
|
24535
24563
|
};
|
|
24536
24564
|
var packageScripts = (cwd, keys) => {
|
|
24537
|
-
const pkgPath =
|
|
24565
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
24538
24566
|
if (!existsSync7(pkgPath))
|
|
24539
24567
|
return [];
|
|
24540
24568
|
try {
|
|
@@ -24560,9 +24588,9 @@ var documentationFiles = (cwd) => {
|
|
|
24560
24588
|
if (entry.isDirectory()) {
|
|
24561
24589
|
if (excluded.has(entry.name))
|
|
24562
24590
|
continue;
|
|
24563
|
-
walk(
|
|
24591
|
+
walk(path20.join(dir, entry.name), depth + 1);
|
|
24564
24592
|
} else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
|
|
24565
|
-
matches.push("./" +
|
|
24593
|
+
matches.push("./" + path20.relative(cwd, path20.join(dir, entry.name)).replaceAll("\\", "/"));
|
|
24566
24594
|
}
|
|
24567
24595
|
}
|
|
24568
24596
|
};
|
|
@@ -24578,7 +24606,7 @@ var readTrimmed2 = (file, maxLines) => {
|
|
|
24578
24606
|
`);
|
|
24579
24607
|
};
|
|
24580
24608
|
function prReadyContext(root, range) {
|
|
24581
|
-
const cwd =
|
|
24609
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
24582
24610
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
24583
24611
|
return invalidRange(cwd);
|
|
24584
24612
|
let stdout = "";
|
|
@@ -24636,7 +24664,7 @@ ${status.stderr}` : "");
|
|
|
24636
24664
|
stdout += `template_path: ${template}
|
|
24637
24665
|
|
|
24638
24666
|
`;
|
|
24639
|
-
stdout += readTrimmed2(
|
|
24667
|
+
stdout += readTrimmed2(path20.join(cwd, template), 220);
|
|
24640
24668
|
} else {
|
|
24641
24669
|
stdout += `template_path: none
|
|
24642
24670
|
|
|
@@ -24646,7 +24674,7 @@ ${status.stderr}` : "");
|
|
|
24646
24674
|
stdout += `
|
|
24647
24675
|
`;
|
|
24648
24676
|
stdout += printSection("Recent Validation Signals");
|
|
24649
|
-
if (existsSync7(
|
|
24677
|
+
if (existsSync7(path20.join(cwd, "package.json"))) {
|
|
24650
24678
|
stdout += `package.json detected. Common scripts:
|
|
24651
24679
|
`;
|
|
24652
24680
|
const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
|
|
@@ -24655,7 +24683,7 @@ ${status.stderr}` : "");
|
|
|
24655
24683
|
`) + `
|
|
24656
24684
|
`;
|
|
24657
24685
|
}
|
|
24658
|
-
if (existsSync7(
|
|
24686
|
+
if (existsSync7(path20.join(cwd, "Cargo.toml")) || existsSync7(path20.join(cwd, "src-tauri/Cargo.toml"))) {
|
|
24659
24687
|
stdout += `Rust project detected.
|
|
24660
24688
|
`;
|
|
24661
24689
|
}
|
|
@@ -24688,7 +24716,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
|
|
|
24688
24716
|
- Apply with the host-native editor, preserving the repository changelog conventions.
|
|
24689
24717
|
- If Unreleased already has duplicate category headings, normalize_only first.`;
|
|
24690
24718
|
function changelogContext(root, range) {
|
|
24691
|
-
const cwd =
|
|
24719
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
24692
24720
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
24693
24721
|
return invalidRange(cwd);
|
|
24694
24722
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -24706,7 +24734,7 @@ function changelogContext(root, range) {
|
|
|
24706
24734
|
stdout += CHANGELOG_RULES + `
|
|
24707
24735
|
`;
|
|
24708
24736
|
stdout += printSection("Existing CHANGELOG.md");
|
|
24709
|
-
const changelogPath =
|
|
24737
|
+
const changelogPath = path20.join(cwd, "CHANGELOG.md");
|
|
24710
24738
|
if (existsSync7(changelogPath)) {
|
|
24711
24739
|
stdout += readTrimmed2(changelogPath, 260) + `
|
|
24712
24740
|
`;
|
|
@@ -24726,7 +24754,7 @@ function changelogContext(root, range) {
|
|
|
24726
24754
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
24727
24755
|
}
|
|
24728
24756
|
function docsRefreshContext(root, range) {
|
|
24729
|
-
const cwd =
|
|
24757
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
24730
24758
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
24731
24759
|
return invalidRange(cwd);
|
|
24732
24760
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -24748,7 +24776,7 @@ function docsRefreshContext(root, range) {
|
|
|
24748
24776
|
`) + `
|
|
24749
24777
|
`;
|
|
24750
24778
|
stdout += printSection("README Preview");
|
|
24751
|
-
const readme =
|
|
24779
|
+
const readme = path20.join(cwd, "README.md");
|
|
24752
24780
|
if (existsSync7(readme)) {
|
|
24753
24781
|
stdout += readTrimmed2(readme, 220) + `
|
|
24754
24782
|
`;
|
|
@@ -24757,7 +24785,7 @@ function docsRefreshContext(root, range) {
|
|
|
24757
24785
|
`;
|
|
24758
24786
|
}
|
|
24759
24787
|
stdout += printSection("Package Scripts");
|
|
24760
|
-
const pkgPath =
|
|
24788
|
+
const pkgPath = path20.join(cwd, "package.json");
|
|
24761
24789
|
if (existsSync7(pkgPath)) {
|
|
24762
24790
|
try {
|
|
24763
24791
|
const pkg = JSON.parse(readFileSync6(pkgPath, "utf8"));
|
|
@@ -24771,7 +24799,7 @@ function docsRefreshContext(root, range) {
|
|
|
24771
24799
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
24772
24800
|
}
|
|
24773
24801
|
function releaseNotesContext(root, rangeOrTag) {
|
|
24774
|
-
const cwd =
|
|
24802
|
+
const cwd = path20.resolve(repoRoot(root));
|
|
24775
24803
|
if (!rangeOrTag) {
|
|
24776
24804
|
return { stdout: "", stderr: `ERROR: release tag or range required
|
|
24777
24805
|
`, exitCode: 1, cwd };
|
|
@@ -24809,7 +24837,7 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
24809
24837
|
`;
|
|
24810
24838
|
stdout += printSection("Existing Release Files");
|
|
24811
24839
|
for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
|
|
24812
|
-
if (existsSync7(
|
|
24840
|
+
if (existsSync7(path20.join(cwd, rel)))
|
|
24813
24841
|
stdout += rel + `
|
|
24814
24842
|
`;
|
|
24815
24843
|
}
|
|
@@ -24840,8 +24868,8 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
24840
24868
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
24841
24869
|
|
|
24842
24870
|
// packages/workit-core/src/core/pr-create.ts
|
|
24843
|
-
import
|
|
24844
|
-
import
|
|
24871
|
+
import fs15 from "node:fs";
|
|
24872
|
+
import path21 from "node:path";
|
|
24845
24873
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
24846
24874
|
// packages/workit-core/src/forge/pr-body.ts
|
|
24847
24875
|
function parseGhIssue(value) {
|
|
@@ -24852,13 +24880,13 @@ function parseGhIssue(value) {
|
|
|
24852
24880
|
// packages/workit-core/src/core/pr-create.ts
|
|
24853
24881
|
function whichOnPath(tool) {
|
|
24854
24882
|
const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
|
|
24855
|
-
for (const dir of (process.env.PATH ?? "").split(
|
|
24883
|
+
for (const dir of (process.env.PATH ?? "").split(path21.delimiter)) {
|
|
24856
24884
|
if (!dir)
|
|
24857
24885
|
continue;
|
|
24858
24886
|
for (const name of names) {
|
|
24859
|
-
const candidate =
|
|
24887
|
+
const candidate = path21.join(dir, name);
|
|
24860
24888
|
try {
|
|
24861
|
-
|
|
24889
|
+
fs15.accessSync(candidate, fs15.constants.X_OK);
|
|
24862
24890
|
return candidate;
|
|
24863
24891
|
} catch {}
|
|
24864
24892
|
}
|
|
@@ -24976,8 +25004,8 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
|
|
|
24976
25004
|
};
|
|
24977
25005
|
|
|
24978
25006
|
// packages/workit-core/src/core/youtrack.ts
|
|
24979
|
-
import
|
|
24980
|
-
import
|
|
25007
|
+
import fs16 from "node:fs";
|
|
25008
|
+
import path22 from "node:path";
|
|
24981
25009
|
|
|
24982
25010
|
// packages/workit-core/src/core/templates.ts
|
|
24983
25011
|
var repoRoot2 = assetRoot();
|
|
@@ -24990,22 +25018,22 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
|
|
|
24990
25018
|
// packages/workit-core/src/core/youtrack.ts
|
|
24991
25019
|
var ISSUE_RE = /^[A-Z]+-\d+$/;
|
|
24992
25020
|
var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
|
|
24993
|
-
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
24994
|
-
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
25021
|
+
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(configDir(), "youtrack.json");
|
|
25022
|
+
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path22.join(resolveConfigDir(), "youtrack.json");
|
|
24995
25023
|
var youTrackTokenModeOk = (p) => {
|
|
24996
25024
|
if (process.platform === "win32")
|
|
24997
25025
|
return true;
|
|
24998
|
-
const mode =
|
|
25026
|
+
const mode = fs16.statSync(p).mode & 511;
|
|
24999
25027
|
return mode === 384;
|
|
25000
25028
|
};
|
|
25001
25029
|
function readYouTrackConfig(required) {
|
|
25002
25030
|
const cfgPath = youTrackConfigPath();
|
|
25003
|
-
if (!
|
|
25031
|
+
if (!fs16.existsSync(cfgPath)) {
|
|
25004
25032
|
return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
|
|
25005
25033
|
}
|
|
25006
25034
|
let parsed;
|
|
25007
25035
|
try {
|
|
25008
|
-
parsed = JSON.parse(
|
|
25036
|
+
parsed = JSON.parse(fs16.readFileSync(cfgPath, "utf8"));
|
|
25009
25037
|
} catch {
|
|
25010
25038
|
return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
|
|
25011
25039
|
}
|
|
@@ -25016,11 +25044,11 @@ function readYouTrackConfig(required) {
|
|
|
25016
25044
|
}
|
|
25017
25045
|
var readYouTrackContextConfig = () => {
|
|
25018
25046
|
const cfgPath = youTrackReadOnlyConfigPath();
|
|
25019
|
-
if (!
|
|
25047
|
+
if (!fs16.existsSync(cfgPath))
|
|
25020
25048
|
return { data: {} };
|
|
25021
25049
|
let parsed;
|
|
25022
25050
|
try {
|
|
25023
|
-
parsed = JSON.parse(
|
|
25051
|
+
parsed = JSON.parse(fs16.readFileSync(cfgPath, "utf8"));
|
|
25024
25052
|
} catch {
|
|
25025
25053
|
return { error: "YouTrack configuration is unavailable" };
|
|
25026
25054
|
}
|
|
@@ -25059,12 +25087,12 @@ var youTrackToken = () => {
|
|
|
25059
25087
|
if ("error" in loaded)
|
|
25060
25088
|
return loaded;
|
|
25061
25089
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
25062
|
-
const tokenPath = tokenFile ?
|
|
25063
|
-
if (!tokenPath || !
|
|
25090
|
+
const tokenPath = tokenFile ? path22.isAbsolute(tokenFile) ? path22.resolve(tokenFile) : path22.resolve(process.cwd(), tokenFile) : "";
|
|
25091
|
+
if (!tokenPath || !fs16.existsSync(tokenPath))
|
|
25064
25092
|
return { error: "missing youtrack.token" };
|
|
25065
25093
|
if (!youTrackTokenModeOk(tokenPath))
|
|
25066
25094
|
return { error: "youtrack.token mode must be 0600" };
|
|
25067
|
-
const token =
|
|
25095
|
+
const token = fs16.readFileSync(tokenPath, "utf8").trim();
|
|
25068
25096
|
if (!token)
|
|
25069
25097
|
return { error: "empty token file" };
|
|
25070
25098
|
if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
|
|
@@ -25129,9 +25157,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
|
|
|
25129
25157
|
} catch {
|
|
25130
25158
|
continue;
|
|
25131
25159
|
}
|
|
25132
|
-
if (!
|
|
25160
|
+
if (!fs16.existsSync(full))
|
|
25133
25161
|
continue;
|
|
25134
|
-
const text =
|
|
25162
|
+
const text = fs16.readFileSync(full, "utf8");
|
|
25135
25163
|
const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
|
|
25136
25164
|
if (m)
|
|
25137
25165
|
return m[1];
|
|
@@ -25401,15 +25429,15 @@ function resolveGitRevision(root, value) {
|
|
|
25401
25429
|
}
|
|
25402
25430
|
function resolveInside(root, candidate) {
|
|
25403
25431
|
const base = realpathSync5(root);
|
|
25404
|
-
const target =
|
|
25405
|
-
if (target !== base && !target.startsWith(base +
|
|
25432
|
+
const target = path23.resolve(base, candidate);
|
|
25433
|
+
if (target !== base && !target.startsWith(base + path23.sep)) {
|
|
25406
25434
|
throw new Error("path must stay inside repository root");
|
|
25407
25435
|
}
|
|
25408
25436
|
let ancestor = target;
|
|
25409
25437
|
while (!existsSync8(ancestor))
|
|
25410
|
-
ancestor =
|
|
25438
|
+
ancestor = path23.dirname(ancestor);
|
|
25411
25439
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
25412
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
25440
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path23.sep)) {
|
|
25413
25441
|
throw new Error("path must stay inside repository root");
|
|
25414
25442
|
}
|
|
25415
25443
|
return target;
|
|
@@ -25441,7 +25469,7 @@ var SUPPORT_MATRIX = {
|
|
|
25441
25469
|
|
|
25442
25470
|
// packages/workit-mcp/src/server.ts
|
|
25443
25471
|
import { existsSync as existsSync9, readFileSync as readFileSync7, realpathSync as realpathSync6 } from "node:fs";
|
|
25444
|
-
import
|
|
25472
|
+
import path24 from "node:path";
|
|
25445
25473
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
25446
25474
|
function isZ4Schema(s) {
|
|
25447
25475
|
const schema = s;
|
|
@@ -27889,13 +27917,13 @@ var rootVariants = (workspaceRoot) => {
|
|
|
27889
27917
|
if (!workspaceRoot)
|
|
27890
27918
|
return [];
|
|
27891
27919
|
const roots = new Set;
|
|
27892
|
-
for (const candidate of [workspaceRoot,
|
|
27893
|
-
if (
|
|
27920
|
+
for (const candidate of [workspaceRoot, path24.resolve(workspaceRoot)]) {
|
|
27921
|
+
if (path24.isAbsolute(candidate) && candidate !== path24.parse(candidate).root)
|
|
27894
27922
|
roots.add(candidate);
|
|
27895
27923
|
}
|
|
27896
27924
|
try {
|
|
27897
27925
|
const canonical = realpathSync6(workspaceRoot);
|
|
27898
|
-
if (canonical !==
|
|
27926
|
+
if (canonical !== path24.parse(canonical).root)
|
|
27899
27927
|
roots.add(canonical);
|
|
27900
27928
|
} catch {}
|
|
27901
27929
|
return [...roots].toSorted((left, right) => right.length - left.length);
|
|
@@ -27977,11 +28005,11 @@ var thrownResult = (tool, error, workspaceRoot) => {
|
|
|
27977
28005
|
};
|
|
27978
28006
|
function createMcpServer(host, contextProvider) {
|
|
27979
28007
|
assertMcpHost(host);
|
|
27980
|
-
const here =
|
|
28008
|
+
const here = path24.dirname(fileURLToPath2(import.meta.url));
|
|
27981
28009
|
const sourceMarker = markSourcesLoaded([
|
|
27982
|
-
|
|
27983
|
-
|
|
27984
|
-
|
|
28010
|
+
path24.join(here, "server.ts"),
|
|
28011
|
+
path24.join(here, "..", "..", "workit-core", "src", "core", "task-contract.ts"),
|
|
28012
|
+
path24.join(here, "..", "..", "workit-core", "src", "core", "task-engine.ts")
|
|
27985
28013
|
].filter((file) => existsSync9(file)));
|
|
27986
28014
|
let staleWarned = false;
|
|
27987
28015
|
const failures = new Map;
|
|
@@ -28320,7 +28348,7 @@ var EXEC = new Set(["exec", "x", "dlx"]);
|
|
|
28320
28348
|
// packages/workit-core/src/core/heavy-words.ts
|
|
28321
28349
|
var HEAVY_WORDS = new Set(("npm npx pnpm pnpx yarn bun bunx deno corepack make gmake docker podman nerdctl " + "python python3 py uv poetry pdm pipenv hatch rye bundle rake nx " + "jest vitest mocha ava tap karma jasmine nyc c8 tsc vue-tsc svelte-check eslint stylelint " + "tslint webpack webpack-cli rollup parcel tsup vite next nuxt nuxi astro ng react-scripts " + "playwright cypress wdio testcafe turbo lerna sonar-scanner sonarless sonarless-mcp go " + "golangci-lint gotestsum staticcheck cargo mvn mvnw gradle gradlew ant sbt bazel bazelisk " + "buck2 dotnet msbuild pytest py.test tox nox mypy pyright pylint coverage maturin pip pip3 " + "rspec rails phpunit pest phpstan psalm composer mix swift xcodebuild flutter dart pod cmake " + "ninja meson ctest scons docker-compose buildah earthly").split(" "));
|
|
28322
28350
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
28323
|
-
import
|
|
28351
|
+
import path25 from "node:path";
|
|
28324
28352
|
|
|
28325
28353
|
// packages/workit-core/src/core/live-session.ts
|
|
28326
28354
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
@@ -28361,7 +28389,7 @@ var MUTATING_WORKIT_GIT = new Set(["commit", "branch"]);
|
|
|
28361
28389
|
var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
28362
28390
|
var PUSHD2 = new Set(["pushd", "push-location"]);
|
|
28363
28391
|
var POPD2 = new Set(["popd", "pop-location"]);
|
|
28364
|
-
var UNKNOWN_DIR =
|
|
28392
|
+
var UNKNOWN_DIR = path25.resolve(path25.parse(process.cwd()).root, ".workit-unknown-dir");
|
|
28365
28393
|
// packages/workit-core/src/core/skill-manifests.ts
|
|
28366
28394
|
if (false) {}
|
|
28367
28395
|
|
|
@@ -28381,7 +28409,42 @@ var READERS = new Set([
|
|
|
28381
28409
|
"type"
|
|
28382
28410
|
]);
|
|
28383
28411
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
28412
|
+
import { existsSync as existsSync10, realpathSync as realpathSync7, statSync as statSync3 } from "node:fs";
|
|
28413
|
+
import path26 from "node:path";
|
|
28414
|
+
var isRecord4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
28415
|
+
var nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "";
|
|
28416
|
+
var optionalText = (value) => typeof value === "string" ? value : null;
|
|
28417
|
+
var existingDirectory = (value) => {
|
|
28418
|
+
if (!nonEmpty2(value) || !path26.isAbsolute(value) || !existsSync10(value))
|
|
28419
|
+
return null;
|
|
28420
|
+
try {
|
|
28421
|
+
return statSync3(value).isDirectory() ? realpathSync7(value) : null;
|
|
28422
|
+
} catch {
|
|
28423
|
+
return null;
|
|
28424
|
+
}
|
|
28425
|
+
};
|
|
28384
28426
|
var SHELLS2 = new Set(["sh", "bash", "zsh", "dash", "pwsh", "powershell", "cmd"]);
|
|
28427
|
+
var SCRIPT_FLAG = /^(?:-\w*c|-command|\/c)$/i;
|
|
28428
|
+
var quoteArg = (arg) => /^[\w@%+=:,./-]+$/.test(arg) ? arg : JSON.stringify(arg);
|
|
28429
|
+
var commandText = (value) => {
|
|
28430
|
+
if (nonEmpty2(value))
|
|
28431
|
+
return value;
|
|
28432
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
28433
|
+
return null;
|
|
28434
|
+
const argv = value;
|
|
28435
|
+
if (!argv.every((arg) => typeof arg === "string"))
|
|
28436
|
+
return null;
|
|
28437
|
+
const shell = argv[0].split(/[\\/]/).at(-1)?.replace(/\.exe$/i, "").toLowerCase() ?? "";
|
|
28438
|
+
if (SHELLS2.has(shell))
|
|
28439
|
+
for (let index = 1;index < argv.length - 1; index++) {
|
|
28440
|
+
if (SCRIPT_FLAG.test(argv[index]))
|
|
28441
|
+
return nonEmpty2(argv[index + 1]) ? argv[index + 1] : null;
|
|
28442
|
+
if (!/^[-/]/.test(argv[index]))
|
|
28443
|
+
break;
|
|
28444
|
+
}
|
|
28445
|
+
const joined = argv.map(quoteArg).join(" ");
|
|
28446
|
+
return nonEmpty2(joined) ? joined : null;
|
|
28447
|
+
};
|
|
28385
28448
|
var WRITE_TOOLS = new Set([
|
|
28386
28449
|
"write",
|
|
28387
28450
|
"edit",
|
|
@@ -28401,6 +28464,23 @@ var WRITE_TOOLS = new Set([
|
|
|
28401
28464
|
"editfile",
|
|
28402
28465
|
"writefile"
|
|
28403
28466
|
]);
|
|
28467
|
+
var isWriteTool = (name) => typeof name === "string" && WRITE_TOOLS.has(name.toLowerCase().replace(/[_-]/g, ""));
|
|
28468
|
+
var PATH_KEYS = ["file_path", "filePath", "notebook_path", "path", "target_file", "file"];
|
|
28469
|
+
var PATCH_HEADER = /^[ \t]*\*\*\* (?:(?:Add|Update|Delete) File|Move to): (.+)$/gm;
|
|
28470
|
+
var writePaths = (input) => {
|
|
28471
|
+
if (!isRecord4(input))
|
|
28472
|
+
return [];
|
|
28473
|
+
const paths = PATH_KEYS.map((key) => input[key]).filter(nonEmpty2);
|
|
28474
|
+
for (const value of Object.values(input))
|
|
28475
|
+
if (typeof value === "string")
|
|
28476
|
+
for (const match of value.matchAll(PATCH_HEADER))
|
|
28477
|
+
paths.push(match[1].trim());
|
|
28478
|
+
return [...new Set(paths)];
|
|
28479
|
+
};
|
|
28480
|
+
var writeTargets = (input) => {
|
|
28481
|
+
const paths = writePaths(input);
|
|
28482
|
+
return paths.length > 0 ? paths : null;
|
|
28483
|
+
};
|
|
28404
28484
|
// packages/workit-core/src/hooks/standing.ts
|
|
28405
28485
|
var sinceStart = new Map;
|
|
28406
28486
|
// packages/workit-core/src/hooks/cwd-normalize.ts
|
|
@@ -28647,8 +28727,168 @@ var CODEX_DESCRIPTOR = {
|
|
|
28647
28727
|
]
|
|
28648
28728
|
};
|
|
28649
28729
|
var codexDescriptor = (host) => ({ ...CODEX_DESCRIPTOR, host });
|
|
28730
|
+
var EVENTS = {
|
|
28731
|
+
SessionStart: "session.start",
|
|
28732
|
+
UserPromptSubmit: "context.turn",
|
|
28733
|
+
PreToolUse: "shell.pre",
|
|
28734
|
+
PostToolUse: "shell.post",
|
|
28735
|
+
SubagentStart: "subagent.start",
|
|
28736
|
+
SubagentStop: "subagent.stop",
|
|
28737
|
+
Stop: "stop"
|
|
28738
|
+
};
|
|
28650
28739
|
var SHELL_TOOLS2 = new Set(["bash", "unified-exec"]);
|
|
28740
|
+
var isShellTool = (name) => SHELL_TOOLS2.has(String(name).toLowerCase());
|
|
28651
28741
|
var SOURCES2 = new Set(["startup", "resume", "clear", "compact", "fork"]);
|
|
28742
|
+
var parseCodexHookInput = (value) => {
|
|
28743
|
+
if (!isRecord4(value) || !Object.hasOwn(EVENTS, String(value.hook_event_name)))
|
|
28744
|
+
return { ok: false, error: "hook_event_name is required" };
|
|
28745
|
+
const event = value.hook_event_name;
|
|
28746
|
+
const cwd = existingDirectory(value.cwd);
|
|
28747
|
+
if (!cwd)
|
|
28748
|
+
return { ok: false, error: "cwd must be an existing absolute directory" };
|
|
28749
|
+
const toolEvent = event === "PreToolUse" || event === "PostToolUse";
|
|
28750
|
+
if (toolEvent && !nonEmpty2(value.tool_name))
|
|
28751
|
+
return { ok: false, error: "tool_name is required" };
|
|
28752
|
+
const command = isRecord4(value.tool_input) ? commandText(value.tool_input.command) : null;
|
|
28753
|
+
if (toolEvent && isShellTool(value.tool_name) && !command)
|
|
28754
|
+
return { ok: false, error: "tool_input.command is required for shell tools" };
|
|
28755
|
+
if (event === "SubagentStart" && !nonEmpty2(value.agent_id))
|
|
28756
|
+
return { ok: false, error: "agent_id is required" };
|
|
28757
|
+
return {
|
|
28758
|
+
ok: true,
|
|
28759
|
+
data: {
|
|
28760
|
+
hook_event_name: event,
|
|
28761
|
+
session_id: nonEmpty2(value.session_id) ? value.session_id : "",
|
|
28762
|
+
model: optionalText(value.model),
|
|
28763
|
+
permission_mode: optionalText(value.permission_mode),
|
|
28764
|
+
transcript_path: optionalText(value.transcript_path),
|
|
28765
|
+
cwd,
|
|
28766
|
+
...event === "SessionStart" ? { source: SOURCES2.has(String(value.source)) ? value.source : "resume" } : {},
|
|
28767
|
+
...nonEmpty2(value.turn_id) ? { turn_id: value.turn_id } : {},
|
|
28768
|
+
...event === "UserPromptSubmit" ? { prompt: optionalText(value.prompt) } : {},
|
|
28769
|
+
...nonEmpty2(value.tool_name) ? { tool_name: value.tool_name } : {},
|
|
28770
|
+
...toolEvent ? { tool_input: value.tool_input } : {},
|
|
28771
|
+
...event === "PostToolUse" && typeof value.tool_response === "string" ? { tool_response: value.tool_response } : {},
|
|
28772
|
+
...command ? { command } : {},
|
|
28773
|
+
...nonEmpty2(value.tool_use_id) ? { tool_use_id: value.tool_use_id } : {},
|
|
28774
|
+
...nonEmpty2(value.agent_id) ? { agent_id: value.agent_id } : {},
|
|
28775
|
+
...nonEmpty2(value.agent_type) ? { agent_type: value.agent_type } : {},
|
|
28776
|
+
...event === "Stop" ? {
|
|
28777
|
+
last_assistant_message: optionalText(value.last_assistant_message),
|
|
28778
|
+
stop_hook_active: value.stop_hook_active === true
|
|
28779
|
+
} : {},
|
|
28780
|
+
...event === "SubagentStop" ? {
|
|
28781
|
+
agent_transcript_path: optionalText(value.agent_transcript_path),
|
|
28782
|
+
last_assistant_message: optionalText(value.last_assistant_message),
|
|
28783
|
+
stop_hook_active: value.stop_hook_active === true
|
|
28784
|
+
} : {}
|
|
28785
|
+
}
|
|
28786
|
+
};
|
|
28787
|
+
};
|
|
28788
|
+
var protocolEvent = (input) => {
|
|
28789
|
+
switch (input.hook_event_name) {
|
|
28790
|
+
case "SessionStart":
|
|
28791
|
+
return { kind: "session.start", source: input.source };
|
|
28792
|
+
case "UserPromptSubmit":
|
|
28793
|
+
return { kind: "context.turn", prompt: input.prompt ?? null };
|
|
28794
|
+
case "PreToolUse": {
|
|
28795
|
+
const toolUseId = input.tool_use_id ?? null;
|
|
28796
|
+
if (isShellTool(input.tool_name))
|
|
28797
|
+
return { kind: "shell.pre", command: input.command ?? "", toolUseId };
|
|
28798
|
+
if (isWriteTool(input.tool_name))
|
|
28799
|
+
return {
|
|
28800
|
+
kind: "write.pre",
|
|
28801
|
+
tool: input.tool_name,
|
|
28802
|
+
paths: writeTargets(input.tool_input),
|
|
28803
|
+
toolUseId
|
|
28804
|
+
};
|
|
28805
|
+
return { kind: "tool.pre", tool: input.tool_name, toolUseId };
|
|
28806
|
+
}
|
|
28807
|
+
case "PostToolUse": {
|
|
28808
|
+
const toolUseId = input.tool_use_id ?? null;
|
|
28809
|
+
return isShellTool(input.tool_name) ? {
|
|
28810
|
+
kind: "shell.post",
|
|
28811
|
+
command: input.command ?? "",
|
|
28812
|
+
stdout: input.tool_response ?? "",
|
|
28813
|
+
exitCode: null,
|
|
28814
|
+
toolUseId
|
|
28815
|
+
} : { kind: "tool.pre", tool: input.tool_name, toolUseId };
|
|
28816
|
+
}
|
|
28817
|
+
case "SubagentStart":
|
|
28818
|
+
return {
|
|
28819
|
+
kind: "subagent.start",
|
|
28820
|
+
agentId: input.agent_id,
|
|
28821
|
+
agentType: input.agent_type ?? "unknown",
|
|
28822
|
+
task: null
|
|
28823
|
+
};
|
|
28824
|
+
case "SubagentStop":
|
|
28825
|
+
return {
|
|
28826
|
+
kind: "subagent.stop",
|
|
28827
|
+
agentId: input.agent_id ?? null,
|
|
28828
|
+
agentType: input.agent_type ?? null,
|
|
28829
|
+
lastMessage: input.last_assistant_message ?? null,
|
|
28830
|
+
stopHookActive: input.stop_hook_active ?? false
|
|
28831
|
+
};
|
|
28832
|
+
case "Stop":
|
|
28833
|
+
return {
|
|
28834
|
+
kind: "stop",
|
|
28835
|
+
lastMessage: input.last_assistant_message ?? null,
|
|
28836
|
+
stopHookActive: input.stop_hook_active ?? false
|
|
28837
|
+
};
|
|
28838
|
+
}
|
|
28839
|
+
};
|
|
28840
|
+
var output = (event, extra = {}) => ({
|
|
28841
|
+
hookSpecificOutput: { hookEventName: event, ...extra }
|
|
28842
|
+
});
|
|
28843
|
+
var render = (decision, native) => {
|
|
28844
|
+
if (native === "Stop" && decision.kind === "continue")
|
|
28845
|
+
return { json: { decision: "block", reason: decision.reason }, exitCode: 0 };
|
|
28846
|
+
if (native === "SubagentStop" || native === "Stop" || native === null)
|
|
28847
|
+
return { json: {}, exitCode: 0 };
|
|
28848
|
+
if (decision.kind === "deny")
|
|
28849
|
+
return {
|
|
28850
|
+
json: output(native, {
|
|
28851
|
+
permissionDecision: "deny",
|
|
28852
|
+
permissionDecisionReason: decision.reason
|
|
28853
|
+
}),
|
|
28854
|
+
exitCode: 0
|
|
28855
|
+
};
|
|
28856
|
+
if (decision.kind === "context")
|
|
28857
|
+
return { json: output(native, { additionalContext: decision.text }), exitCode: 0 };
|
|
28858
|
+
return { json: output(native), exitCode: 0 };
|
|
28859
|
+
};
|
|
28860
|
+
var codexAdapter = {
|
|
28861
|
+
descriptor: CODEX_DESCRIPTOR,
|
|
28862
|
+
parse(raw, env) {
|
|
28863
|
+
const host = detectCodexSurface(env);
|
|
28864
|
+
const parsed = parseCodexHookInput(raw);
|
|
28865
|
+
if (!parsed.ok) {
|
|
28866
|
+
const native = isRecord4(raw) && Object.hasOwn(EVENTS, String(raw.hook_event_name)) ? raw.hook_event_name : null;
|
|
28867
|
+
return { ok: false, error: parsed.error, native, event: native ? EVENTS[native] : null };
|
|
28868
|
+
}
|
|
28869
|
+
const input = parsed.data;
|
|
28870
|
+
return {
|
|
28871
|
+
ok: true,
|
|
28872
|
+
native: input.hook_event_name,
|
|
28873
|
+
input: {
|
|
28874
|
+
host,
|
|
28875
|
+
cwd: input.cwd,
|
|
28876
|
+
session: {
|
|
28877
|
+
id: input.session_id,
|
|
28878
|
+
agentId: input.agent_id ?? null,
|
|
28879
|
+
agentType: input.agent_type ?? null,
|
|
28880
|
+
parentId: null
|
|
28881
|
+
},
|
|
28882
|
+
permissionMode: input.permission_mode,
|
|
28883
|
+
transcriptPath: input.transcript_path,
|
|
28884
|
+
model: input.model,
|
|
28885
|
+
event: protocolEvent(input)
|
|
28886
|
+
}
|
|
28887
|
+
};
|
|
28888
|
+
},
|
|
28889
|
+
render,
|
|
28890
|
+
addendum: (input) => `<workit-codex-mutations>Codex MCP is read-only: unattested callers cannot mutate. Run workit verbs with the workit CLI on the shell (node_modules/.bin/workit, or npx -y @brainervirus/workit-cli): check, git branch|commit|push, pr, ci, stack, ledger, handoff; task-family mutations take --json${input.session.id ? ` --actor ${input.session.id}` : ""}. workit acts as this thread (CODEX_THREAD_ID${input.session.id ? `=${input.session.id}` : ""}) unless WORKIT_SESSION_ID is set. A verifier or reviewer records workit ledger verdict under its own session, never the author's: a workit-verifier or workit-reviewer agent uses the --session its SubagentStart context names; any other passes --as verifier (an id derived from its own thread). A hand-minted id such as <lead>-v1 is refused as forged_session. Merge and release need a workspace grant (workit grant show); a question answer is not host permission.</workit-codex-mutations>`
|
|
28891
|
+
};
|
|
28652
28892
|
|
|
28653
28893
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
28654
28894
|
var TRANSCRIPT_TAIL_BYTES = 256 * 1024;
|
|
@@ -28656,6 +28896,112 @@ var BLOCKING2 = new Set(["preToolUse", "beforeShellExecution", "subagentStart"])
|
|
|
28656
28896
|
|
|
28657
28897
|
// packages/workit-core/src/hooks/run.ts
|
|
28658
28898
|
if (false) {}
|
|
28899
|
+
// packages/workit-core/src/hooks/budget-signal.ts
|
|
28900
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
28901
|
+
import fs17 from "node:fs";
|
|
28902
|
+
import path27 from "node:path";
|
|
28903
|
+
var hash2 = (text) => createHash12("sha256").update(text).digest("hex").slice(0, 32);
|
|
28904
|
+
var budgetDir = (store) => path27.join(store, "budget");
|
|
28905
|
+
var agentBase = (store, session, agentId) => path27.join(budgetDir(store), hash2(`${session}\x00${agentId ?? ""}`));
|
|
28906
|
+
var spawnsFile = (store, session) => path27.join(budgetDir(store), `spawns-${hash2(session)}.jsonl`);
|
|
28907
|
+
var spawnBudget = (prompt) => {
|
|
28908
|
+
const found = /^TIMEBOX:[^\n]*?\b(\d+)\s+tool calls\b/mu.exec(prompt);
|
|
28909
|
+
const n = found ? Number(found[1]) : NaN;
|
|
28910
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
28911
|
+
};
|
|
28912
|
+
var noteSpawnBudget = (cwd, session, type, prompt) => {
|
|
28913
|
+
try {
|
|
28914
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
28915
|
+
if (!store)
|
|
28916
|
+
return;
|
|
28917
|
+
fs17.mkdirSync(budgetDir(store), { recursive: true });
|
|
28918
|
+
fs17.appendFileSync(spawnsFile(store, session), `${JSON.stringify({ type: type ?? "", n: spawnBudget(prompt) })}
|
|
28919
|
+
`);
|
|
28920
|
+
} catch {}
|
|
28921
|
+
};
|
|
28922
|
+
var readBudget = (file) => {
|
|
28923
|
+
try {
|
|
28924
|
+
const { limit, told } = JSON.parse(fs17.readFileSync(file, "utf8"));
|
|
28925
|
+
return typeof limit === "number" && limit > 0 ? { limit, told: Number(told) || 0 } : null;
|
|
28926
|
+
} catch {
|
|
28927
|
+
return null;
|
|
28928
|
+
}
|
|
28929
|
+
};
|
|
28930
|
+
var claimSpawnBudget = (cwd, session, agentId, agentType) => {
|
|
28931
|
+
try {
|
|
28932
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
28933
|
+
if (!store)
|
|
28934
|
+
return null;
|
|
28935
|
+
const file = spawnsFile(store, session);
|
|
28936
|
+
const entries = fs17.readFileSync(file, "utf8").split(`
|
|
28937
|
+
`).filter(Boolean).map((line) => JSON.parse(line));
|
|
28938
|
+
const at = entries.findIndex((entry) => entry.type === (agentType ?? ""));
|
|
28939
|
+
if (at < 0)
|
|
28940
|
+
return null;
|
|
28941
|
+
const [{ n }] = entries.splice(at, 1);
|
|
28942
|
+
fs17.writeFileSync(file, entries.map((entry) => `${JSON.stringify(entry)}
|
|
28943
|
+
`).join(""));
|
|
28944
|
+
if (typeof n !== "number" || n <= 0)
|
|
28945
|
+
return null;
|
|
28946
|
+
startBudget(store, session, agentId, n);
|
|
28947
|
+
return n;
|
|
28948
|
+
} catch {
|
|
28949
|
+
return null;
|
|
28950
|
+
}
|
|
28951
|
+
};
|
|
28952
|
+
var startBudget = (store, session, agentId, n) => {
|
|
28953
|
+
const dir = budgetDir(store);
|
|
28954
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
28955
|
+
const cutoff = Date.now() - 604800000;
|
|
28956
|
+
for (const name of fs17.readdirSync(dir))
|
|
28957
|
+
try {
|
|
28958
|
+
if (fs17.statSync(path27.join(dir, name)).mtimeMs < cutoff)
|
|
28959
|
+
fs17.rmSync(path27.join(dir, name));
|
|
28960
|
+
} catch {}
|
|
28961
|
+
const base = agentBase(store, session, agentId);
|
|
28962
|
+
fs17.writeFileSync(`${base}.json`, JSON.stringify({ limit: n, told: 0 }));
|
|
28963
|
+
fs17.rmSync(`${base}.calls`, { force: true });
|
|
28964
|
+
};
|
|
28965
|
+
var lineFor = (calls) => `Tool-call budget reached (${calls}): commit your work, write your report, stop.`;
|
|
28966
|
+
var reachedOf = (cwd, session, agentId) => {
|
|
28967
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
28968
|
+
const base = store && agentBase(store, session, agentId);
|
|
28969
|
+
const budget = base && readBudget(`${base}.json`);
|
|
28970
|
+
if (!budget)
|
|
28971
|
+
return null;
|
|
28972
|
+
return { base, budget, reached: Math.floor(fs17.statSync(`${base}.calls`).size / budget.limit) };
|
|
28973
|
+
};
|
|
28974
|
+
var dropBudget = (cwd, session, agentId) => {
|
|
28975
|
+
const store = session ? gitStoreDir(cwd) : null;
|
|
28976
|
+
if (store)
|
|
28977
|
+
for (const ext of [".json", ".calls"])
|
|
28978
|
+
fs17.rmSync(agentBase(store, session, agentId) + ext, { force: true });
|
|
28979
|
+
};
|
|
28980
|
+
var budgetLine = (cwd, session, agentId) => {
|
|
28981
|
+
try {
|
|
28982
|
+
const at = reachedOf(cwd, session, agentId);
|
|
28983
|
+
if (!at || at.reached <= at.budget.told)
|
|
28984
|
+
return null;
|
|
28985
|
+
fs17.writeFileSync(`${at.base}.json`, JSON.stringify({ ...at.budget, told: at.reached }));
|
|
28986
|
+
return lineFor(at.budget.limit * at.reached);
|
|
28987
|
+
} catch {
|
|
28988
|
+
return null;
|
|
28989
|
+
}
|
|
28990
|
+
};
|
|
28991
|
+
var CODEX_GATED = new Set(["bash", "unifiedexec", "shell", "applypatch", "edit", "write"]);
|
|
28992
|
+
var budgetHooks = {
|
|
28993
|
+
line: (input) => budgetLine(input.cwd, input.session.id ?? "", input.session.agentId),
|
|
28994
|
+
start: (input, agentId, agentType) => void claimSpawnBudget(input.cwd, input.session.id ?? "", agentId, agentType),
|
|
28995
|
+
spawn: (input, spawn) => {
|
|
28996
|
+
if (!input.session.agentId)
|
|
28997
|
+
noteSpawnBudget(input.cwd, input.session.id ?? "", String(spawn.subagent_type || "general-purpose"), String(spawn.prompt ?? ""));
|
|
28998
|
+
},
|
|
28999
|
+
stop: (input, agentId) => {
|
|
29000
|
+
try {
|
|
29001
|
+
dropBudget(input.cwd, input.session.id ?? "", agentId);
|
|
29002
|
+
} catch {}
|
|
29003
|
+
}
|
|
29004
|
+
};
|
|
28659
29005
|
// packages/workit-codex/hooks/workit-hook.ts
|
|
28660
29006
|
var codexCapabilities = (host, availability = {}) => capabilitiesFor(codexDescriptor(host), {
|
|
28661
29007
|
"session.start": availability.sessionStart,
|
|
@@ -28663,12 +29009,13 @@ var codexCapabilities = (host, availability = {}) => capabilitiesFor(codexDescri
|
|
|
28663
29009
|
"subagent.start": availability.subagentStart,
|
|
28664
29010
|
"subagent.stop": availability.subagentStop
|
|
28665
29011
|
});
|
|
29012
|
+
var adapter = { ...codexAdapter, budget: budgetHooks };
|
|
28666
29013
|
if (false)
|
|
28667
29014
|
;
|
|
28668
29015
|
|
|
28669
29016
|
// packages/workit-codex/scripts/agents.ts
|
|
28670
29017
|
import {
|
|
28671
|
-
existsSync as
|
|
29018
|
+
existsSync as existsSync11,
|
|
28672
29019
|
lstatSync as lstatSync3,
|
|
28673
29020
|
mkdirSync as mkdirSync3,
|
|
28674
29021
|
readdirSync as readdirSync5,
|
|
@@ -28678,18 +29025,18 @@ import {
|
|
|
28678
29025
|
writeFileSync as writeFileSync3
|
|
28679
29026
|
} from "node:fs";
|
|
28680
29027
|
import os5 from "node:os";
|
|
28681
|
-
import
|
|
29028
|
+
import path28 from "node:path";
|
|
28682
29029
|
var CODEX_AGENT_ROLES = ["verifier", "reviewer", "implementer"];
|
|
28683
29030
|
var CODEX_AGENT_MARKER = "# Generated by Workit";
|
|
28684
29031
|
var codexAgentName = (role) => `workit-${role}`;
|
|
28685
29032
|
var codexAgentFile = (role) => `${codexAgentName(role)}.toml`;
|
|
28686
29033
|
var tomlString = (value) => JSON.stringify(value);
|
|
28687
29034
|
var codexHomeOfInstall = (pluginRoot) => {
|
|
28688
|
-
const parts =
|
|
29035
|
+
const parts = path28.resolve(pluginRoot).split(path28.sep);
|
|
28689
29036
|
const cache = parts.length - 4;
|
|
28690
|
-
return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(
|
|
29037
|
+
return cache >= 2 && parts[cache] === "cache" && parts[cache - 1] === "plugins" ? parts.slice(0, cache - 1).join(path28.sep) || path28.sep : null;
|
|
28691
29038
|
};
|
|
28692
|
-
var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME ||
|
|
29039
|
+
var codexHomeFor = (pluginRoot, env) => codexHomeOfInstall(pluginRoot) ?? (env.CODEX_HOME || path28.join(env.HOME || os5.homedir(), ".codex"));
|
|
28693
29040
|
var withRoleModel = (content, file, models) => {
|
|
28694
29041
|
const role = CODEX_AGENT_ROLES.find((candidate) => codexAgentFile(candidate) === file);
|
|
28695
29042
|
const chosen = role ? models[role] : undefined;
|
|
@@ -28712,7 +29059,7 @@ var versionAtLeast = (version, min) => {
|
|
|
28712
29059
|
};
|
|
28713
29060
|
var pluginVersion = (pluginRoot) => {
|
|
28714
29061
|
try {
|
|
28715
|
-
const version = JSON.parse(readFileSync8(
|
|
29062
|
+
const version = JSON.parse(readFileSync8(path28.join(pluginRoot, "package.json"), "utf8")).version;
|
|
28716
29063
|
return typeof version === "string" && /^\d+\.\d+\.\d+/.test(version) ? version.match(/^\d+\.\d+\.\d+/)[0] : null;
|
|
28717
29064
|
} catch {
|
|
28718
29065
|
return null;
|
|
@@ -28726,15 +29073,15 @@ var lstatOrNull = (file) => {
|
|
|
28726
29073
|
}
|
|
28727
29074
|
};
|
|
28728
29075
|
var installCodexAgents = (pluginRoot, codexHome, models = {}) => {
|
|
28729
|
-
const source =
|
|
28730
|
-
if (!
|
|
29076
|
+
const source = path28.join(pluginRoot, "agents");
|
|
29077
|
+
if (!existsSync11(source))
|
|
28731
29078
|
return [];
|
|
28732
29079
|
const version = pluginVersion(pluginRoot);
|
|
28733
|
-
const target =
|
|
29080
|
+
const target = path28.join(codexHome, "agents");
|
|
28734
29081
|
const results = [];
|
|
28735
29082
|
for (const file of readdirSync5(source).filter((name) => name.endsWith(".toml")).toSorted()) {
|
|
28736
|
-
const content = withRoleModel(stampCodexAgent(readFileSync8(
|
|
28737
|
-
const dest =
|
|
29083
|
+
const content = withRoleModel(stampCodexAgent(readFileSync8(path28.join(source, file), "utf8"), version), file, models);
|
|
29084
|
+
const dest = path28.join(target, file);
|
|
28738
29085
|
const stat = lstatOrNull(dest);
|
|
28739
29086
|
if (stat?.isSymbolicLink()) {
|
|
28740
29087
|
results.push({ file: dest, action: "skipped-symlink" });
|
|
@@ -28770,7 +29117,7 @@ var installCodexAgents = (pluginRoot, codexHome, models = {}) => {
|
|
|
28770
29117
|
results.push({ file: dest, action: "kept-newer-version" });
|
|
28771
29118
|
continue;
|
|
28772
29119
|
}
|
|
28773
|
-
const temp =
|
|
29120
|
+
const temp = path28.join(target, `.${file}.${process.pid}.${Date.now()}.tmp`);
|
|
28774
29121
|
writeFileSync3(temp, content, { flag: "wx" });
|
|
28775
29122
|
try {
|
|
28776
29123
|
renameSync2(temp, dest);
|
|
@@ -28792,14 +29139,14 @@ var codexQualification = (host) => host === "codex_cli" ? { surface: host, cli:
|
|
|
28792
29139
|
var resolveCodexWorkspaceRoot = (pluginRoot, env) => {
|
|
28793
29140
|
const explicit = env.WORKFLOW_WORKSPACE_ROOT;
|
|
28794
29141
|
const inherited = env.PWD;
|
|
28795
|
-
const candidate = explicit ?? (inherited &&
|
|
28796
|
-
if (!candidate || !
|
|
29142
|
+
const candidate = explicit ?? (inherited && path29.resolve(inherited) !== path29.resolve(pluginRoot) ? inherited : undefined);
|
|
29143
|
+
if (!candidate || !path29.isAbsolute(candidate) || !existsSync12(candidate))
|
|
28797
29144
|
return null;
|
|
28798
29145
|
try {
|
|
28799
|
-
if (!
|
|
29146
|
+
if (!statSync4(candidate).isDirectory())
|
|
28800
29147
|
return null;
|
|
28801
|
-
const canonical =
|
|
28802
|
-
if (canonical ===
|
|
29148
|
+
const canonical = realpathSync8(candidate);
|
|
29149
|
+
if (canonical === realpathSync8(pluginRoot)) {
|
|
28803
29150
|
if (!explicit)
|
|
28804
29151
|
return null;
|
|
28805
29152
|
const workspace = new TaskStore(canonical).readWorkspace();
|
|
@@ -28832,7 +29179,7 @@ var codexContextProvider = (host = detectCodexSurface(process.env), root) => ({
|
|
|
28832
29179
|
};
|
|
28833
29180
|
}
|
|
28834
29181
|
});
|
|
28835
|
-
var pluginRoot = () =>
|
|
29182
|
+
var pluginRoot = () => path29.resolve(path29.dirname(fileURLToPath3(import.meta.url)), "..");
|
|
28836
29183
|
var codexRoleModels = (cwd) => {
|
|
28837
29184
|
const out = {};
|
|
28838
29185
|
for (const role of ["verifier", "reviewer"]) {
|