@brainervirus/workit-cursor 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/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +622 -434
- package/dist/mcp-server.js +3 -0
- package/dist/workit-hook.js +627 -435
- package/package.json +3 -3
|
@@ -10767,11 +10767,62 @@ var init_host_session = __esm(() => {
|
|
|
10767
10767
|
OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
|
|
10768
10768
|
});
|
|
10769
10769
|
|
|
10770
|
-
// packages/workit-core/src/
|
|
10771
|
-
import {
|
|
10772
|
-
import { createHash as createHash8, randomBytes as randomBytes2 } from "node:crypto";
|
|
10770
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
10771
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
10773
10772
|
import fs6 from "node:fs";
|
|
10774
10773
|
import path8 from "node:path";
|
|
10774
|
+
var gitStoreDir = (cwd) => {
|
|
10775
|
+
try {
|
|
10776
|
+
for (let dir = path8.resolve(cwd);; dir = path8.dirname(dir)) {
|
|
10777
|
+
const dotGit = path8.join(dir, ".git");
|
|
10778
|
+
if (fs6.existsSync(dotGit)) {
|
|
10779
|
+
let gitDir = dotGit;
|
|
10780
|
+
if (fs6.statSync(dotGit).isFile()) {
|
|
10781
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs6.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
10782
|
+
if (!target)
|
|
10783
|
+
return null;
|
|
10784
|
+
gitDir = path8.resolve(dir, target);
|
|
10785
|
+
const common = path8.join(gitDir, "commondir");
|
|
10786
|
+
if (fs6.existsSync(common))
|
|
10787
|
+
gitDir = path8.resolve(gitDir, fs6.readFileSync(common, "utf8").trim());
|
|
10788
|
+
}
|
|
10789
|
+
return path8.join(gitDir, "workit");
|
|
10790
|
+
}
|
|
10791
|
+
if (path8.dirname(dir) === dir)
|
|
10792
|
+
return null;
|
|
10793
|
+
}
|
|
10794
|
+
} catch {
|
|
10795
|
+
return null;
|
|
10796
|
+
}
|
|
10797
|
+
}, standingRevFile = (store) => path8.join(store, "standing", "rev"), standingSeenFile = (store, session, agentId) => path8.join(store, "standing", "seen", `${createHash8("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`), readStandingRev = (store) => {
|
|
10798
|
+
try {
|
|
10799
|
+
return fs6.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
10800
|
+
} catch {
|
|
10801
|
+
return null;
|
|
10802
|
+
}
|
|
10803
|
+
}, readStandingSeen = (file) => {
|
|
10804
|
+
try {
|
|
10805
|
+
const value = JSON.parse(fs6.readFileSync(file, "utf8"));
|
|
10806
|
+
return {
|
|
10807
|
+
rev: typeof value.rev === "string" ? value.rev : null,
|
|
10808
|
+
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
10809
|
+
};
|
|
10810
|
+
} catch {
|
|
10811
|
+
return { rev: null, ids: [] };
|
|
10812
|
+
}
|
|
10813
|
+
}, writeStandingSeen = (file, seen) => {
|
|
10814
|
+
try {
|
|
10815
|
+
fs6.mkdirSync(path8.dirname(file), { recursive: true });
|
|
10816
|
+
fs6.writeFileSync(file, JSON.stringify(seen));
|
|
10817
|
+
} catch {}
|
|
10818
|
+
};
|
|
10819
|
+
var init_standing_signal = () => {};
|
|
10820
|
+
|
|
10821
|
+
// packages/workit-core/src/ledger.ts
|
|
10822
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
10823
|
+
import { createHash as createHash9, randomBytes as randomBytes2 } from "node:crypto";
|
|
10824
|
+
import fs7 from "node:fs";
|
|
10825
|
+
import path9 from "node:path";
|
|
10775
10826
|
function resolveCommit(cwd, ref) {
|
|
10776
10827
|
if (!safeRef(ref))
|
|
10777
10828
|
return null;
|
|
@@ -10825,7 +10876,7 @@ function diffHash(cwd, base, head) {
|
|
|
10825
10876
|
], GIT_TIMEOUTS.worktree);
|
|
10826
10877
|
if (!diff.ok || !diff.stdout)
|
|
10827
10878
|
return null;
|
|
10828
|
-
const hash =
|
|
10879
|
+
const hash = createHash9("sha256");
|
|
10829
10880
|
for (const line of diff.stdout.split(`
|
|
10830
10881
|
`)) {
|
|
10831
10882
|
if (line.startsWith("index "))
|
|
@@ -10837,14 +10888,14 @@ function diffHash(cwd, base, head) {
|
|
|
10837
10888
|
return `sha256:${hash.digest("hex")}`;
|
|
10838
10889
|
}
|
|
10839
10890
|
function storeRoot(cwd) {
|
|
10840
|
-
const location = resolveStore(
|
|
10891
|
+
const location = resolveStore(path9.resolve(cwd));
|
|
10841
10892
|
if (location instanceof Error)
|
|
10842
10893
|
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");
|
|
10843
10894
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
10844
10895
|
}
|
|
10845
10896
|
function ledgerPath(cwd) {
|
|
10846
10897
|
const root = storeRoot(cwd);
|
|
10847
|
-
return root.ok ? { ok: true, value:
|
|
10898
|
+
return root.ok ? { ok: true, value: path9.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
10848
10899
|
}
|
|
10849
10900
|
function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
|
|
10850
10901
|
const lock = `${file}.lock`;
|
|
@@ -10870,15 +10921,15 @@ function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
|
|
|
10870
10921
|
}
|
|
10871
10922
|
function appendLine(file, build, options) {
|
|
10872
10923
|
const write = () => {
|
|
10873
|
-
const fd =
|
|
10924
|
+
const fd = fs7.openSync(file, "a+", 384);
|
|
10874
10925
|
try {
|
|
10875
10926
|
if (process.platform !== "win32")
|
|
10876
10927
|
tighten(fd);
|
|
10877
|
-
const size =
|
|
10928
|
+
const size = fs7.fstatSync(fd).size;
|
|
10878
10929
|
let fence = "";
|
|
10879
10930
|
if (size > 0) {
|
|
10880
10931
|
const last = Buffer.alloc(1);
|
|
10881
|
-
|
|
10932
|
+
fs7.readSync(fd, last, 0, 1, size - 1);
|
|
10882
10933
|
if (last[0] !== 10)
|
|
10883
10934
|
fence = `
|
|
10884
10935
|
`;
|
|
@@ -10887,17 +10938,17 @@ function appendLine(file, build, options) {
|
|
|
10887
10938
|
if (!line.ok)
|
|
10888
10939
|
return line;
|
|
10889
10940
|
const bytes = Buffer.from(fence + line.value);
|
|
10890
|
-
const written =
|
|
10941
|
+
const written = fs7.writeSync(fd, bytes);
|
|
10891
10942
|
if (written !== bytes.length)
|
|
10892
10943
|
return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
|
|
10893
10944
|
return { ok: true, value: undefined };
|
|
10894
10945
|
} finally {
|
|
10895
|
-
|
|
10946
|
+
fs7.closeSync(fd);
|
|
10896
10947
|
}
|
|
10897
10948
|
};
|
|
10898
10949
|
try {
|
|
10899
|
-
|
|
10900
|
-
if (!options.forceLock && !onNetworkFs(
|
|
10950
|
+
fs7.mkdirSync(path9.dirname(file), { recursive: true });
|
|
10951
|
+
if (!options.forceLock && !onNetworkFs(path9.dirname(file)))
|
|
10901
10952
|
return write();
|
|
10902
10953
|
const locked = withLedgerLock(file, write);
|
|
10903
10954
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -10952,8 +11003,8 @@ function readLedger(cwd, options = {}) {
|
|
|
10952
11003
|
let text = "";
|
|
10953
11004
|
let stat = null;
|
|
10954
11005
|
try {
|
|
10955
|
-
stat =
|
|
10956
|
-
text =
|
|
11006
|
+
stat = fs7.statSync(file.value);
|
|
11007
|
+
text = fs7.readFileSync(file.value, "utf8");
|
|
10957
11008
|
} catch (error) {
|
|
10958
11009
|
if (error.code === "ENOENT")
|
|
10959
11010
|
return {
|
|
@@ -11085,7 +11136,7 @@ function ledgerTampering(cwd) {
|
|
|
11085
11136
|
if (!file.ok)
|
|
11086
11137
|
return [];
|
|
11087
11138
|
try {
|
|
11088
|
-
const stat =
|
|
11139
|
+
const stat = fs7.statSync(file.value);
|
|
11089
11140
|
const cached = tamperCache.get(file.value);
|
|
11090
11141
|
if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
|
|
11091
11142
|
return cached.breaks;
|
|
@@ -11367,6 +11418,27 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
11367
11418
|
warnings
|
|
11368
11419
|
};
|
|
11369
11420
|
}
|
|
11421
|
+
function activeStanding(rows, fanout, leads = null) {
|
|
11422
|
+
const active = [];
|
|
11423
|
+
for (const row of rows) {
|
|
11424
|
+
if (row.fanout !== fanout || !fromLead(row, leads))
|
|
11425
|
+
continue;
|
|
11426
|
+
if (row.type === "standing" && typeof row.what === "string" && row.what.trim()) {
|
|
11427
|
+
if (!row.superseded)
|
|
11428
|
+
active.push(row);
|
|
11429
|
+
} else if (row.type === "standing.cleared") {
|
|
11430
|
+
const target = str(row.target);
|
|
11431
|
+
if (target === null)
|
|
11432
|
+
active.length = 0;
|
|
11433
|
+
else {
|
|
11434
|
+
const index = active.findIndex((order) => order.id === target);
|
|
11435
|
+
if (index >= 0)
|
|
11436
|
+
active.splice(index, 1);
|
|
11437
|
+
}
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11440
|
+
return active;
|
|
11441
|
+
}
|
|
11370
11442
|
var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, PASSING, FAILING, STRONG_RESULTS, PR_ROW_TYPES, err = (code, error, unblock) => ({
|
|
11371
11443
|
ok: false,
|
|
11372
11444
|
code,
|
|
@@ -11411,28 +11483,28 @@ var LEDGER_VERSION = 1, MAX_LINE_BYTES = 4096, PASSING, FAILING, STRONG_RESULTS,
|
|
|
11411
11483
|
if (process.platform !== "linux")
|
|
11412
11484
|
return false;
|
|
11413
11485
|
try {
|
|
11414
|
-
return isNetworkFsType(
|
|
11486
|
+
return isNetworkFsType(fs7.statfsSync(dir).type);
|
|
11415
11487
|
} catch {
|
|
11416
11488
|
return false;
|
|
11417
11489
|
}
|
|
11418
11490
|
}, LOCK_WAIT_MS = 5000, LOCK_STALE_MS = 30000, LOCK_OWNER = "owner", lockToken = (lock) => {
|
|
11419
11491
|
try {
|
|
11420
|
-
return
|
|
11492
|
+
return fs7.readFileSync(path9.join(lock, LOCK_OWNER), "utf8");
|
|
11421
11493
|
} catch {
|
|
11422
11494
|
return null;
|
|
11423
11495
|
}
|
|
11424
11496
|
}, lockAgeMs = (lock) => {
|
|
11425
|
-
for (const target of [
|
|
11497
|
+
for (const target of [path9.join(lock, LOCK_OWNER), lock]) {
|
|
11426
11498
|
try {
|
|
11427
|
-
return Date.now() -
|
|
11499
|
+
return Date.now() - fs7.statSync(target).mtimeMs;
|
|
11428
11500
|
} catch {}
|
|
11429
11501
|
}
|
|
11430
11502
|
return null;
|
|
11431
|
-
}, ledgerLock, sha2562 = (text) =>
|
|
11503
|
+
}, ledgerLock, sha2562 = (text) => createHash9("sha256").update(text).digest("hex"), chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
|
|
11432
11504
|
${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
11433
11505
|
for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
|
|
11434
11506
|
const buffer = Buffer.alloc(span);
|
|
11435
|
-
|
|
11507
|
+
fs7.readSync(fd, buffer, 0, span, size - span);
|
|
11436
11508
|
const end = buffer.lastIndexOf(10);
|
|
11437
11509
|
if (end < 0) {
|
|
11438
11510
|
if (span === size)
|
|
@@ -11462,8 +11534,8 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
11462
11534
|
return null;
|
|
11463
11535
|
}, tighten = (fd) => {
|
|
11464
11536
|
try {
|
|
11465
|
-
if ((
|
|
11466
|
-
|
|
11537
|
+
if ((fs7.fstatSync(fd).mode & 63) !== 0)
|
|
11538
|
+
fs7.fchmodSync(fd, 384);
|
|
11467
11539
|
} catch {}
|
|
11468
11540
|
}, sealed = (row, id, at, previous) => {
|
|
11469
11541
|
const { prevHash: _prev, rowHash: _row, ...fields } = row;
|
|
@@ -11505,12 +11577,13 @@ ${body}`), TAIL_BYTES, lastLine = (fd, size) => {
|
|
|
11505
11577
|
if (row.self === true && !reasons.includes("no_session"))
|
|
11506
11578
|
reasons.push("self");
|
|
11507
11579
|
return reasons;
|
|
11508
|
-
}, OBSERVED_ONLY;
|
|
11580
|
+
}, fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session), OBSERVED_ONLY;
|
|
11509
11581
|
var init_ledger = __esm(() => {
|
|
11510
11582
|
init_store_lock();
|
|
11511
11583
|
init_vcs_config();
|
|
11512
11584
|
init_rev();
|
|
11513
11585
|
init_host_session();
|
|
11586
|
+
init_standing_signal();
|
|
11514
11587
|
init_paths();
|
|
11515
11588
|
PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
|
|
11516
11589
|
FAILING = new Set(["failed", "blocked"]);
|
|
@@ -11536,14 +11609,14 @@ var init_ledger = __esm(() => {
|
|
|
11536
11609
|
ledgerLock = {
|
|
11537
11610
|
acquire(lock) {
|
|
11538
11611
|
try {
|
|
11539
|
-
|
|
11612
|
+
fs7.mkdirSync(lock);
|
|
11540
11613
|
} catch (error) {
|
|
11541
11614
|
if (error.code === "EEXIST")
|
|
11542
11615
|
return null;
|
|
11543
11616
|
throw error;
|
|
11544
11617
|
}
|
|
11545
11618
|
const token = `${process.pid}-${randomBytes2(8).toString("hex")}`;
|
|
11546
|
-
|
|
11619
|
+
fs7.writeFileSync(path9.join(lock, LOCK_OWNER), token);
|
|
11547
11620
|
return token;
|
|
11548
11621
|
},
|
|
11549
11622
|
release(lock, token) {
|
|
@@ -11551,35 +11624,35 @@ var init_ledger = __esm(() => {
|
|
|
11551
11624
|
return false;
|
|
11552
11625
|
const tomb = `${lock}.release-${randomBytes2(6).toString("hex")}`;
|
|
11553
11626
|
try {
|
|
11554
|
-
|
|
11627
|
+
fs7.renameSync(lock, tomb);
|
|
11555
11628
|
} catch {
|
|
11556
11629
|
return false;
|
|
11557
11630
|
}
|
|
11558
11631
|
if (lockToken(tomb) !== token) {
|
|
11559
11632
|
try {
|
|
11560
|
-
|
|
11633
|
+
fs7.renameSync(tomb, lock);
|
|
11561
11634
|
} catch {}
|
|
11562
11635
|
return false;
|
|
11563
11636
|
}
|
|
11564
|
-
|
|
11637
|
+
fs7.rmSync(tomb, { recursive: true, force: true });
|
|
11565
11638
|
return true;
|
|
11566
11639
|
},
|
|
11567
11640
|
token: lockToken,
|
|
11568
11641
|
reap(lock, observed) {
|
|
11569
11642
|
const tomb = `${lock}.reap-${randomBytes2(6).toString("hex")}`;
|
|
11570
11643
|
try {
|
|
11571
|
-
|
|
11644
|
+
fs7.renameSync(lock, tomb);
|
|
11572
11645
|
} catch {
|
|
11573
11646
|
return false;
|
|
11574
11647
|
}
|
|
11575
11648
|
if (lockToken(tomb) === observed) {
|
|
11576
|
-
|
|
11649
|
+
fs7.rmSync(tomb, { recursive: true, force: true });
|
|
11577
11650
|
return true;
|
|
11578
11651
|
}
|
|
11579
11652
|
try {
|
|
11580
|
-
|
|
11653
|
+
fs7.renameSync(tomb, lock);
|
|
11581
11654
|
} catch {
|
|
11582
|
-
|
|
11655
|
+
fs7.rmSync(tomb, { recursive: true, force: true });
|
|
11583
11656
|
}
|
|
11584
11657
|
return false;
|
|
11585
11658
|
}
|
|
@@ -11613,7 +11686,7 @@ var init_ledger = __esm(() => {
|
|
|
11613
11686
|
|
|
11614
11687
|
// packages/workit-core/src/core/policy/derive.ts
|
|
11615
11688
|
import { existsSync as existsSync2 } from "node:fs";
|
|
11616
|
-
import
|
|
11689
|
+
import path10 from "node:path";
|
|
11617
11690
|
function deriveRequirements(judgment, scope, constraints, verification = "self") {
|
|
11618
11691
|
const out = [];
|
|
11619
11692
|
const base = { scope, dependentAction: null };
|
|
@@ -11765,7 +11838,7 @@ var RULES, derived2 = (spec) => ({
|
|
|
11765
11838
|
decisionIds: []
|
|
11766
11839
|
};
|
|
11767
11840
|
}, planRecorded = (task, root) => {
|
|
11768
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(
|
|
11841
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync2(path10.resolve(root, ref.path)));
|
|
11769
11842
|
if (cited)
|
|
11770
11843
|
return {
|
|
11771
11844
|
met: true,
|
|
@@ -12362,7 +12435,7 @@ var init_safe_write = () => {};
|
|
|
12362
12435
|
|
|
12363
12436
|
// packages/workit-core/src/autonomy.ts
|
|
12364
12437
|
import os4 from "node:os";
|
|
12365
|
-
import
|
|
12438
|
+
import path11 from "node:path";
|
|
12366
12439
|
function endpointOf(entry) {
|
|
12367
12440
|
const raw = entry?.defaultEndpoint;
|
|
12368
12441
|
if (raw === undefined)
|
|
@@ -12459,9 +12532,9 @@ var accountHome = () => {
|
|
|
12459
12532
|
} catch {
|
|
12460
12533
|
return os4.homedir();
|
|
12461
12534
|
}
|
|
12462
|
-
}, grantsHome, grantsDir = () =>
|
|
12463
|
-
const configured =
|
|
12464
|
-
return configured ===
|
|
12535
|
+
}, grantsHome, grantsDir = () => path11.join(grantsHome.resolve(), ".config", "workit"), grantsOverride = () => {
|
|
12536
|
+
const configured = path11.resolve(resolveConfigDir());
|
|
12537
|
+
return configured === path11.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 ${path11.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
12465
12538
|
}, GRANT_KINDS, DEFAULT_GRANTS, DEFAULT_ENDPOINTS, DEFAULT_ENDPOINT = "commit", isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value), DEFAULT_VERIFICATION = "self", verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self", isGrantValue = (value) => value === true || value === false || value === "verified", normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value, fromAutoApprove = (value) => {
|
|
12466
12539
|
if (value === true)
|
|
12467
12540
|
return { push: true, pr: true, merge: "verified" };
|
|
@@ -12552,7 +12625,7 @@ function normalizeMaxBytes(value, options = {}) {
|
|
|
12552
12625
|
}
|
|
12553
12626
|
|
|
12554
12627
|
// node_modules/@openclaw/fs-safe/dist/bounded-read.js
|
|
12555
|
-
import
|
|
12628
|
+
import fs8 from "node:fs";
|
|
12556
12629
|
function createScratchBuffer(maxBytes) {
|
|
12557
12630
|
const initialReadBytes = Number.isFinite(maxBytes) ? Math.min(READ_CHUNK_BYTES, maxBytes + 1) : READ_CHUNK_BYTES;
|
|
12558
12631
|
return Buffer.allocUnsafe(Math.max(1, initialReadBytes));
|
|
@@ -12575,7 +12648,7 @@ function readFileDescriptorBoundedSync(fd, maxBytes) {
|
|
|
12575
12648
|
let total = 0;
|
|
12576
12649
|
while (true) {
|
|
12577
12650
|
const length = nextReadLength(total, maxBytes, scratch.length);
|
|
12578
|
-
const bytesRead =
|
|
12651
|
+
const bytesRead = fs8.readSync(fd, scratch, 0, length, null);
|
|
12579
12652
|
if (bytesRead === 0) {
|
|
12580
12653
|
return Buffer.concat(chunks, total);
|
|
12581
12654
|
}
|
|
@@ -12589,9 +12662,9 @@ var init_bounded_read = __esm(() => {
|
|
|
12589
12662
|
});
|
|
12590
12663
|
|
|
12591
12664
|
// node_modules/@openclaw/fs-safe/dist/read-open-flags.js
|
|
12592
|
-
import
|
|
12665
|
+
import fs9 from "node:fs";
|
|
12593
12666
|
function resolveReadOpenFlags(options) {
|
|
12594
|
-
const constants = options?.constants ??
|
|
12667
|
+
const constants = options?.constants ?? fs9.constants;
|
|
12595
12668
|
const noFollow = process.platform !== "win32" && options?.followSymlinks !== true && typeof constants.O_NOFOLLOW === "number" ? constants.O_NOFOLLOW : 0;
|
|
12596
12669
|
const nonBlocking = process.platform !== "win32" && typeof constants.O_NONBLOCK === "number" ? constants.O_NONBLOCK : 0;
|
|
12597
12670
|
return constants.O_RDONLY | noFollow | nonBlocking;
|
|
@@ -12601,7 +12674,7 @@ var init_read_open_flags = () => {};
|
|
|
12601
12674
|
// node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js
|
|
12602
12675
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
12603
12676
|
import fsSync from "node:fs";
|
|
12604
|
-
import
|
|
12677
|
+
import path12 from "node:path";
|
|
12605
12678
|
function parseSidecarLockSnapshot(snapshot, parser) {
|
|
12606
12679
|
return snapshot && { ...snapshot, payload: parseSidecarLockPayload(snapshot.raw, parser) };
|
|
12607
12680
|
}
|
|
@@ -12629,13 +12702,13 @@ ${ownershipToken}
|
|
|
12629
12702
|
return { raw, ownershipToken };
|
|
12630
12703
|
}
|
|
12631
12704
|
function relativeSidecarLockPath(lockRoot, lockPath) {
|
|
12632
|
-
const resolved =
|
|
12633
|
-
const lexicalRelative =
|
|
12634
|
-
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${
|
|
12635
|
-
if (!relative || relative === ".." || relative.startsWith(`..${
|
|
12705
|
+
const resolved = path12.resolve(lockPath);
|
|
12706
|
+
const lexicalRelative = path12.relative(lockRoot.rootDir, resolved);
|
|
12707
|
+
const relative = lexicalRelative !== ".." && !lexicalRelative.startsWith(`..${path12.sep}`) && !path12.isAbsolute(lexicalRelative) ? lexicalRelative : path12.relative(lockRoot.rootReal, resolved);
|
|
12708
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path12.sep}`) || path12.isAbsolute(relative)) {
|
|
12636
12709
|
throw new FsSafeError("outside-workspace", "sidecar lock path is outside lockRoot");
|
|
12637
12710
|
}
|
|
12638
|
-
return relative.split(
|
|
12711
|
+
return relative.split(path12.sep).join(path12.posix.sep);
|
|
12639
12712
|
}
|
|
12640
12713
|
function parseSidecarLockPayload(raw, parser) {
|
|
12641
12714
|
if (parser) {
|
|
@@ -12804,8 +12877,8 @@ function sleepSync(ms) {
|
|
|
12804
12877
|
}
|
|
12805
12878
|
|
|
12806
12879
|
// node_modules/@openclaw/fs-safe/dist/file-lock-sync.js
|
|
12807
|
-
import
|
|
12808
|
-
import
|
|
12880
|
+
import fs10 from "node:fs";
|
|
12881
|
+
import path13 from "node:path";
|
|
12809
12882
|
function getSyncHeldLocks() {
|
|
12810
12883
|
const globalWithState = globalThis;
|
|
12811
12884
|
if (!globalWithState[SYNC_HELD_LOCKS_KEY]) {
|
|
@@ -12822,7 +12895,7 @@ function releaseAllSyncHeldLocks() {
|
|
|
12822
12895
|
}
|
|
12823
12896
|
try {
|
|
12824
12897
|
if (held.fd !== undefined)
|
|
12825
|
-
|
|
12898
|
+
fs10.closeSync(held.fd);
|
|
12826
12899
|
} catch {}
|
|
12827
12900
|
try {
|
|
12828
12901
|
removeSidecarLockIfUnchangedSync(held.lockPath, held.snapshot);
|
|
@@ -12857,7 +12930,7 @@ function releaseSyncHeldLock(held) {
|
|
|
12857
12930
|
if (held.fd !== undefined) {
|
|
12858
12931
|
const fd = held.fd;
|
|
12859
12932
|
held.fd = undefined;
|
|
12860
|
-
|
|
12933
|
+
fs10.closeSync(fd);
|
|
12861
12934
|
}
|
|
12862
12935
|
removeSidecarLockIfUnchangedSync(held.lockPath, held.snapshot);
|
|
12863
12936
|
heldLocks.delete(held.normalizedTargetPath);
|
|
@@ -12880,29 +12953,29 @@ function createSyncHeldLockHandle(held) {
|
|
|
12880
12953
|
};
|
|
12881
12954
|
}
|
|
12882
12955
|
function canonicalLockParentSync(parent) {
|
|
12883
|
-
return process.platform === "win32" ?
|
|
12956
|
+
return process.platform === "win32" ? fs10.realpathSync.native(parent) : fs10.realpathSync(parent);
|
|
12884
12957
|
}
|
|
12885
12958
|
function normalizeTargetPath(targetPath) {
|
|
12886
|
-
const resolved =
|
|
12887
|
-
|
|
12959
|
+
const resolved = path13.resolve(targetPath);
|
|
12960
|
+
fs10.mkdirSync(path13.dirname(resolved), { recursive: true });
|
|
12888
12961
|
try {
|
|
12889
|
-
return
|
|
12962
|
+
return path13.join(canonicalLockParentSync(path13.dirname(resolved)), path13.basename(resolved));
|
|
12890
12963
|
} catch {
|
|
12891
12964
|
return resolved;
|
|
12892
12965
|
}
|
|
12893
12966
|
}
|
|
12894
12967
|
function boundedLockPath(lockPath, lockRoot) {
|
|
12895
|
-
const resolved =
|
|
12968
|
+
const resolved = path13.resolve(lockPath);
|
|
12896
12969
|
if (!lockRoot)
|
|
12897
12970
|
return resolved;
|
|
12898
12971
|
relativeSidecarLockPath(lockRoot, resolved);
|
|
12899
|
-
const parent =
|
|
12972
|
+
const parent = path13.dirname(resolved);
|
|
12900
12973
|
const parentReal = canonicalLockParentSync(parent);
|
|
12901
|
-
const parentRelative =
|
|
12902
|
-
if (parentRelative === ".." || parentRelative.startsWith(`..${
|
|
12974
|
+
const parentRelative = path13.relative(lockRoot.rootReal, parentReal);
|
|
12975
|
+
if (parentRelative === ".." || parentRelative.startsWith(`..${path13.sep}`) || path13.isAbsolute(parentRelative)) {
|
|
12903
12976
|
throw new FsSafeError("outside-workspace", "sidecar lock parent is outside lockRoot");
|
|
12904
12977
|
}
|
|
12905
|
-
return
|
|
12978
|
+
return path13.join(parentReal, path13.basename(resolved));
|
|
12906
12979
|
}
|
|
12907
12980
|
function defaultShouldReclaim(snapshot, staleMs, nowMs) {
|
|
12908
12981
|
const createdAtMs = sidecarLockPayloadCreatedAtMs(snapshot.payload);
|
|
@@ -12912,7 +12985,7 @@ function defaultShouldReclaim(snapshot, staleMs, nowMs) {
|
|
|
12912
12985
|
}
|
|
12913
12986
|
function reclaimGuardExists(reclaimGuardPath) {
|
|
12914
12987
|
try {
|
|
12915
|
-
|
|
12988
|
+
fs10.lstatSync(reclaimGuardPath);
|
|
12916
12989
|
return true;
|
|
12917
12990
|
} catch (error) {
|
|
12918
12991
|
if (error.code === "ENOENT")
|
|
@@ -12976,19 +13049,19 @@ function acquireFileLockSync(targetPath, options) {
|
|
|
12976
13049
|
const { raw, ownershipToken } = serializeSidecarLockPayload(payload);
|
|
12977
13050
|
let lockFileCreateDenied = false;
|
|
12978
13051
|
try {
|
|
12979
|
-
const noFollow = process.platform !== "win32" && typeof
|
|
13052
|
+
const noFollow = process.platform !== "win32" && typeof fs10.constants.O_NOFOLLOW === "number" ? fs10.constants.O_NOFOLLOW : 0;
|
|
12980
13053
|
try {
|
|
12981
|
-
fd =
|
|
13054
|
+
fd = fs10.openSync(lockPath, fs10.constants.O_WRONLY | fs10.constants.O_CREAT | fs10.constants.O_EXCL | noFollow, 384);
|
|
12982
13055
|
} catch (error) {
|
|
12983
13056
|
lockFileCreateDenied = isTransientLockFileDenial(error, lockPath);
|
|
12984
13057
|
throw error;
|
|
12985
13058
|
}
|
|
12986
|
-
|
|
12987
|
-
|
|
13059
|
+
fs10.writeFileSync(fd, raw, "utf8");
|
|
13060
|
+
fs10.fsyncSync(fd);
|
|
12988
13061
|
const snapshot = {
|
|
12989
13062
|
raw,
|
|
12990
13063
|
payload,
|
|
12991
|
-
stat:
|
|
13064
|
+
stat: fs10.fstatSync(fd),
|
|
12992
13065
|
ownershipToken
|
|
12993
13066
|
};
|
|
12994
13067
|
const createdHeld = {
|
|
@@ -13023,8 +13096,8 @@ function acquireFileLockSync(targetPath, options) {
|
|
|
13023
13096
|
return returnedHandle;
|
|
13024
13097
|
} catch (error) {
|
|
13025
13098
|
if (fd !== undefined) {
|
|
13026
|
-
const failed = { payload: null, stat:
|
|
13027
|
-
|
|
13099
|
+
const failed = { payload: null, stat: fs10.fstatSync(fd) };
|
|
13100
|
+
fs10.closeSync(fd);
|
|
13028
13101
|
fd = undefined;
|
|
13029
13102
|
removeSidecarLockIfUnchangedSync(lockPath, failed);
|
|
13030
13103
|
}
|
|
@@ -13073,7 +13146,7 @@ function acquireFileLockSync(targetPath, options) {
|
|
|
13073
13146
|
})) {
|
|
13074
13147
|
let ownsReclaimGuard = false;
|
|
13075
13148
|
try {
|
|
13076
|
-
|
|
13149
|
+
fs10.mkdirSync(reclaimGuardPath);
|
|
13077
13150
|
ownsReclaimGuard = true;
|
|
13078
13151
|
if (removeSidecarLockIfUnchangedSync(lockPath, snapshot))
|
|
13079
13152
|
continue;
|
|
@@ -13086,7 +13159,7 @@ function acquireFileLockSync(targetPath, options) {
|
|
|
13086
13159
|
} finally {
|
|
13087
13160
|
if (ownsReclaimGuard) {
|
|
13088
13161
|
try {
|
|
13089
|
-
|
|
13162
|
+
fs10.rmdirSync(reclaimGuardPath);
|
|
13090
13163
|
} catch {}
|
|
13091
13164
|
}
|
|
13092
13165
|
}
|
|
@@ -13119,13 +13192,13 @@ var init_file_lock = __esm(() => {
|
|
|
13119
13192
|
|
|
13120
13193
|
// packages/workit-core/src/core/package-root.ts
|
|
13121
13194
|
import { existsSync as existsSync3 } from "node:fs";
|
|
13122
|
-
import
|
|
13195
|
+
import path14 from "node:path";
|
|
13123
13196
|
import { fileURLToPath } from "node:url";
|
|
13124
13197
|
var packageRoot = () => {
|
|
13125
|
-
let dir =
|
|
13198
|
+
let dir = path14.dirname(fileURLToPath(import.meta.url));
|
|
13126
13199
|
while (true) {
|
|
13127
|
-
const parent =
|
|
13128
|
-
if (existsSync3(
|
|
13200
|
+
const parent = path14.dirname(dir);
|
|
13201
|
+
if (existsSync3(path14.join(dir, "package.json")) || parent === dir)
|
|
13129
13202
|
return dir;
|
|
13130
13203
|
dir = parent;
|
|
13131
13204
|
}
|
|
@@ -13134,12 +13207,12 @@ var init_package_root = () => {};
|
|
|
13134
13207
|
|
|
13135
13208
|
// packages/workit-core/src/store/event-log.ts
|
|
13136
13209
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
13137
|
-
import
|
|
13138
|
-
import
|
|
13210
|
+
import fs11 from "node:fs";
|
|
13211
|
+
import path15 from "node:path";
|
|
13139
13212
|
function readLog(file, from = 0, expectSeq = null) {
|
|
13140
13213
|
let fd;
|
|
13141
13214
|
try {
|
|
13142
|
-
fd =
|
|
13215
|
+
fd = fs11.openSync(file, "r");
|
|
13143
13216
|
} catch (error) {
|
|
13144
13217
|
if (error.code === "ENOENT")
|
|
13145
13218
|
return null;
|
|
@@ -13148,13 +13221,13 @@ function readLog(file, from = 0, expectSeq = null) {
|
|
|
13148
13221
|
let bytes;
|
|
13149
13222
|
let size;
|
|
13150
13223
|
try {
|
|
13151
|
-
size =
|
|
13224
|
+
size = fs11.fstatSync(fd).size;
|
|
13152
13225
|
if (from > size)
|
|
13153
13226
|
throw new LogDamage(`${file}: shorter than its snapshot`);
|
|
13154
13227
|
bytes = Buffer.alloc(size - from);
|
|
13155
13228
|
let read = 0;
|
|
13156
13229
|
while (read < bytes.length) {
|
|
13157
|
-
const got =
|
|
13230
|
+
const got = fs11.readSync(fd, bytes, read, bytes.length - read, from + read);
|
|
13158
13231
|
if (got === 0)
|
|
13159
13232
|
break;
|
|
13160
13233
|
read += got;
|
|
@@ -13162,7 +13235,7 @@ function readLog(file, from = 0, expectSeq = null) {
|
|
|
13162
13235
|
bytes = bytes.subarray(0, read);
|
|
13163
13236
|
size = from + read;
|
|
13164
13237
|
} finally {
|
|
13165
|
-
|
|
13238
|
+
fs11.closeSync(fd);
|
|
13166
13239
|
}
|
|
13167
13240
|
const events = [];
|
|
13168
13241
|
let start = 0;
|
|
@@ -13188,46 +13261,46 @@ function readLog(file, from = 0, expectSeq = null) {
|
|
|
13188
13261
|
function appendEvent(file, event, validEnd) {
|
|
13189
13262
|
const line = Buffer.from(`${JSON.stringify(event)}
|
|
13190
13263
|
`, "utf8");
|
|
13191
|
-
const created = !
|
|
13192
|
-
if (!created &&
|
|
13193
|
-
const cut =
|
|
13264
|
+
const created = !fs11.existsSync(file);
|
|
13265
|
+
if (!created && fs11.statSync(file).size !== validEnd) {
|
|
13266
|
+
const cut = fs11.openSync(file, "r+");
|
|
13194
13267
|
try {
|
|
13195
|
-
|
|
13196
|
-
|
|
13268
|
+
fs11.ftruncateSync(cut, validEnd);
|
|
13269
|
+
fs11.fsyncSync(cut);
|
|
13197
13270
|
} finally {
|
|
13198
|
-
|
|
13271
|
+
fs11.closeSync(cut);
|
|
13199
13272
|
}
|
|
13200
13273
|
}
|
|
13201
|
-
const fd =
|
|
13274
|
+
const fd = fs11.openSync(file, "a", 384);
|
|
13202
13275
|
try {
|
|
13203
13276
|
let written = 0;
|
|
13204
13277
|
while (written < line.length)
|
|
13205
|
-
written +=
|
|
13206
|
-
|
|
13278
|
+
written += fs11.writeSync(fd, line, written, line.length - written);
|
|
13279
|
+
fs11.fsyncSync(fd);
|
|
13207
13280
|
} finally {
|
|
13208
|
-
|
|
13281
|
+
fs11.closeSync(fd);
|
|
13209
13282
|
}
|
|
13210
13283
|
if (created)
|
|
13211
|
-
fsyncDirectory(
|
|
13284
|
+
fsyncDirectory(path15.dirname(file));
|
|
13212
13285
|
return validEnd;
|
|
13213
13286
|
}
|
|
13214
13287
|
function replaceFile(file, bytes, durable) {
|
|
13215
13288
|
const temporary = `${file}.${process.pid}.${randomUUID2()}.tmp`;
|
|
13216
13289
|
try {
|
|
13217
|
-
const fd =
|
|
13290
|
+
const fd = fs11.openSync(temporary, "wx", 384);
|
|
13218
13291
|
try {
|
|
13219
|
-
|
|
13292
|
+
fs11.writeSync(fd, bytes);
|
|
13220
13293
|
if (durable)
|
|
13221
|
-
|
|
13294
|
+
fs11.fsyncSync(fd);
|
|
13222
13295
|
} finally {
|
|
13223
|
-
|
|
13296
|
+
fs11.closeSync(fd);
|
|
13224
13297
|
}
|
|
13225
13298
|
renameWithRetry(temporary, file);
|
|
13226
13299
|
if (durable)
|
|
13227
|
-
fsyncDirectory(
|
|
13300
|
+
fsyncDirectory(path15.dirname(file));
|
|
13228
13301
|
} catch (error) {
|
|
13229
13302
|
try {
|
|
13230
|
-
|
|
13303
|
+
fs11.unlinkSync(temporary);
|
|
13231
13304
|
} catch {}
|
|
13232
13305
|
throw error;
|
|
13233
13306
|
}
|
|
@@ -13248,11 +13321,11 @@ var EVENT_VERSION = 1, LogDamage, isObject4 = (value) => typeof value === "objec
|
|
|
13248
13321
|
return value;
|
|
13249
13322
|
}, fsyncDirectory = (dir) => {
|
|
13250
13323
|
try {
|
|
13251
|
-
const fd =
|
|
13324
|
+
const fd = fs11.openSync(dir, "r");
|
|
13252
13325
|
try {
|
|
13253
|
-
|
|
13326
|
+
fs11.fsyncSync(fd);
|
|
13254
13327
|
} finally {
|
|
13255
|
-
|
|
13328
|
+
fs11.closeSync(fd);
|
|
13256
13329
|
}
|
|
13257
13330
|
} catch (error) {
|
|
13258
13331
|
if (process.platform !== "win32")
|
|
@@ -13275,7 +13348,7 @@ var EVENT_VERSION = 1, LogDamage, isObject4 = (value) => typeof value === "objec
|
|
|
13275
13348
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5 * (attempt + 1));
|
|
13276
13349
|
}
|
|
13277
13350
|
}
|
|
13278
|
-
}, renameWithRetry = (from, to) => retryTransient(() =>
|
|
13351
|
+
}, renameWithRetry = (from, to) => retryTransient(() => fs11.renameSync(from, to));
|
|
13279
13352
|
var init_event_log = __esm(() => {
|
|
13280
13353
|
LogDamage = class LogDamage extends Error {
|
|
13281
13354
|
upgrade;
|
|
@@ -13394,7 +13467,7 @@ var isPlainObject2 = (value) => typeof value === "object" && value !== null && !
|
|
|
13394
13467
|
});
|
|
13395
13468
|
|
|
13396
13469
|
// packages/workit-core/src/store/reduce.ts
|
|
13397
|
-
import { createHash as
|
|
13470
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
13398
13471
|
function reduce(state, event, blobs) {
|
|
13399
13472
|
const data = event.data;
|
|
13400
13473
|
const known = KNOWN_TYPES.has(event.type);
|
|
@@ -13461,7 +13534,7 @@ function eventType(before, after) {
|
|
|
13461
13534
|
return "task.noted";
|
|
13462
13535
|
return "task.updated";
|
|
13463
13536
|
}
|
|
13464
|
-
var OPENING_TYPES, KNOWN_TYPES, isObject5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isKey = (value) => isObject5(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string"), BLOB_REF = "$blob", blobRef = (value) => isObject5(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null, blobDigest = (value) =>
|
|
13537
|
+
var OPENING_TYPES, KNOWN_TYPES, isObject5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isKey = (value) => isObject5(value) && typeof value.key === "string" && (value.kind === "branch" || value.kind === "detached" || value.kind === "dir") && (value.branch === null || typeof value.branch === "string"), BLOB_REF = "$blob", blobRef = (value) => isObject5(value) && Object.keys(value).length === 1 && typeof value[BLOB_REF] === "string" && /^[0-9a-f]{64}$/.test(value[BLOB_REF]) ? value[BLOB_REF] : null, blobDigest = (value) => createHash10("sha256").update(JSON.stringify(value)).digest("hex"), toBlob = (value, blobs) => {
|
|
13465
13538
|
if (!isObject5(value))
|
|
13466
13539
|
return value;
|
|
13467
13540
|
const digest = blobDigest(value);
|
|
@@ -13532,9 +13605,9 @@ var init_notes = __esm(() => {
|
|
|
13532
13605
|
});
|
|
13533
13606
|
|
|
13534
13607
|
// packages/workit-core/src/core/task-store.ts
|
|
13535
|
-
import { createHash as
|
|
13536
|
-
import * as
|
|
13537
|
-
import
|
|
13608
|
+
import { createHash as createHash11, randomUUID as randomUUID3 } from "node:crypto";
|
|
13609
|
+
import * as fs12 from "node:fs";
|
|
13610
|
+
import path16 from "node:path";
|
|
13538
13611
|
|
|
13539
13612
|
class TaskStore {
|
|
13540
13613
|
root;
|
|
@@ -13546,8 +13619,8 @@ class TaskStore {
|
|
|
13546
13619
|
migrationChecked = false;
|
|
13547
13620
|
compactDue = new Set;
|
|
13548
13621
|
constructor(root, options = {}) {
|
|
13549
|
-
const resolved =
|
|
13550
|
-
this.origin =
|
|
13622
|
+
const resolved = path16.resolve(root);
|
|
13623
|
+
this.origin = fs12.existsSync(resolved) ? fs12.realpathSync(resolved) : resolved;
|
|
13551
13624
|
this.located = resolveStore(this.origin);
|
|
13552
13625
|
this.root = checkoutRootOf(this.origin, this.located);
|
|
13553
13626
|
this.lockTimeoutMs = options.lockTimeoutMs ?? defaultLockTimeout();
|
|
@@ -13555,7 +13628,7 @@ class TaskStore {
|
|
|
13555
13628
|
this.migrateOnRead = options.migrateOnRead;
|
|
13556
13629
|
}
|
|
13557
13630
|
location() {
|
|
13558
|
-
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared &&
|
|
13631
|
+
if (this.located !== undefined && !(this.located instanceof Error) && !this.located.shared && fs12.existsSync(path16.join(this.root, ".git"))) {
|
|
13559
13632
|
this.located = undefined;
|
|
13560
13633
|
this.migrationChecked = false;
|
|
13561
13634
|
}
|
|
@@ -13619,7 +13692,7 @@ class TaskStore {
|
|
|
13619
13692
|
const tasksDir = this.paths().tasks;
|
|
13620
13693
|
let names;
|
|
13621
13694
|
try {
|
|
13622
|
-
names =
|
|
13695
|
+
names = fs12.existsSync(tasksDir) ? fs12.readdirSync(tasksDir).filter((name) => validId(name)) : [];
|
|
13623
13696
|
} catch (error) {
|
|
13624
13697
|
return failure2("storage_error", `unable to list tasks: ${String(error)}`, {
|
|
13625
13698
|
path: tasksDir
|
|
@@ -13660,7 +13733,7 @@ class TaskStore {
|
|
|
13660
13733
|
const file = this.paths().workspace;
|
|
13661
13734
|
let bytes;
|
|
13662
13735
|
try {
|
|
13663
|
-
bytes = retryTransient(() =>
|
|
13736
|
+
bytes = retryTransient(() => fs12.readFileSync(file, "utf8"));
|
|
13664
13737
|
} catch (error) {
|
|
13665
13738
|
if (error.code === "ENOENT")
|
|
13666
13739
|
return success(null, null, null);
|
|
@@ -13711,7 +13784,7 @@ class TaskStore {
|
|
|
13711
13784
|
const moved = this.bindLocked(again.data.id, key, input.now);
|
|
13712
13785
|
return moved.ok ? success(moved.data.revision, null, { task: moved.data, created: false, key }) : moved;
|
|
13713
13786
|
}
|
|
13714
|
-
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" :
|
|
13787
|
+
const label = key.kind === "branch" ? `branch ${key.branch}` : key.kind === "detached" ? "a detached HEAD" : path16.basename(this.root) || this.root;
|
|
13715
13788
|
const intent = {
|
|
13716
13789
|
objective: input.objective?.trim() || `Work on ${label}`,
|
|
13717
13790
|
scope: { description: `the checkout (${label})`, paths: ["."], exclusions: [] },
|
|
@@ -13777,14 +13850,14 @@ class TaskStore {
|
|
|
13777
13850
|
const branch = key.ok ? key.data.branch : null;
|
|
13778
13851
|
if (!branch || !location.ok)
|
|
13779
13852
|
return success(null, null, null);
|
|
13780
|
-
const common =
|
|
13781
|
-
const heads =
|
|
13782
|
-
const headLog = location.data.git ?
|
|
13853
|
+
const common = path16.dirname(location.data.dir);
|
|
13854
|
+
const heads = path16.join(common, "logs", "refs", "heads");
|
|
13855
|
+
const headLog = location.data.git ? path16.join(location.data.git.gitDir, "logs", "HEAD") : "";
|
|
13783
13856
|
const signatures = [
|
|
13784
|
-
|
|
13857
|
+
path16.join(heads, branch),
|
|
13785
13858
|
headLog,
|
|
13786
13859
|
heads,
|
|
13787
|
-
|
|
13860
|
+
path16.join(common, "packed-refs")
|
|
13788
13861
|
].map((file) => fileSignature(file) ?? "-");
|
|
13789
13862
|
const slot = `${location.data.dir}\x00${headLog}\x00${branch}`;
|
|
13790
13863
|
let resolved = origins.get(slot);
|
|
@@ -13796,7 +13869,7 @@ class TaskStore {
|
|
|
13796
13869
|
aliases.push(rename.from);
|
|
13797
13870
|
const start = branchStart(location.data, branch, aliases);
|
|
13798
13871
|
const slash = start?.indexOf("/") ?? -1;
|
|
13799
|
-
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(
|
|
13872
|
+
const remote = slash > 0 && !refExists(common, `refs/heads/${start}`) && (refExists(common, `refs/remotes/${start}`) || readText(path16.join(common, "config")).includes(`[remote "${start.slice(0, slash)}"]`));
|
|
13800
13873
|
const name = start && (remote ? start.slice(slash + 1) : start);
|
|
13801
13874
|
resolved = {
|
|
13802
13875
|
signature: signatures.join("|"),
|
|
@@ -14034,13 +14107,13 @@ class TaskStore {
|
|
|
14034
14107
|
if (!ready.ok)
|
|
14035
14108
|
return ready;
|
|
14036
14109
|
const dirs = this.paths();
|
|
14037
|
-
const recovery =
|
|
14038
|
-
if (
|
|
14110
|
+
const recovery = path16.join(this.root, ".workit", "recovery");
|
|
14111
|
+
if (fs12.existsSync(recovery)) {
|
|
14039
14112
|
let files = 0;
|
|
14040
14113
|
let bytes = 0;
|
|
14041
14114
|
try {
|
|
14042
|
-
for (const name of
|
|
14043
|
-
const stat =
|
|
14115
|
+
for (const name of fs12.readdirSync(recovery)) {
|
|
14116
|
+
const stat = fs12.lstatSync(path16.join(recovery, name));
|
|
14044
14117
|
if (!stat.isFile())
|
|
14045
14118
|
continue;
|
|
14046
14119
|
files += 1;
|
|
@@ -14049,17 +14122,17 @@ class TaskStore {
|
|
|
14049
14122
|
} catch {}
|
|
14050
14123
|
const remove = options.pruneRecovery === true && !dryRun;
|
|
14051
14124
|
if (remove)
|
|
14052
|
-
|
|
14125
|
+
fs12.rmSync(recovery, { recursive: true, force: true });
|
|
14053
14126
|
report.legacyRecovery = { path: recovery, files, bytes, removed: remove };
|
|
14054
14127
|
}
|
|
14055
|
-
if (!
|
|
14128
|
+
if (!fs12.existsSync(dirs.tasks))
|
|
14056
14129
|
return success(null, null, report);
|
|
14057
|
-
const names =
|
|
14130
|
+
const names = fs12.readdirSync(dirs.tasks).filter((name) => validId(name));
|
|
14058
14131
|
for (const name of names) {
|
|
14059
14132
|
const file = this.eventsPath(name);
|
|
14060
14133
|
let size = 0;
|
|
14061
14134
|
try {
|
|
14062
|
-
size =
|
|
14135
|
+
size = fs12.statSync(file).size;
|
|
14063
14136
|
} catch {
|
|
14064
14137
|
continue;
|
|
14065
14138
|
}
|
|
@@ -14087,16 +14160,16 @@ class TaskStore {
|
|
|
14087
14160
|
const references = new Set;
|
|
14088
14161
|
for (const name of names)
|
|
14089
14162
|
try {
|
|
14090
|
-
for (const match of
|
|
14163
|
+
for (const match of fs12.readFileSync(this.eventsPath(name), "utf8").matchAll(/"\$blob":"([0-9a-f]{64})"/g))
|
|
14091
14164
|
references.add(match[1]);
|
|
14092
14165
|
} catch {}
|
|
14093
|
-
if (
|
|
14094
|
-
for (const name of
|
|
14166
|
+
if (fs12.existsSync(dirs.blobs))
|
|
14167
|
+
for (const name of fs12.readdirSync(dirs.blobs)) {
|
|
14095
14168
|
const digest = name.replace(/\.json$/, "");
|
|
14096
|
-
const file =
|
|
14169
|
+
const file = path16.join(dirs.blobs, name);
|
|
14097
14170
|
let stat;
|
|
14098
14171
|
try {
|
|
14099
|
-
stat =
|
|
14172
|
+
stat = fs12.lstatSync(file);
|
|
14100
14173
|
} catch {
|
|
14101
14174
|
continue;
|
|
14102
14175
|
}
|
|
@@ -14107,11 +14180,11 @@ class TaskStore {
|
|
|
14107
14180
|
report.blobs.removed += 1;
|
|
14108
14181
|
report.blobs.removedBytes += stat.size;
|
|
14109
14182
|
if (!dryRun)
|
|
14110
|
-
|
|
14183
|
+
fs12.rmSync(file, { force: true });
|
|
14111
14184
|
}
|
|
14112
14185
|
return success(null, null, null);
|
|
14113
14186
|
};
|
|
14114
|
-
const swept = dryRun ? sweep() : this.withLock(
|
|
14187
|
+
const swept = dryRun ? sweep() : this.withLock(path16.join(dirs.dir, "gc.lock"), sweep);
|
|
14115
14188
|
if (!swept.ok)
|
|
14116
14189
|
return swept;
|
|
14117
14190
|
const temporaryDirs = [
|
|
@@ -14119,17 +14192,17 @@ class TaskStore {
|
|
|
14119
14192
|
dirs.tasks,
|
|
14120
14193
|
dirs.blobs,
|
|
14121
14194
|
dirs.checkout,
|
|
14122
|
-
...names.map((name) =>
|
|
14195
|
+
...names.map((name) => path16.join(dirs.tasks, name))
|
|
14123
14196
|
];
|
|
14124
14197
|
for (const directory of temporaryDirs) {
|
|
14125
|
-
if (!
|
|
14198
|
+
if (!fs12.existsSync(directory))
|
|
14126
14199
|
continue;
|
|
14127
|
-
for (const name of
|
|
14200
|
+
for (const name of fs12.readdirSync(directory)) {
|
|
14128
14201
|
if (!name.endsWith(".tmp") && !name.endsWith(".probe"))
|
|
14129
14202
|
continue;
|
|
14130
|
-
const file =
|
|
14203
|
+
const file = path16.join(directory, name);
|
|
14131
14204
|
try {
|
|
14132
|
-
const stat =
|
|
14205
|
+
const stat = fs12.lstatSync(file);
|
|
14133
14206
|
if (!stat.isFile() || nowMs - stat.mtimeMs <= STALE_TEMPORARY_MS)
|
|
14134
14207
|
continue;
|
|
14135
14208
|
} catch {
|
|
@@ -14137,37 +14210,37 @@ class TaskStore {
|
|
|
14137
14210
|
}
|
|
14138
14211
|
report.temporary.removed += 1;
|
|
14139
14212
|
if (!dryRun)
|
|
14140
|
-
|
|
14213
|
+
fs12.rmSync(file, { force: true });
|
|
14141
14214
|
}
|
|
14142
14215
|
}
|
|
14143
14216
|
return success(null, null, report);
|
|
14144
14217
|
}
|
|
14145
14218
|
paths() {
|
|
14146
14219
|
const location = this.location();
|
|
14147
|
-
const dir = location.ok ? location.data.dir :
|
|
14148
|
-
const checkout =
|
|
14220
|
+
const dir = location.ok ? location.data.dir : path16.join(this.root, ".workit");
|
|
14221
|
+
const checkout = path16.join(dir, "checkouts", checkoutSlug(this.root));
|
|
14149
14222
|
return {
|
|
14150
14223
|
dir,
|
|
14151
14224
|
shared: location.ok ? location.data.shared : false,
|
|
14152
|
-
marker:
|
|
14225
|
+
marker: path16.join(dir, "store.json"),
|
|
14153
14226
|
checkout,
|
|
14154
|
-
workspace:
|
|
14155
|
-
checkoutLock:
|
|
14156
|
-
tasks:
|
|
14157
|
-
index:
|
|
14158
|
-
blobs:
|
|
14159
|
-
legacy:
|
|
14160
|
-
v2:
|
|
14227
|
+
workspace: path16.join(checkout, "workspace.json"),
|
|
14228
|
+
checkoutLock: path16.join(checkout, "metadata.lock"),
|
|
14229
|
+
tasks: path16.join(dir, "tasks"),
|
|
14230
|
+
index: path16.join(dir, "task-index.json"),
|
|
14231
|
+
blobs: path16.join(dir, "blobs", "candidates"),
|
|
14232
|
+
legacy: path16.join(dir, "legacy", checkoutSlug(this.root), "v2"),
|
|
14233
|
+
v2: path16.join(this.root, ".workit")
|
|
14161
14234
|
};
|
|
14162
14235
|
}
|
|
14163
14236
|
eventsPath(taskId) {
|
|
14164
|
-
return
|
|
14237
|
+
return path16.join(this.paths().tasks, taskId, "events.jsonl");
|
|
14165
14238
|
}
|
|
14166
14239
|
snapshotPath(taskId) {
|
|
14167
|
-
return
|
|
14240
|
+
return path16.join(this.paths().tasks, taskId, "snapshot.json");
|
|
14168
14241
|
}
|
|
14169
14242
|
taskLockPath(taskId) {
|
|
14170
|
-
return
|
|
14243
|
+
return path16.join(this.paths().tasks, taskId, "lock");
|
|
14171
14244
|
}
|
|
14172
14245
|
ready(write = false) {
|
|
14173
14246
|
const location = this.location();
|
|
@@ -14177,7 +14250,7 @@ class TaskStore {
|
|
|
14177
14250
|
return success(null, null, null);
|
|
14178
14251
|
const dirs = this.paths();
|
|
14179
14252
|
try {
|
|
14180
|
-
const marker = JSON.parse(
|
|
14253
|
+
const marker = JSON.parse(fs12.readFileSync(dirs.marker, "utf8"));
|
|
14181
14254
|
if (typeof marker.version === "number" && marker.version > STORE_FORMAT)
|
|
14182
14255
|
return failure2("recovery_required", `the workit store at ${dirs.dir} has format ${marker.version}; upgrade Workit to use it`, { path: dirs.marker });
|
|
14183
14256
|
} catch {}
|
|
@@ -14206,21 +14279,21 @@ class TaskStore {
|
|
|
14206
14279
|
return {
|
|
14207
14280
|
read: (digest) => {
|
|
14208
14281
|
try {
|
|
14209
|
-
return JSON.parse(
|
|
14282
|
+
return JSON.parse(fs12.readFileSync(path16.join(dir, `${digest}.json`), "utf8"));
|
|
14210
14283
|
} catch (error) {
|
|
14211
14284
|
throw new LogDamage(`stored candidate ${digest} is missing or unreadable: ${String(error)}`);
|
|
14212
14285
|
}
|
|
14213
14286
|
},
|
|
14214
14287
|
write: (digest, value) => {
|
|
14215
|
-
const file =
|
|
14216
|
-
if (
|
|
14288
|
+
const file = path16.join(dir, `${digest}.json`);
|
|
14289
|
+
if (fs12.existsSync(file)) {
|
|
14217
14290
|
const stamp = new Date;
|
|
14218
14291
|
try {
|
|
14219
|
-
|
|
14292
|
+
fs12.utimesSync(file, stamp, stamp);
|
|
14220
14293
|
return;
|
|
14221
14294
|
} catch {}
|
|
14222
14295
|
}
|
|
14223
|
-
|
|
14296
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
14224
14297
|
replaceFile(file, JSON.stringify(value), true);
|
|
14225
14298
|
}
|
|
14226
14299
|
};
|
|
@@ -14302,7 +14375,7 @@ class TaskStore {
|
|
|
14302
14375
|
}
|
|
14303
14376
|
readSnapshot(taskId) {
|
|
14304
14377
|
try {
|
|
14305
|
-
const value = JSON.parse(
|
|
14378
|
+
const value = JSON.parse(fs12.readFileSync(this.snapshotPath(taskId), "utf8"));
|
|
14306
14379
|
if (!isObject6(value) || value.v !== 1 || value.task !== taskId || typeof value.seq !== "number" || typeof value.lastId !== "string" || typeof value.lastStart !== "number" || typeof value.end !== "number" || !isObject6(value.record))
|
|
14307
14380
|
return null;
|
|
14308
14381
|
return value;
|
|
@@ -14404,8 +14477,8 @@ class TaskStore {
|
|
|
14404
14477
|
}
|
|
14405
14478
|
}
|
|
14406
14479
|
openTask(record, type, key, legacy = null) {
|
|
14407
|
-
const dir =
|
|
14408
|
-
|
|
14480
|
+
const dir = path16.join(this.paths().tasks, record.id);
|
|
14481
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
14409
14482
|
const blobs = this.blobStore();
|
|
14410
14483
|
const bound = key ? { ...key, boundAt: key.boundAt ?? new Date().toISOString() } : null;
|
|
14411
14484
|
const event = this.event(record.id, 1, type, {
|
|
@@ -14457,11 +14530,11 @@ class TaskStore {
|
|
|
14457
14530
|
} catch {}
|
|
14458
14531
|
if (!latest || latest.events[0]?.id !== last.id)
|
|
14459
14532
|
return failure2("busy", "the task log changed during compaction; retry", { taskId });
|
|
14460
|
-
const appended =
|
|
14533
|
+
const appended = fs12.readFileSync(file).subarray(log.end, latest.end);
|
|
14461
14534
|
const bytes = Buffer.concat([Buffer.from(prefix, "utf8"), appended]);
|
|
14462
14535
|
replaceFile(file, bytes.toString("utf8"), true);
|
|
14463
14536
|
try {
|
|
14464
|
-
|
|
14537
|
+
fs12.rmSync(this.snapshotPath(taskId), { force: true });
|
|
14465
14538
|
} catch {}
|
|
14466
14539
|
const reloaded = this.load(taskId);
|
|
14467
14540
|
if (reloaded.ok && reloaded.data)
|
|
@@ -14474,7 +14547,7 @@ class TaskStore {
|
|
|
14474
14547
|
}
|
|
14475
14548
|
countEvents(file) {
|
|
14476
14549
|
try {
|
|
14477
|
-
const bytes =
|
|
14550
|
+
const bytes = fs12.readFileSync(file);
|
|
14478
14551
|
let count = 0;
|
|
14479
14552
|
for (let index = bytes.indexOf(10);index >= 0; index = bytes.indexOf(10, index + 1))
|
|
14480
14553
|
count += 1;
|
|
@@ -14496,8 +14569,8 @@ class TaskStore {
|
|
|
14496
14569
|
return bound.ok ? success(null, null, bound.data[0] ?? null) : bound;
|
|
14497
14570
|
}
|
|
14498
14571
|
withKeyLock(key, operation) {
|
|
14499
|
-
const digest =
|
|
14500
|
-
return this.withLock(
|
|
14572
|
+
const digest = createHash11("sha256").update(key).digest("hex").slice(0, 32);
|
|
14573
|
+
return this.withLock(path16.join(this.paths().dir, "keys", `${digest}.lock`), operation);
|
|
14501
14574
|
}
|
|
14502
14575
|
bindLocked(taskId, key, timestamp) {
|
|
14503
14576
|
const current = this.readWorkspace();
|
|
@@ -14638,7 +14711,7 @@ class TaskStore {
|
|
|
14638
14711
|
writeWorkspace(record) {
|
|
14639
14712
|
const file = this.paths().workspace;
|
|
14640
14713
|
try {
|
|
14641
|
-
|
|
14714
|
+
fs12.mkdirSync(path16.dirname(file), { recursive: true });
|
|
14642
14715
|
replaceFile(file, `${canonicalJson(record)}
|
|
14643
14716
|
`, true);
|
|
14644
14717
|
return success(null, null, null);
|
|
@@ -14648,7 +14721,7 @@ class TaskStore {
|
|
|
14648
14721
|
}
|
|
14649
14722
|
readIndex() {
|
|
14650
14723
|
try {
|
|
14651
|
-
const value = JSON.parse(
|
|
14724
|
+
const value = JSON.parse(fs12.readFileSync(this.paths().index, "utf8"));
|
|
14652
14725
|
if (!isObject6(value) || value.version !== INDEX_VERSION || !isObject6(value.tasks))
|
|
14653
14726
|
return {};
|
|
14654
14727
|
const tasks = {};
|
|
@@ -14662,7 +14735,7 @@ class TaskStore {
|
|
|
14662
14735
|
}
|
|
14663
14736
|
writeIndex(entries) {
|
|
14664
14737
|
try {
|
|
14665
|
-
|
|
14738
|
+
fs12.mkdirSync(this.paths().tasks, { recursive: true });
|
|
14666
14739
|
replaceFile(this.paths().index, JSON.stringify({
|
|
14667
14740
|
version: INDEX_VERSION,
|
|
14668
14741
|
tasks: Object.fromEntries(entries.map((entry) => [entry.id, entry]))
|
|
@@ -14716,23 +14789,23 @@ class TaskStore {
|
|
|
14716
14789
|
return failure2("revision_conflict", "workspace revision does not match; omit expectedWorkspaceRevision to use the current record", { expectedWorkspaceRevision: expected, actualWorkspaceRevision: actual });
|
|
14717
14790
|
}
|
|
14718
14791
|
v2Dirs() {
|
|
14719
|
-
return [...new Set([this.root, this.origin])].map((dir) =>
|
|
14792
|
+
return [...new Set([this.root, this.origin])].map((dir) => path16.join(dir, ".workit"));
|
|
14720
14793
|
}
|
|
14721
14794
|
pendingMigrations() {
|
|
14722
14795
|
return this.v2Dirs().filter((dir) => {
|
|
14723
|
-
const raw = this.readV2Workspace(
|
|
14796
|
+
const raw = this.readV2Workspace(path16.join(dir, "workspace.json"));
|
|
14724
14797
|
return raw !== null && raw !== TOMBSTONE;
|
|
14725
14798
|
});
|
|
14726
14799
|
}
|
|
14727
14800
|
migrateV2(v2) {
|
|
14728
14801
|
const dirs = this.paths();
|
|
14729
|
-
const v2Workspace =
|
|
14730
|
-
const v2Tasks =
|
|
14731
|
-
const legacy =
|
|
14802
|
+
const v2Workspace = path16.join(v2, "workspace.json");
|
|
14803
|
+
const v2Tasks = path16.join(v2, "tasks");
|
|
14804
|
+
const legacy = path16.join(dirs.dir, "legacy", checkoutSlug(path16.dirname(v2)), "v2");
|
|
14732
14805
|
const raw = this.readV2Workspace(v2Workspace);
|
|
14733
14806
|
if (raw === null || raw === TOMBSTONE)
|
|
14734
14807
|
return success(null, null, null);
|
|
14735
|
-
return this.withLock(dirs.checkoutLock, () => this.withLock(
|
|
14808
|
+
return this.withLock(dirs.checkoutLock, () => this.withLock(path16.join(v2, "metadata.lock"), () => {
|
|
14736
14809
|
const workspace = this.readV2Workspace(v2Workspace);
|
|
14737
14810
|
if (workspace === null || workspace === TOMBSTONE)
|
|
14738
14811
|
return success(null, null, null);
|
|
@@ -14741,7 +14814,7 @@ class TaskStore {
|
|
|
14741
14814
|
return failure2("recovery_required", `cannot migrate the 2.x store at ${v2}: ${parsedWorkspace.error}; move it aside to start fresh`, { path: v2Workspace });
|
|
14742
14815
|
let files = [];
|
|
14743
14816
|
try {
|
|
14744
|
-
files =
|
|
14817
|
+
files = fs12.readdirSync(v2Tasks).filter((name) => name.endsWith(".json") && validId(name.slice(0, -5))).filter((name) => !this.isStub(path16.join(v2Tasks, name)));
|
|
14745
14818
|
} catch {}
|
|
14746
14819
|
const current = this.readWorkspace();
|
|
14747
14820
|
if (!current.ok)
|
|
@@ -14759,22 +14832,22 @@ class TaskStore {
|
|
|
14759
14832
|
let skipped = 0;
|
|
14760
14833
|
const done = new Map;
|
|
14761
14834
|
try {
|
|
14762
|
-
|
|
14835
|
+
fs12.mkdirSync(path16.join(legacy, "tasks"), { recursive: true });
|
|
14763
14836
|
for (const name of ["workspace.json", "index.json"])
|
|
14764
|
-
if (
|
|
14765
|
-
|
|
14837
|
+
if (fs12.existsSync(path16.join(v2, name)))
|
|
14838
|
+
fs12.copyFileSync(path16.join(v2, name), path16.join(legacy, name));
|
|
14766
14839
|
for (const name of files) {
|
|
14767
14840
|
const id = name.slice(0, -5);
|
|
14768
|
-
const file =
|
|
14769
|
-
const bytes =
|
|
14841
|
+
const file = path16.join(v2Tasks, name);
|
|
14842
|
+
const bytes = fs12.readFileSync(file, "utf8");
|
|
14770
14843
|
const digest = sha256(bytes);
|
|
14771
|
-
|
|
14844
|
+
fs12.writeFileSync(path16.join(legacy, "tasks", name), bytes);
|
|
14772
14845
|
const parsed = this.parseRecord(bytes, taskRecordSchema, "2.x task");
|
|
14773
14846
|
if (!parsed.ok || parsed.data.id !== id)
|
|
14774
14847
|
return failure2("recovery_required", `cannot migrate 2.x task ${id}: ${parsed.ok ? "file name and record ID differ" : parsed.error}; move ${file} aside to continue`, { path: file });
|
|
14775
14848
|
const record = { ...parsed.data, workspaceId: target.id };
|
|
14776
|
-
const origin = { path:
|
|
14777
|
-
if (!
|
|
14849
|
+
const origin = { path: path16.join(legacy, "tasks", name), digest };
|
|
14850
|
+
if (!fs12.existsSync(this.eventsPath(id))) {
|
|
14778
14851
|
this.openTask(record, "migrated.from_v2", null, origin);
|
|
14779
14852
|
migrated += 1;
|
|
14780
14853
|
} else {
|
|
@@ -14809,8 +14882,8 @@ class TaskStore {
|
|
|
14809
14882
|
try {
|
|
14810
14883
|
let complete = true;
|
|
14811
14884
|
for (const [name, digest] of done) {
|
|
14812
|
-
const file =
|
|
14813
|
-
if (sha256(
|
|
14885
|
+
const file = path16.join(v2Tasks, name);
|
|
14886
|
+
if (sha256(fs12.readFileSync(file, "utf8")) !== digest) {
|
|
14814
14887
|
complete = false;
|
|
14815
14888
|
continue;
|
|
14816
14889
|
}
|
|
@@ -14820,7 +14893,7 @@ class TaskStore {
|
|
|
14820
14893
|
return failure2("busy", `the 2.x store at ${v2} changed during migration; retry`, {
|
|
14821
14894
|
path: v2
|
|
14822
14895
|
});
|
|
14823
|
-
|
|
14896
|
+
fs12.rmSync(path16.join(v2, "index.json"), { force: true });
|
|
14824
14897
|
this.writeTombstone(v2, target.id);
|
|
14825
14898
|
} catch (error) {
|
|
14826
14899
|
return failure2("storage_error", `cannot finish the 2.x migration: ${String(error)}`, {
|
|
@@ -14840,45 +14913,45 @@ class TaskStore {
|
|
|
14840
14913
|
}
|
|
14841
14914
|
adoptLocalStore() {
|
|
14842
14915
|
const dirs = this.paths();
|
|
14843
|
-
const marker =
|
|
14844
|
-
if (!dirs.shared || !
|
|
14916
|
+
const marker = path16.join(dirs.v2, "store.json");
|
|
14917
|
+
if (!dirs.shared || !fs12.existsSync(marker))
|
|
14845
14918
|
return success(null, null, null);
|
|
14846
14919
|
return this.withLock(dirs.checkoutLock, () => {
|
|
14847
|
-
if (!
|
|
14920
|
+
if (!fs12.existsSync(marker))
|
|
14848
14921
|
return success(null, null, null);
|
|
14849
14922
|
let tasks = 0;
|
|
14850
14923
|
try {
|
|
14851
14924
|
const merge = (from, to) => {
|
|
14852
|
-
if (!
|
|
14853
|
-
|
|
14925
|
+
if (!fs12.existsSync(to)) {
|
|
14926
|
+
fs12.mkdirSync(path16.dirname(to), { recursive: true });
|
|
14854
14927
|
try {
|
|
14855
|
-
|
|
14928
|
+
fs12.renameSync(from, to);
|
|
14856
14929
|
} catch {
|
|
14857
|
-
|
|
14858
|
-
|
|
14930
|
+
fs12.cpSync(from, to, { recursive: true, errorOnExist: true, force: false });
|
|
14931
|
+
fs12.rmSync(from, { recursive: true, force: true });
|
|
14859
14932
|
}
|
|
14860
14933
|
return;
|
|
14861
14934
|
}
|
|
14862
|
-
if (
|
|
14863
|
-
for (const name of
|
|
14864
|
-
merge(
|
|
14935
|
+
if (fs12.lstatSync(from).isDirectory() && fs12.lstatSync(to).isDirectory())
|
|
14936
|
+
for (const name of fs12.readdirSync(from))
|
|
14937
|
+
merge(path16.join(from, name), path16.join(to, name));
|
|
14865
14938
|
};
|
|
14866
14939
|
for (const sub of ["tasks", "checkouts", "blobs", "legacy"]) {
|
|
14867
|
-
const from =
|
|
14868
|
-
if (!
|
|
14940
|
+
const from = path16.join(dirs.v2, sub);
|
|
14941
|
+
if (!fs12.existsSync(from))
|
|
14869
14942
|
continue;
|
|
14870
14943
|
if (sub === "tasks") {
|
|
14871
|
-
for (const name of
|
|
14872
|
-
if (validId(name) && !
|
|
14944
|
+
for (const name of fs12.readdirSync(from))
|
|
14945
|
+
if (validId(name) && !fs12.existsSync(path16.join(dirs.dir, sub, name)))
|
|
14873
14946
|
tasks += 1;
|
|
14874
14947
|
}
|
|
14875
|
-
merge(from,
|
|
14948
|
+
merge(from, path16.join(dirs.dir, sub));
|
|
14876
14949
|
}
|
|
14877
|
-
const ledger =
|
|
14878
|
-
if (
|
|
14879
|
-
merge(ledger,
|
|
14880
|
-
|
|
14881
|
-
|
|
14950
|
+
const ledger = path16.join(dirs.v2, "ledger");
|
|
14951
|
+
if (fs12.existsSync(ledger) && !fs12.existsSync(path16.join(dirs.dir, "ledger")))
|
|
14952
|
+
merge(ledger, path16.join(dirs.dir, "ledger"));
|
|
14953
|
+
fs12.rmSync(path16.join(dirs.v2, "task-index.json"), { force: true });
|
|
14954
|
+
fs12.renameSync(marker, path16.join(dirs.v2, "store.moved.json"));
|
|
14882
14955
|
} catch (error) {
|
|
14883
14956
|
return failure2("storage_error", `cannot move ${dirs.v2} into ${dirs.dir}: ${String(error)}`, {
|
|
14884
14957
|
path: dirs.v2
|
|
@@ -14898,7 +14971,7 @@ class TaskStore {
|
|
|
14898
14971
|
readV2Workspace(file) {
|
|
14899
14972
|
let bytes;
|
|
14900
14973
|
try {
|
|
14901
|
-
bytes =
|
|
14974
|
+
bytes = fs12.readFileSync(file, "utf8");
|
|
14902
14975
|
} catch {
|
|
14903
14976
|
return null;
|
|
14904
14977
|
}
|
|
@@ -14916,7 +14989,7 @@ class TaskStore {
|
|
|
14916
14989
|
schemaVersion: SCHEMA_VERSION,
|
|
14917
14990
|
id: workspaceId ?? newId(),
|
|
14918
14991
|
revision: newRevision(),
|
|
14919
|
-
root:
|
|
14992
|
+
root: path16.dirname(v2),
|
|
14920
14993
|
runtime: { createdWith: version, updatedWith: version },
|
|
14921
14994
|
writer: null,
|
|
14922
14995
|
store: {
|
|
@@ -14927,12 +15000,12 @@ class TaskStore {
|
|
|
14927
15000
|
},
|
|
14928
15001
|
critical: ["store"]
|
|
14929
15002
|
};
|
|
14930
|
-
|
|
14931
|
-
const ignore =
|
|
14932
|
-
if (!
|
|
14933
|
-
|
|
15003
|
+
fs12.mkdirSync(v2, { recursive: true });
|
|
15004
|
+
const ignore = path16.join(v2, ".gitignore");
|
|
15005
|
+
if (!fs12.existsSync(ignore))
|
|
15006
|
+
fs12.writeFileSync(ignore, `*
|
|
14934
15007
|
`);
|
|
14935
|
-
replaceFile(
|
|
15008
|
+
replaceFile(path16.join(v2, "workspace.json"), `${JSON.stringify(marker, null, 2)}
|
|
14936
15009
|
`, true);
|
|
14937
15010
|
}
|
|
14938
15011
|
stubFor(taskId) {
|
|
@@ -14948,7 +15021,7 @@ class TaskStore {
|
|
|
14948
15021
|
}
|
|
14949
15022
|
isStub(file) {
|
|
14950
15023
|
try {
|
|
14951
|
-
const value = JSON.parse(
|
|
15024
|
+
const value = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
14952
15025
|
return isObject6(value) && isObject6(value.store) && value.store.format === "workit-store";
|
|
14953
15026
|
} catch {
|
|
14954
15027
|
return false;
|
|
@@ -14956,32 +15029,32 @@ class TaskStore {
|
|
|
14956
15029
|
}
|
|
14957
15030
|
writeTombstoneIfMissing() {
|
|
14958
15031
|
try {
|
|
14959
|
-
const v2 =
|
|
14960
|
-
if (
|
|
15032
|
+
const v2 = path16.join(this.root, ".workit");
|
|
15033
|
+
if (fs12.existsSync(path16.join(v2, "workspace.json")))
|
|
14961
15034
|
return;
|
|
14962
15035
|
let id = null;
|
|
14963
15036
|
try {
|
|
14964
|
-
id = JSON.parse(
|
|
15037
|
+
id = JSON.parse(fs12.readFileSync(this.paths().workspace, "utf8")).id ?? null;
|
|
14965
15038
|
} catch {}
|
|
14966
15039
|
this.writeTombstone(v2, id);
|
|
14967
15040
|
} catch {}
|
|
14968
15041
|
}
|
|
14969
15042
|
initializeStorage() {
|
|
14970
15043
|
const dirs = this.paths();
|
|
14971
|
-
retryTransient(() =>
|
|
14972
|
-
retryTransient(() =>
|
|
14973
|
-
if (!
|
|
15044
|
+
retryTransient(() => fs12.mkdirSync(dirs.checkout, { recursive: true }));
|
|
15045
|
+
retryTransient(() => fs12.mkdirSync(dirs.tasks, { recursive: true }));
|
|
15046
|
+
if (!fs12.existsSync(dirs.marker))
|
|
14974
15047
|
replaceFile(dirs.marker, `${JSON.stringify({ format: "workit-store", version: STORE_FORMAT, createdWith: runtimeVersion() })}
|
|
14975
15048
|
`, false);
|
|
14976
15049
|
if (!dirs.shared) {
|
|
14977
|
-
const ignore =
|
|
15050
|
+
const ignore = path16.join(dirs.dir, ".gitignore");
|
|
14978
15051
|
let current = null;
|
|
14979
15052
|
try {
|
|
14980
|
-
current =
|
|
15053
|
+
current = fs12.readFileSync(ignore, "utf8");
|
|
14981
15054
|
} catch {}
|
|
14982
15055
|
if (current !== `*
|
|
14983
15056
|
`)
|
|
14984
|
-
retryTransient(() =>
|
|
15057
|
+
retryTransient(() => fs12.writeFileSync(ignore, `*
|
|
14985
15058
|
`));
|
|
14986
15059
|
}
|
|
14987
15060
|
this.writeTombstoneIfMissing();
|
|
@@ -14997,7 +15070,7 @@ class TaskStore {
|
|
|
14997
15070
|
shouldReclaim: ({ payload, nowMs }) => {
|
|
14998
15071
|
let ageMs = null;
|
|
14999
15072
|
try {
|
|
15000
|
-
ageMs = nowMs -
|
|
15073
|
+
ageMs = nowMs - fs12.lstatSync(lockPath).mtimeMs;
|
|
15001
15074
|
} catch {}
|
|
15002
15075
|
return classifyLockOwner(payload, ageMs, localLockHost(), TASK_STORE_LOCK).state === "stale";
|
|
15003
15076
|
},
|
|
@@ -15034,7 +15107,7 @@ class TaskStore {
|
|
|
15034
15107
|
withLock(lockPath, operation) {
|
|
15035
15108
|
try {
|
|
15036
15109
|
this.initializeStorage();
|
|
15037
|
-
|
|
15110
|
+
fs12.mkdirSync(path16.dirname(lockPath), { recursive: true });
|
|
15038
15111
|
} catch (error) {
|
|
15039
15112
|
return failure2("storage_error", `unable to initialize store: ${String(error)}`, {
|
|
15040
15113
|
path: this.paths().dir
|
|
@@ -15074,18 +15147,18 @@ class TaskStore {
|
|
|
15074
15147
|
lockDirWritable(lockPath) {
|
|
15075
15148
|
const probe = `${lockPath}.${process.pid}.${randomUUID3()}.probe`;
|
|
15076
15149
|
try {
|
|
15077
|
-
|
|
15150
|
+
fs12.closeSync(fs12.openSync(probe, "wx", 384));
|
|
15078
15151
|
} catch {
|
|
15079
15152
|
return false;
|
|
15080
15153
|
}
|
|
15081
15154
|
try {
|
|
15082
|
-
|
|
15155
|
+
fs12.rmSync(probe, { force: true });
|
|
15083
15156
|
} catch {}
|
|
15084
15157
|
return true;
|
|
15085
15158
|
}
|
|
15086
15159
|
lockHolderPresent(lockPath) {
|
|
15087
15160
|
try {
|
|
15088
|
-
|
|
15161
|
+
fs12.lstatSync(lockPath);
|
|
15089
15162
|
return true;
|
|
15090
15163
|
} catch (error) {
|
|
15091
15164
|
return error?.code !== "ENOENT";
|
|
@@ -15097,12 +15170,12 @@ class TaskStore {
|
|
|
15097
15170
|
if (isTransientWindowsError(error) && !this.lockHolderPresent(lockPath) && !this.lockDirWritable(lockPath))
|
|
15098
15171
|
return failure2("storage_error", `cannot create the workit lock (${code}); no other Workit call holds it`, {
|
|
15099
15172
|
path: lockPath,
|
|
15100
|
-
guidance: `Check permissions and the read-only attribute on ${
|
|
15173
|
+
guidance: `Check permissions and the read-only attribute on ${path16.dirname(lockPath)}.`
|
|
15101
15174
|
});
|
|
15102
15175
|
if (code === "EEXIST" || code === "file_lock_timeout" || code === "file_lock_stale" || isTransientWindowsError(error)) {
|
|
15103
15176
|
let lock = null;
|
|
15104
15177
|
try {
|
|
15105
|
-
lock = parseMetadataLockOrNull(
|
|
15178
|
+
lock = parseMetadataLockOrNull(fs12.readFileSync(lockPath, "utf8"));
|
|
15106
15179
|
} catch {}
|
|
15107
15180
|
return failure2("busy", `workit lock is held by another Workit call${lock ? ` (pid ${lock.pid} on ${lock.host})` : ""}; retry shortly`, {
|
|
15108
15181
|
outcome: "not_started",
|
|
@@ -15143,7 +15216,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
15143
15216
|
};
|
|
15144
15217
|
}, fileSignature = (file) => {
|
|
15145
15218
|
try {
|
|
15146
|
-
const stat =
|
|
15219
|
+
const stat = fs12.statSync(file, { bigint: true });
|
|
15147
15220
|
return `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
|
|
15148
15221
|
} catch {
|
|
15149
15222
|
return null;
|
|
@@ -15155,7 +15228,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
15155
15228
|
}, now = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z"), oldestFirst = (left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id), cachedRuntimeVersion = null, runtimeVersion = () => {
|
|
15156
15229
|
if (cachedRuntimeVersion === null) {
|
|
15157
15230
|
try {
|
|
15158
|
-
const pkg = JSON.parse(
|
|
15231
|
+
const pkg = JSON.parse(fs12.readFileSync(path16.join(packageRoot(), "package.json"), "utf8"));
|
|
15159
15232
|
cachedRuntimeVersion = typeof pkg.version === "string" && pkg.version ? pkg.version : "0.0.0";
|
|
15160
15233
|
} catch {
|
|
15161
15234
|
cachedRuntimeVersion = "0.0.0";
|
|
@@ -15177,12 +15250,12 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
15177
15250
|
return false;
|
|
15178
15251
|
}, validId = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value), readText = (file) => {
|
|
15179
15252
|
try {
|
|
15180
|
-
return
|
|
15253
|
+
return fs12.readFileSync(file, "utf8");
|
|
15181
15254
|
} catch {
|
|
15182
15255
|
return "";
|
|
15183
15256
|
}
|
|
15184
15257
|
}, REFLOG_LINE, branchStart = (location, branch, aliases) => {
|
|
15185
|
-
const first = readText(
|
|
15258
|
+
const first = readText(path16.join(path16.dirname(location.dir), "logs", "refs", "heads", branch)).split(`
|
|
15186
15259
|
`, 1)[0];
|
|
15187
15260
|
const created = REFLOG_LINE.exec(first);
|
|
15188
15261
|
const start = created && /^branch: Created from (\S+)$/u.exec(created[3])?.[1];
|
|
@@ -15192,7 +15265,7 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
15192
15265
|
return start;
|
|
15193
15266
|
if (!location.git)
|
|
15194
15267
|
return null;
|
|
15195
|
-
for (const line of readText(
|
|
15268
|
+
for (const line of readText(path16.join(location.git.gitDir, "logs", "HEAD")).split(`
|
|
15196
15269
|
`)) {
|
|
15197
15270
|
const entry = REFLOG_LINE.exec(line);
|
|
15198
15271
|
const moved = entry && /^checkout: moving from (\S+) to (\S+)$/u.exec(entry[3]);
|
|
@@ -15201,21 +15274,21 @@ var MIGRATION_PENDING = "workit migration pending", STORE_FORMAT = 3, STORE_MIN_
|
|
|
15201
15274
|
return moved[1];
|
|
15202
15275
|
}
|
|
15203
15276
|
return null;
|
|
15204
|
-
}, refExists = (common, ref) =>
|
|
15277
|
+
}, refExists = (common, ref) => fs12.existsSync(path16.join(common, ref)) || readText(path16.join(common, "packed-refs")).includes(` ${ref}
|
|
15205
15278
|
`), origins, sameDirectoryIdentity = (left, right) => {
|
|
15206
|
-
if (!
|
|
15279
|
+
if (!path16.isAbsolute(left) || !path16.isAbsolute(right))
|
|
15207
15280
|
return false;
|
|
15208
|
-
const normalizedLeft =
|
|
15209
|
-
const normalizedRight =
|
|
15281
|
+
const normalizedLeft = path16.resolve(left);
|
|
15282
|
+
const normalizedRight = path16.resolve(right);
|
|
15210
15283
|
try {
|
|
15211
|
-
const a =
|
|
15212
|
-
const b =
|
|
15284
|
+
const a = fs12.statSync(normalizedLeft, { bigint: true });
|
|
15285
|
+
const b = fs12.statSync(normalizedRight, { bigint: true });
|
|
15213
15286
|
if (!a.isDirectory() || !b.isDirectory())
|
|
15214
15287
|
return false;
|
|
15215
15288
|
if (process.platform === "win32" ? normalizedLeft.toLowerCase() === normalizedRight.toLowerCase() : normalizedLeft === normalizedRight)
|
|
15216
15289
|
return true;
|
|
15217
|
-
const canonicalLeft =
|
|
15218
|
-
const canonicalRight =
|
|
15290
|
+
const canonicalLeft = fs12.realpathSync(normalizedLeft);
|
|
15291
|
+
const canonicalRight = fs12.realpathSync(normalizedRight);
|
|
15219
15292
|
if (process.platform === "win32" ? canonicalLeft.toLowerCase() === canonicalRight.toLowerCase() : canonicalLeft === canonicalRight)
|
|
15220
15293
|
return true;
|
|
15221
15294
|
return a.dev === b.dev && a.ino !== 0n && a.ino === b.ino;
|
|
@@ -15263,16 +15336,16 @@ var init_workers = __esm(() => {
|
|
|
15263
15336
|
|
|
15264
15337
|
// packages/workit-core/src/check-config.ts
|
|
15265
15338
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
15266
|
-
import
|
|
15267
|
-
import
|
|
15339
|
+
import fs13 from "node:fs";
|
|
15340
|
+
import path17 from "node:path";
|
|
15268
15341
|
function checksConfigFile(root) {
|
|
15269
|
-
const current =
|
|
15270
|
-
const legacy =
|
|
15271
|
-
return !
|
|
15342
|
+
const current = path17.join(root, CHECKS_FILE);
|
|
15343
|
+
const legacy = path17.join(root, LEGACY_CHECKS_FILE);
|
|
15344
|
+
return !fs13.existsSync(current) && fs13.existsSync(legacy) ? legacy : current;
|
|
15272
15345
|
}
|
|
15273
15346
|
function repoHeavyCommands(root) {
|
|
15274
15347
|
try {
|
|
15275
|
-
const value = JSON.parse(
|
|
15348
|
+
const value = JSON.parse(fs13.readFileSync(checksConfigFile(root), "utf8"));
|
|
15276
15349
|
const resources = isRecord3(value) ? value.resources : undefined;
|
|
15277
15350
|
const list = isRecord3(resources) ? resources.heavyCommands : undefined;
|
|
15278
15351
|
return Array.isArray(list) ? list.filter((item) => typeof item === "string") : [];
|
|
@@ -15317,12 +15390,12 @@ function splitCommand(command) {
|
|
|
15317
15390
|
return argv.length ? argv : new Error("empty command");
|
|
15318
15391
|
}
|
|
15319
15392
|
function checkRoot(cwd) {
|
|
15320
|
-
return
|
|
15393
|
+
return path17.resolve(git4(cwd, ["rev-parse", "--show-toplevel"]) ?? cwd);
|
|
15321
15394
|
}
|
|
15322
15395
|
function detectedChecks(root) {
|
|
15323
15396
|
const read = (file) => {
|
|
15324
15397
|
try {
|
|
15325
|
-
return
|
|
15398
|
+
return fs13.readFileSync(path17.join(root, file), "utf8");
|
|
15326
15399
|
} catch {
|
|
15327
15400
|
return null;
|
|
15328
15401
|
}
|
|
@@ -15361,7 +15434,7 @@ function detectedChecks(root) {
|
|
|
15361
15434
|
function loadCheckConfig(cwd) {
|
|
15362
15435
|
const root = checkRoot(cwd);
|
|
15363
15436
|
const file = checksConfigFile(root);
|
|
15364
|
-
const legacy =
|
|
15437
|
+
const legacy = path17.basename(file) === LEGACY_CHECKS_FILE;
|
|
15365
15438
|
const label = legacy ? LEGACY_CHECKS_FILE : CHECKS_FILE;
|
|
15366
15439
|
const note = legacy ? {
|
|
15367
15440
|
note: `${LEGACY_CHECKS_FILE} is deprecated; move it to ${CHECKS_FILE} (workit doctor --fix)`
|
|
@@ -15376,7 +15449,7 @@ function loadCheckConfig(cwd) {
|
|
|
15376
15449
|
});
|
|
15377
15450
|
let text = null;
|
|
15378
15451
|
try {
|
|
15379
|
-
text =
|
|
15452
|
+
text = fs13.readFileSync(file, "utf8");
|
|
15380
15453
|
} catch (error) {
|
|
15381
15454
|
if (error.code !== "ENOENT")
|
|
15382
15455
|
return none(`cannot read ${label}: ${error.message}`);
|
|
@@ -15437,10 +15510,10 @@ function workitAvailable(env = process.env) {
|
|
|
15437
15510
|
return workitOnPath;
|
|
15438
15511
|
const windows = process.platform === "win32";
|
|
15439
15512
|
const exts = windows ? (env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
15440
|
-
const dirs = (env.PATH ?? env.Path ?? "").split(
|
|
15513
|
+
const dirs = (env.PATH ?? env.Path ?? "").split(path17.delimiter).filter(Boolean);
|
|
15441
15514
|
workitOnPath = dirs.some((dir) => exts.some((ext) => {
|
|
15442
15515
|
try {
|
|
15443
|
-
return
|
|
15516
|
+
return fs13.statSync(path17.join(dir, `workit${ext}`)).isFile();
|
|
15444
15517
|
} catch {
|
|
15445
15518
|
return false;
|
|
15446
15519
|
}
|
|
@@ -15461,7 +15534,7 @@ var SCRIPT_CHECKS, CHECKS_FILE = ".workit/checks.json", LEGACY_CHECKS_FILE = "wo
|
|
|
15461
15534
|
const value = run.status === 0 ? (run.stdout ?? "").trim() : "";
|
|
15462
15535
|
return value || null;
|
|
15463
15536
|
}, packageManager = (root) => {
|
|
15464
|
-
const has = (file) =>
|
|
15537
|
+
const has = (file) => fs13.existsSync(path17.join(root, file));
|
|
15465
15538
|
if (has("bun.lock") || has("bun.lockb"))
|
|
15466
15539
|
return "bun";
|
|
15467
15540
|
if (has("pnpm-lock.yaml"))
|
|
@@ -15484,14 +15557,14 @@ var init_check_config = __esm(() => {
|
|
|
15484
15557
|
});
|
|
15485
15558
|
|
|
15486
15559
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
15487
|
-
import { createHash as
|
|
15488
|
-
import * as
|
|
15560
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
15561
|
+
import * as fs14 from "node:fs";
|
|
15489
15562
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
15490
|
-
import
|
|
15563
|
+
import path18 from "node:path";
|
|
15491
15564
|
function captureCandidate(root, scope, environment = []) {
|
|
15492
15565
|
let checkout;
|
|
15493
15566
|
try {
|
|
15494
|
-
checkout =
|
|
15567
|
+
checkout = fs14.realpathSync(root);
|
|
15495
15568
|
} catch {
|
|
15496
15569
|
return failure2("invalid_input", "candidate root does not exist");
|
|
15497
15570
|
}
|
|
@@ -15509,11 +15582,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15509
15582
|
if (item === ".git" || item === ".workit")
|
|
15510
15583
|
continue;
|
|
15511
15584
|
names.add(item);
|
|
15512
|
-
if (!
|
|
15585
|
+
if (!fs14.existsSync(target))
|
|
15513
15586
|
continue;
|
|
15514
15587
|
let stat;
|
|
15515
15588
|
try {
|
|
15516
|
-
stat =
|
|
15589
|
+
stat = fs14.lstatSync(target);
|
|
15517
15590
|
} catch {
|
|
15518
15591
|
uncertain = true;
|
|
15519
15592
|
continue;
|
|
@@ -15529,17 +15602,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15529
15602
|
for (const item of [...names].toSorted()) {
|
|
15530
15603
|
if (!scopeMatches(item, normalizedScope))
|
|
15531
15604
|
continue;
|
|
15532
|
-
const target =
|
|
15605
|
+
const target = path18.join(checkout, item);
|
|
15533
15606
|
try {
|
|
15534
|
-
const stat =
|
|
15607
|
+
const stat = fs14.lstatSync(target);
|
|
15535
15608
|
if (stat.isSymbolicLink()) {
|
|
15536
|
-
const link =
|
|
15609
|
+
const link = fs14.readlinkSync(target);
|
|
15537
15610
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
15538
15611
|
} else if (stat.isFile()) {
|
|
15539
15612
|
files.push({
|
|
15540
15613
|
path: item,
|
|
15541
15614
|
kind: "file",
|
|
15542
|
-
digest: digestBytes(
|
|
15615
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
15543
15616
|
executable: (stat.mode & 73) !== 0
|
|
15544
15617
|
});
|
|
15545
15618
|
} else if (!stat.isDirectory()) {
|
|
@@ -15938,12 +16011,12 @@ function boundTaskSummary(summary) {
|
|
|
15938
16011
|
brief.truncated = JSON.stringify(brief).includes("…") || progress.blockers.length > BRIEF_BLOCKERS || unmet.length > BRIEF_OPEN;
|
|
15939
16012
|
return brief;
|
|
15940
16013
|
}
|
|
15941
|
-
var digestBytes = (value) =>
|
|
16014
|
+
var digestBytes = (value) => createHash12("sha256").update(value).digest("hex"), inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path18.sep}`), relative = (root, candidate) => path18.relative(root, candidate).split(path18.sep).join("/") || ".", canonicalPath = (value) => {
|
|
15942
16015
|
if (typeof value !== "string" || !value)
|
|
15943
16016
|
return null;
|
|
15944
16017
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
15945
16018
|
return null;
|
|
15946
|
-
const normalized =
|
|
16019
|
+
const normalized = path18.posix.normalize(value);
|
|
15947
16020
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
15948
16021
|
return null;
|
|
15949
16022
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -15985,20 +16058,20 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
15985
16058
|
git: !/not a git repository/i.test(stderr)
|
|
15986
16059
|
};
|
|
15987
16060
|
}
|
|
15988
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
16061
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")) : [];
|
|
15989
16062
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
15990
16063
|
if (stagedDeleted.status !== 0) {
|
|
15991
16064
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
15992
16065
|
if (!/not a git repository/i.test(stderr))
|
|
15993
16066
|
return { paths, uncertain: true, git: true };
|
|
15994
16067
|
} else if (stagedDeleted.stdout) {
|
|
15995
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
16068
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path18.sep).join("/")));
|
|
15996
16069
|
}
|
|
15997
16070
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
15998
16071
|
}, walk = (root, directory, output) => {
|
|
15999
16072
|
let names;
|
|
16000
16073
|
try {
|
|
16001
|
-
names =
|
|
16074
|
+
names = fs14.readdirSync(directory);
|
|
16002
16075
|
} catch {
|
|
16003
16076
|
return true;
|
|
16004
16077
|
}
|
|
@@ -16006,10 +16079,10 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
16006
16079
|
for (const name of names) {
|
|
16007
16080
|
if (name === ".git" || name === ".workit")
|
|
16008
16081
|
continue;
|
|
16009
|
-
const target =
|
|
16082
|
+
const target = path18.join(directory, name);
|
|
16010
16083
|
let stat;
|
|
16011
16084
|
try {
|
|
16012
|
-
stat =
|
|
16085
|
+
stat = fs14.lstatSync(target);
|
|
16013
16086
|
} catch {
|
|
16014
16087
|
uncertain = true;
|
|
16015
16088
|
continue;
|
|
@@ -16023,14 +16096,14 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
16023
16096
|
}, scopeRoots = (root, scope) => {
|
|
16024
16097
|
const roots = [];
|
|
16025
16098
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
16026
|
-
const target =
|
|
16099
|
+
const target = path18.resolve(root, item);
|
|
16027
16100
|
if (!inside(root, target))
|
|
16028
16101
|
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` }] });
|
|
16029
16102
|
let ancestor = target;
|
|
16030
|
-
while (!
|
|
16031
|
-
ancestor =
|
|
16103
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
16104
|
+
ancestor = path18.dirname(ancestor);
|
|
16032
16105
|
try {
|
|
16033
|
-
if (!inside(root,
|
|
16106
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
16034
16107
|
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` }] });
|
|
16035
16108
|
} catch {
|
|
16036
16109
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -16083,7 +16156,7 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
16083
16156
|
}, findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId != null), verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
16084
16157
|
let root;
|
|
16085
16158
|
try {
|
|
16086
|
-
root =
|
|
16159
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
16087
16160
|
} catch {
|
|
16088
16161
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
16089
16162
|
}
|
|
@@ -16092,23 +16165,23 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
16092
16165
|
continue;
|
|
16093
16166
|
if (!reference.digest)
|
|
16094
16167
|
return failure2("invalid_input", "document references require a byte digest");
|
|
16095
|
-
const target =
|
|
16096
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
16168
|
+
const target = path18.resolve(root, reference.path);
|
|
16169
|
+
if (target !== root && !target.startsWith(`${root}${path18.sep}`))
|
|
16097
16170
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16098
16171
|
fields: [
|
|
16099
16172
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
16100
16173
|
]
|
|
16101
16174
|
});
|
|
16102
16175
|
try {
|
|
16103
|
-
const below =
|
|
16176
|
+
const below = path18.relative(root, target);
|
|
16104
16177
|
let current = root;
|
|
16105
|
-
for (const segment of below.split(
|
|
16178
|
+
for (const segment of below.split(path18.sep)) {
|
|
16106
16179
|
if (!segment)
|
|
16107
16180
|
continue;
|
|
16108
|
-
current =
|
|
16109
|
-
const stat =
|
|
16110
|
-
const real =
|
|
16111
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
16181
|
+
current = path18.join(current, segment);
|
|
16182
|
+
const stat = fs14.lstatSync(current);
|
|
16183
|
+
const real = fs14.realpathSync(current);
|
|
16184
|
+
if (real !== root && !real.startsWith(`${root}${path18.sep}`))
|
|
16112
16185
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16113
16186
|
fields: [
|
|
16114
16187
|
{
|
|
@@ -16124,7 +16197,7 @@ var digestBytes = (value) => createHash11("sha256").update(value).digest("hex"),
|
|
|
16124
16197
|
if (current !== target && !stat.isDirectory())
|
|
16125
16198
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
16126
16199
|
}
|
|
16127
|
-
if (digestBytes(
|
|
16200
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
16128
16201
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
16129
16202
|
} catch {
|
|
16130
16203
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -18104,9 +18177,9 @@ var support = (descriptor, axis) => {
|
|
|
18104
18177
|
});
|
|
18105
18178
|
|
|
18106
18179
|
// packages/workit-core/src/hooks/context.ts
|
|
18107
|
-
import { createHash as
|
|
18108
|
-
import
|
|
18109
|
-
import
|
|
18180
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
18181
|
+
import fs15 from "node:fs";
|
|
18182
|
+
import path19 from "node:path";
|
|
18110
18183
|
function sessionCompactContext(store, session, context, selection = "session-bound") {
|
|
18111
18184
|
const listed = store.listTaskIndex();
|
|
18112
18185
|
if (!listed.ok)
|
|
@@ -18141,7 +18214,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
18141
18214
|
return null;
|
|
18142
18215
|
const freshness = { mode: "signal", current: () => recentSignal(store.root) };
|
|
18143
18216
|
const observed = task?.data.evidence.some(isObservedCheck) ?? false;
|
|
18144
|
-
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [
|
|
18217
|
+
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path19.resolve(store.root, ref.path)] : []));
|
|
18145
18218
|
const observedFiles = filesKey(files);
|
|
18146
18219
|
const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
|
|
18147
18220
|
if (!compact.ok || !compact.data)
|
|
@@ -18239,7 +18312,7 @@ ${options.addendum}` : ""}
|
|
|
18239
18312
|
} catch {
|
|
18240
18313
|
return null;
|
|
18241
18314
|
}
|
|
18242
|
-
}, TURN_TTL_MS, digestOf = (text) =>
|
|
18315
|
+
}, TURN_TTL_MS, digestOf = (text) => createHash13("sha256").update(text).digest("hex"), turnMarker = (input) => {
|
|
18243
18316
|
if (!input.session.id)
|
|
18244
18317
|
return null;
|
|
18245
18318
|
try {
|
|
@@ -18247,29 +18320,29 @@ ${options.addendum}` : ""}
|
|
|
18247
18320
|
if (location instanceof Error)
|
|
18248
18321
|
return null;
|
|
18249
18322
|
const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
|
|
18250
|
-
return
|
|
18323
|
+
return path19.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
|
|
18251
18324
|
} catch {
|
|
18252
18325
|
return null;
|
|
18253
18326
|
}
|
|
18254
18327
|
}, writeTurnDigest = (file, digest) => {
|
|
18255
18328
|
try {
|
|
18256
|
-
|
|
18257
|
-
|
|
18329
|
+
fs15.mkdirSync(path19.dirname(file), { recursive: true });
|
|
18330
|
+
fs15.writeFileSync(file, `${JSON.stringify({ digest })}
|
|
18258
18331
|
`);
|
|
18259
18332
|
} catch {}
|
|
18260
18333
|
}, clearTurnDigest = (file) => {
|
|
18261
18334
|
try {
|
|
18262
|
-
|
|
18335
|
+
fs15.rmSync(file, { force: true });
|
|
18263
18336
|
} catch {}
|
|
18264
18337
|
}, pruneTurnDigests = (dir, now) => {
|
|
18265
18338
|
try {
|
|
18266
|
-
for (const name of
|
|
18339
|
+
for (const name of fs15.readdirSync(dir)) {
|
|
18267
18340
|
if (!name.startsWith("turn-"))
|
|
18268
18341
|
continue;
|
|
18269
|
-
const file =
|
|
18342
|
+
const file = path19.join(dir, name);
|
|
18270
18343
|
try {
|
|
18271
|
-
if (now -
|
|
18272
|
-
|
|
18344
|
+
if (now - fs15.statSync(file).mtimeMs > TURN_TTL_MS)
|
|
18345
|
+
fs15.rmSync(file, { force: true });
|
|
18273
18346
|
} catch {}
|
|
18274
18347
|
}
|
|
18275
18348
|
} catch {}
|
|
@@ -18284,7 +18357,7 @@ ${options.addendum}` : ""}
|
|
|
18284
18357
|
return text;
|
|
18285
18358
|
const digest = digestOf(text);
|
|
18286
18359
|
try {
|
|
18287
|
-
const previous = JSON.parse(
|
|
18360
|
+
const previous = JSON.parse(fs15.readFileSync(file, "utf8"));
|
|
18288
18361
|
if (previous.digest === digest)
|
|
18289
18362
|
return null;
|
|
18290
18363
|
} catch {}
|
|
@@ -18294,7 +18367,7 @@ ${options.addendum}` : ""}
|
|
|
18294
18367
|
const file = turnMarker(input);
|
|
18295
18368
|
if (!file)
|
|
18296
18369
|
return;
|
|
18297
|
-
pruneTurnDigests(
|
|
18370
|
+
pruneTurnDigests(path19.dirname(file), Date.now());
|
|
18298
18371
|
if (text)
|
|
18299
18372
|
writeTurnDigest(file, digestOf(text));
|
|
18300
18373
|
else
|
|
@@ -18314,9 +18387,9 @@ var init_context = __esm(() => {
|
|
|
18314
18387
|
});
|
|
18315
18388
|
|
|
18316
18389
|
// packages/workit-core/src/hooks/session-marker.ts
|
|
18317
|
-
import { createHash as
|
|
18318
|
-
import
|
|
18319
|
-
import
|
|
18390
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
18391
|
+
import fs16 from "node:fs";
|
|
18392
|
+
import path20 from "node:path";
|
|
18320
18393
|
var sessionMarkerFile = (input, session, store) => {
|
|
18321
18394
|
let dir = store;
|
|
18322
18395
|
if (dir === undefined) {
|
|
@@ -18325,19 +18398,19 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
18325
18398
|
return null;
|
|
18326
18399
|
dir = location.dir;
|
|
18327
18400
|
}
|
|
18328
|
-
const name =
|
|
18329
|
-
return
|
|
18401
|
+
const name = createHash14("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
18402
|
+
return path20.join(dir, "hooks", `skills-${name}.json`);
|
|
18330
18403
|
}, list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [], readSessionMarker = (file) => {
|
|
18331
18404
|
try {
|
|
18332
|
-
const value = JSON.parse(
|
|
18405
|
+
const value = JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
18333
18406
|
return { nudged: list2(value.nudged), loaded: list2(value.loaded), raw: list2(value.raw) };
|
|
18334
18407
|
} catch {
|
|
18335
18408
|
return { nudged: [], loaded: [], raw: [] };
|
|
18336
18409
|
}
|
|
18337
18410
|
}, writeSessionMarker = (file, marker) => {
|
|
18338
18411
|
try {
|
|
18339
|
-
|
|
18340
|
-
|
|
18412
|
+
fs16.mkdirSync(path20.dirname(file), { recursive: true });
|
|
18413
|
+
fs16.writeFileSync(file, JSON.stringify(marker));
|
|
18341
18414
|
} catch {}
|
|
18342
18415
|
};
|
|
18343
18416
|
var init_session_marker = __esm(() => {
|
|
@@ -18772,10 +18845,10 @@ var init_shell_words = __esm(() => {
|
|
|
18772
18845
|
|
|
18773
18846
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
18774
18847
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
18775
|
-
import { createHash as
|
|
18776
|
-
import
|
|
18848
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
18849
|
+
import fs17 from "node:fs";
|
|
18777
18850
|
import os5 from "node:os";
|
|
18778
|
-
import
|
|
18851
|
+
import path21 from "node:path";
|
|
18779
18852
|
function rawInvocations(command, dialect = "posix", depth = 0) {
|
|
18780
18853
|
if (depth > 0)
|
|
18781
18854
|
return walk2(command, dialect, depth);
|
|
@@ -19057,8 +19130,8 @@ function noteRawCommit(input, command, key) {
|
|
|
19057
19130
|
if (action.kind !== "commit")
|
|
19058
19131
|
continue;
|
|
19059
19132
|
const file = markerFile(repo, input.session.id, key);
|
|
19060
|
-
|
|
19061
|
-
|
|
19133
|
+
fs17.mkdirSync(path21.dirname(file), { recursive: true });
|
|
19134
|
+
fs17.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
|
|
19062
19135
|
`);
|
|
19063
19136
|
}
|
|
19064
19137
|
} catch {}
|
|
@@ -19080,16 +19153,16 @@ function settlePendingCommit(input) {
|
|
|
19080
19153
|
if (!repo)
|
|
19081
19154
|
return;
|
|
19082
19155
|
const file = markerFile(repo, input.session.id, NEXT_COMMAND);
|
|
19083
|
-
if (
|
|
19156
|
+
if (fs17.existsSync(file))
|
|
19084
19157
|
settle2(input, repo, file);
|
|
19085
19158
|
} catch {}
|
|
19086
19159
|
}
|
|
19087
|
-
var NONE2, 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) =>
|
|
19160
|
+
var NONE2, 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) => path21.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\"), HERE, joinDir = (base, raw) => {
|
|
19088
19161
|
const next = raw.replace(HERE, ".");
|
|
19089
19162
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
19090
19163
|
return;
|
|
19091
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
19092
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
19164
|
+
const expanded = next === "~" || next.startsWith("~/") ? path21.join(os5.homedir(), next.slice(1)) : next;
|
|
19165
|
+
return base === null || isAbsolute(expanded) ? expanded : path21.join(base, expanded);
|
|
19093
19166
|
}, rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner), cdTarget = (words) => {
|
|
19094
19167
|
const args = words.slice(1);
|
|
19095
19168
|
const flag = args.findIndex((word) => /^-(?:literal)?path$/i.test(word));
|
|
@@ -19558,7 +19631,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19558
19631
|
return null;
|
|
19559
19632
|
return { location, dir, branch: resolveTaskKey(dir, location).branch };
|
|
19560
19633
|
}, isWorkitWorkspace = (repo) => {
|
|
19561
|
-
if (
|
|
19634
|
+
if (fs17.existsSync(repo.location.dir))
|
|
19562
19635
|
return true;
|
|
19563
19636
|
try {
|
|
19564
19637
|
return resolveRuntimeWorkspaceVcs(repo.location.top ?? repo.dir) !== null;
|
|
@@ -19577,17 +19650,17 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19577
19650
|
if (!git || git.reftable)
|
|
19578
19651
|
return null;
|
|
19579
19652
|
try {
|
|
19580
|
-
const head =
|
|
19653
|
+
const head = fs17.readFileSync(path21.join(git.gitDir, "HEAD"), "utf8").trim();
|
|
19581
19654
|
if (/^[0-9a-f]{40,64}$/.test(head))
|
|
19582
19655
|
return head;
|
|
19583
19656
|
const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
|
|
19584
19657
|
if (!ref)
|
|
19585
19658
|
return null;
|
|
19586
|
-
const common =
|
|
19659
|
+
const common = path21.dirname(repo.location.dir);
|
|
19587
19660
|
try {
|
|
19588
|
-
return
|
|
19661
|
+
return fs17.readFileSync(path21.join(common, ref), "utf8").trim() || null;
|
|
19589
19662
|
} catch {}
|
|
19590
|
-
const packed =
|
|
19663
|
+
const packed = fs17.readFileSync(path21.join(common, "packed-refs"), "utf8");
|
|
19591
19664
|
return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
|
|
19592
19665
|
} catch {
|
|
19593
19666
|
return null;
|
|
@@ -19653,8 +19726,8 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19653
19726
|
const sub = invocation.args[0];
|
|
19654
19727
|
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
19655
19728
|
return [invocation];
|
|
19656
|
-
const dir =
|
|
19657
|
-
if (!
|
|
19729
|
+
const dir = path21.resolve(root, invocation.dir ?? ".");
|
|
19730
|
+
if (!fs17.existsSync(dir))
|
|
19658
19731
|
return [invocation];
|
|
19659
19732
|
const config = gitConfig(dir, invocation, cache);
|
|
19660
19733
|
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
@@ -19675,11 +19748,11 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19675
19748
|
}, normalizedUrl = (url, dir) => {
|
|
19676
19749
|
const trimmed = url.trim();
|
|
19677
19750
|
if (/^file:\/\//i.test(trimmed))
|
|
19678
|
-
return
|
|
19751
|
+
return path21.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19679
19752
|
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
19680
19753
|
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
19681
19754
|
if (!scheme && !scp)
|
|
19682
|
-
return
|
|
19755
|
+
return path21.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19683
19756
|
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
19684
19757
|
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
19685
19758
|
}, rewrittenUrl = (url, config) => {
|
|
@@ -19885,7 +19958,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19885
19958
|
const out = [];
|
|
19886
19959
|
const repos = new Map;
|
|
19887
19960
|
const repoFor = (relative) => {
|
|
19888
|
-
const dir =
|
|
19961
|
+
const dir = path21.resolve(cwd, relative ?? ".");
|
|
19889
19962
|
if (!repos.has(dir)) {
|
|
19890
19963
|
const repo = repoAt(dir);
|
|
19891
19964
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
@@ -19929,7 +20002,7 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19929
20002
|
kind: "deny",
|
|
19930
20003
|
reason: `workit: the shell hook could not analyze this command (${error.message}), so it does not run. ${SPLIT_IT}`,
|
|
19931
20004
|
unblock: SPLIT_IT
|
|
19932
|
-
}), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) =>
|
|
20005
|
+
}), NEXT_COMMAND = "next", MARKER_TTL_SECONDS = 3600, markerFile = (repo, session, key) => path21.join(repo.location.dir, "hooks", `commit-${createHash15("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`), callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash15("sha256").update(command).digest("hex")}`, headCommit = (dir) => {
|
|
19933
20006
|
const run = spawnSync11("git", [
|
|
19934
20007
|
"log",
|
|
19935
20008
|
"-1",
|
|
@@ -19946,11 +20019,11 @@ var NONE2, SHELLS, POWERSHELLS, EVALS, WRAPPERS, WRAPPER_VALUES, KEYWORDS, DECLA
|
|
|
19946
20019
|
}, settle2 = (input, repo, file) => {
|
|
19947
20020
|
let marker;
|
|
19948
20021
|
try {
|
|
19949
|
-
marker = JSON.parse(
|
|
20022
|
+
marker = JSON.parse(fs17.readFileSync(file, "utf8"));
|
|
19950
20023
|
} catch {
|
|
19951
20024
|
return;
|
|
19952
20025
|
}
|
|
19953
|
-
|
|
20026
|
+
fs17.rmSync(file, { force: true });
|
|
19954
20027
|
const session = input.session.id;
|
|
19955
20028
|
const now = Date.now() / 1000;
|
|
19956
20029
|
if (typeof marker.at !== "number" || now - marker.at > MARKER_TTL_SECONDS)
|
|
@@ -20128,7 +20201,7 @@ var init_raw_git = __esm(() => {
|
|
|
20128
20201
|
// packages/workit-core/src/core/route-intent.ts
|
|
20129
20202
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
20130
20203
|
import { existsSync as existsSync6 } from "node:fs";
|
|
20131
|
-
import
|
|
20204
|
+
import path22 from "node:path";
|
|
20132
20205
|
var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, SUBTREE_CREATE, BRANCH_NO_CREATE, BRANCH_RENAME, longOption = (name, flags) => flags.has(name) || name.length >= 3 && [...flags].some((flag) => flag.startsWith("--") && flag.startsWith(name)), shortsOf = (flags) => [...flags].filter((flag) => /^-[^-]$/u.test(flag)).join("").replaceAll("-", ""), flagValue = (args, flags) => {
|
|
20133
20206
|
const shorts = shortsOf(flags);
|
|
20134
20207
|
for (let index = 1;index < args.length; index++) {
|
|
@@ -20254,7 +20327,7 @@ var UNKNOWABLE, SWITCH_CREATE, CHECKOUT_CREATE, WORKTREE_CREATE, SUBTREE_CREATE,
|
|
|
20254
20327
|
return null;
|
|
20255
20328
|
if (dir === null)
|
|
20256
20329
|
return root;
|
|
20257
|
-
const resolved =
|
|
20330
|
+
const resolved = path22.resolve(root, dir);
|
|
20258
20331
|
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
20259
20332
|
}, shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
20260
20333
|
let judged = false;
|
|
@@ -20307,9 +20380,9 @@ var init_policy = __esm(() => {
|
|
|
20307
20380
|
});
|
|
20308
20381
|
|
|
20309
20382
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
20310
|
-
import
|
|
20383
|
+
import fs18 from "node:fs";
|
|
20311
20384
|
import os6 from "node:os";
|
|
20312
|
-
import
|
|
20385
|
+
import path23 from "node:path";
|
|
20313
20386
|
function parseJsonc(text) {
|
|
20314
20387
|
let out = "";
|
|
20315
20388
|
for (let index = 0;index < text.length; index += 1) {
|
|
@@ -20339,21 +20412,21 @@ function parseJsonc(text) {
|
|
|
20339
20412
|
return JSON.parse(out.replace(/,(\s*[}\]])/gu, "$1"));
|
|
20340
20413
|
}
|
|
20341
20414
|
function gitTop(cwd) {
|
|
20342
|
-
for (let dir =
|
|
20343
|
-
if (
|
|
20415
|
+
for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
|
|
20416
|
+
if (fs18.existsSync(path23.join(dir, ".git")))
|
|
20344
20417
|
return dir;
|
|
20345
|
-
if (
|
|
20418
|
+
if (path23.dirname(dir) === dir)
|
|
20346
20419
|
return null;
|
|
20347
20420
|
}
|
|
20348
20421
|
}
|
|
20349
20422
|
function claudeSettingsFiles(cwd, env, platform = process.platform) {
|
|
20350
20423
|
const project = env.CLAUDE_PROJECT_DIR || gitTop(cwd) || cwd;
|
|
20351
|
-
const user = env.CLAUDE_CONFIG_DIR ||
|
|
20424
|
+
const user = env.CLAUDE_CONFIG_DIR || path23.join(homeOf(env), ".claude");
|
|
20352
20425
|
return [
|
|
20353
20426
|
...CLAUDE_MANAGED[platform] ? [CLAUDE_MANAGED[platform]] : [],
|
|
20354
|
-
|
|
20355
|
-
|
|
20356
|
-
|
|
20427
|
+
path23.join(user, "settings.json"),
|
|
20428
|
+
path23.join(project, ".claude", "settings.json"),
|
|
20429
|
+
path23.join(project, ".claude", "settings.local.json")
|
|
20357
20430
|
];
|
|
20358
20431
|
}
|
|
20359
20432
|
function claudeRules(cwd, env = process.env) {
|
|
@@ -20398,10 +20471,10 @@ function claudeRules(cwd, env = process.env) {
|
|
|
20398
20471
|
function opencodeRules(cwd, env = process.env) {
|
|
20399
20472
|
const rules = EMPTY();
|
|
20400
20473
|
try {
|
|
20401
|
-
const config = env.XDG_CONFIG_HOME ||
|
|
20474
|
+
const config = env.XDG_CONFIG_HOME || path23.join(homeOf(env), ".config");
|
|
20402
20475
|
const files = [
|
|
20403
|
-
...OPENCODE_NAMES.map((name) =>
|
|
20404
|
-
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [
|
|
20476
|
+
...OPENCODE_NAMES.map((name) => path23.join(config, "opencode", name)),
|
|
20477
|
+
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path23.join(dir, name), path23.join(dir, ".opencode", name)])),
|
|
20405
20478
|
...env.OPENCODE_CONFIG ? [env.OPENCODE_CONFIG] : []
|
|
20406
20479
|
];
|
|
20407
20480
|
for (const file of files) {
|
|
@@ -20419,19 +20492,19 @@ function opencodeRules(cwd, env = process.env) {
|
|
|
20419
20492
|
function codexRules(cwd, env = process.env) {
|
|
20420
20493
|
const rules = EMPTY();
|
|
20421
20494
|
try {
|
|
20422
|
-
const home = env.CODEX_HOME ||
|
|
20495
|
+
const home = env.CODEX_HOME || path23.join(homeOf(env), ".codex");
|
|
20423
20496
|
const top = gitTop(cwd) ?? cwd;
|
|
20424
|
-
for (const dir of [
|
|
20497
|
+
for (const dir of [path23.join(home, "rules"), path23.join(top, ".codex", "rules")]) {
|
|
20425
20498
|
let files;
|
|
20426
20499
|
try {
|
|
20427
|
-
files =
|
|
20500
|
+
files = fs18.readdirSync(dir).filter((name) => name.endsWith(".rules"));
|
|
20428
20501
|
} catch (error) {
|
|
20429
20502
|
if (error.code === "ENOENT")
|
|
20430
20503
|
continue;
|
|
20431
20504
|
return "unreadable";
|
|
20432
20505
|
}
|
|
20433
20506
|
for (const name of files) {
|
|
20434
|
-
const text = readText2(
|
|
20507
|
+
const text = readText2(path23.join(dir, name)) ?? "";
|
|
20435
20508
|
for (const part of text.split(/\bprefix_rule\s*\(/u).slice(1)) {
|
|
20436
20509
|
const rule = codexRule(part);
|
|
20437
20510
|
if (!rule)
|
|
@@ -20450,8 +20523,8 @@ function cursorRules(cwd, env = process.env) {
|
|
|
20450
20523
|
try {
|
|
20451
20524
|
const top = gitTop(cwd) ?? cwd;
|
|
20452
20525
|
for (const file of [
|
|
20453
|
-
|
|
20454
|
-
|
|
20526
|
+
path23.join(homeOf(env), ".cursor", "cli-config.json"),
|
|
20527
|
+
path23.join(top, ".cursor", "cli.json")
|
|
20455
20528
|
]) {
|
|
20456
20529
|
const text = readText2(file);
|
|
20457
20530
|
if (text === null)
|
|
@@ -20504,7 +20577,7 @@ function wrapAllowed(read, words, command, options = {}) {
|
|
|
20504
20577
|
}
|
|
20505
20578
|
var EMPTY = () => ({ deny: [], allow: [] }), readText2 = (file) => {
|
|
20506
20579
|
try {
|
|
20507
|
-
return
|
|
20580
|
+
return fs18.readFileSync(file, "utf8");
|
|
20508
20581
|
} catch (error) {
|
|
20509
20582
|
if (error.code === "ENOENT")
|
|
20510
20583
|
return null;
|
|
@@ -20513,9 +20586,9 @@ var EMPTY = () => ({ deny: [], allow: [] }), readText2 = (file) => {
|
|
|
20513
20586
|
}, isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectDirs = (cwd) => {
|
|
20514
20587
|
const top = gitTop(cwd);
|
|
20515
20588
|
const dirs = [];
|
|
20516
|
-
for (let dir =
|
|
20589
|
+
for (let dir = path23.resolve(cwd);; dir = path23.dirname(dir)) {
|
|
20517
20590
|
dirs.push(dir);
|
|
20518
|
-
if (!top || dir === top ||
|
|
20591
|
+
if (!top || dir === top || path23.dirname(dir) === dir)
|
|
20519
20592
|
return dirs;
|
|
20520
20593
|
}
|
|
20521
20594
|
}, homeOf = (env) => env.HOME || os6.homedir(), CLAUDE_MANAGED, bashPattern = (entry) => {
|
|
@@ -20611,20 +20684,20 @@ var init_heavy_rules = __esm(() => {
|
|
|
20611
20684
|
});
|
|
20612
20685
|
|
|
20613
20686
|
// packages/workit-core/src/core/heavy.ts
|
|
20614
|
-
import
|
|
20687
|
+
import fs19 from "node:fs";
|
|
20615
20688
|
import os7 from "node:os";
|
|
20616
|
-
import
|
|
20689
|
+
import path24 from "node:path";
|
|
20617
20690
|
function stateDir(env, platform = process.platform) {
|
|
20618
20691
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
20619
20692
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
20620
20693
|
if (env.XDG_STATE_HOME)
|
|
20621
|
-
return
|
|
20694
|
+
return path24.join(env.XDG_STATE_HOME, "workit");
|
|
20622
20695
|
const home = env.HOME || os7.homedir();
|
|
20623
20696
|
if (platform === "darwin")
|
|
20624
|
-
return
|
|
20697
|
+
return path24.join(home, "Library", "Application Support", "workit");
|
|
20625
20698
|
if (platform === "win32")
|
|
20626
|
-
return
|
|
20627
|
-
return
|
|
20699
|
+
return path24.join(env.LOCALAPPDATA ?? path24.join(home, "AppData", "Local"), "workit");
|
|
20700
|
+
return path24.join(home, ".local", "state", "workit");
|
|
20628
20701
|
}
|
|
20629
20702
|
function positional2(words, from, values = PM_VALUES) {
|
|
20630
20703
|
let index = from;
|
|
@@ -20764,7 +20837,7 @@ function machinePatterns(env) {
|
|
|
20764
20837
|
return isRecord5(value) ? stringList(value.patterns) : [];
|
|
20765
20838
|
}
|
|
20766
20839
|
function repoPatterns(cwd) {
|
|
20767
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
20840
|
+
return repoHeavyCommands(gitTop(cwd) ?? path24.resolve(cwd));
|
|
20768
20841
|
}
|
|
20769
20842
|
function heavyLines(lines, options) {
|
|
20770
20843
|
const found = [];
|
|
@@ -20833,12 +20906,12 @@ function heavyPlan(command, options) {
|
|
|
20833
20906
|
}
|
|
20834
20907
|
function workitOnPath2(env = process.env) {
|
|
20835
20908
|
const names = process.platform === "win32" ? ["workit.exe", "workit.cmd", "workit"] : ["workit"];
|
|
20836
|
-
for (const dir of (env.PATH ?? "").split(
|
|
20909
|
+
for (const dir of (env.PATH ?? "").split(path24.delimiter))
|
|
20837
20910
|
for (const name of names) {
|
|
20838
20911
|
if (!dir)
|
|
20839
20912
|
continue;
|
|
20840
20913
|
try {
|
|
20841
|
-
|
|
20914
|
+
fs19.accessSync(path24.join(dir, name), fs19.constants.X_OK);
|
|
20842
20915
|
return true;
|
|
20843
20916
|
} catch {}
|
|
20844
20917
|
}
|
|
@@ -20852,9 +20925,9 @@ function leaseRewrite(command) {
|
|
|
20852
20925
|
return null;
|
|
20853
20926
|
return `${prefix}workit check --heavy -- ${rest}`;
|
|
20854
20927
|
}
|
|
20855
|
-
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) =>
|
|
20928
|
+
var HEAVY_COMMANDS_FILE = "heavy-commands.json", heavyCommandsFile = (env) => path24.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"), matches = (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])), readJson = (file) => {
|
|
20856
20929
|
try {
|
|
20857
|
-
return JSON.parse(
|
|
20930
|
+
return JSON.parse(fs19.readFileSync(file, "utf8"));
|
|
20858
20931
|
} catch {
|
|
20859
20932
|
return;
|
|
20860
20933
|
}
|
|
@@ -20996,9 +21069,9 @@ var init_heavy = __esm(() => {
|
|
|
20996
21069
|
});
|
|
20997
21070
|
|
|
20998
21071
|
// packages/workit-core/src/core/heavy-words.ts
|
|
20999
|
-
import
|
|
21072
|
+
import fs20 from "node:fs";
|
|
21000
21073
|
import os8 from "node:os";
|
|
21001
|
-
import
|
|
21074
|
+
import path25 from "node:path";
|
|
21002
21075
|
function maybeHeavy(command, cwd, env = process.env) {
|
|
21003
21076
|
try {
|
|
21004
21077
|
const words = wordsOf(command);
|
|
@@ -21014,30 +21087,30 @@ var HEAVY_WORDS, wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((w
|
|
|
21014
21087
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
21015
21088
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
21016
21089
|
if (env.XDG_STATE_HOME)
|
|
21017
|
-
return
|
|
21090
|
+
return path25.join(env.XDG_STATE_HOME, "workit");
|
|
21018
21091
|
const home = env.HOME || os8.homedir();
|
|
21019
21092
|
if (process.platform === "darwin")
|
|
21020
|
-
return
|
|
21093
|
+
return path25.join(home, "Library", "Application Support", "workit");
|
|
21021
21094
|
if (process.platform === "win32")
|
|
21022
|
-
return
|
|
21023
|
-
return
|
|
21095
|
+
return path25.join(env.LOCALAPPDATA ?? path25.join(home, "AppData", "Local"), "workit");
|
|
21096
|
+
return path25.join(home, ".local", "state", "workit");
|
|
21024
21097
|
}, readJson2 = (file) => {
|
|
21025
21098
|
try {
|
|
21026
|
-
return JSON.parse(
|
|
21099
|
+
return JSON.parse(fs20.readFileSync(file, "utf8"));
|
|
21027
21100
|
} catch {
|
|
21028
21101
|
return;
|
|
21029
21102
|
}
|
|
21030
21103
|
}, patternWords = (cwd, env) => {
|
|
21031
21104
|
const patterns = [];
|
|
21032
|
-
const machine = readJson2(
|
|
21105
|
+
const machine = readJson2(path25.join(stateDir2(env), "heavy-commands.json"));
|
|
21033
21106
|
if (Array.isArray(machine?.patterns))
|
|
21034
21107
|
patterns.push(...machine.patterns);
|
|
21035
|
-
for (let dir =
|
|
21036
|
-
if (
|
|
21108
|
+
for (let dir = path25.resolve(cwd);; dir = path25.dirname(dir)) {
|
|
21109
|
+
if (fs20.existsSync(path25.join(dir, ".git"))) {
|
|
21037
21110
|
patterns.push(...repoHeavyCommands(dir));
|
|
21038
21111
|
break;
|
|
21039
21112
|
}
|
|
21040
|
-
if (
|
|
21113
|
+
if (path25.dirname(dir) === dir)
|
|
21041
21114
|
break;
|
|
21042
21115
|
}
|
|
21043
21116
|
const words = new Set;
|
|
@@ -21104,10 +21177,10 @@ var init_heavy_gate = __esm(() => {
|
|
|
21104
21177
|
|
|
21105
21178
|
// packages/workit-core/src/core/live-session.ts
|
|
21106
21179
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
21107
|
-
import { createHash as
|
|
21108
|
-
import
|
|
21180
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
21181
|
+
import fs21 from "node:fs";
|
|
21109
21182
|
import os9 from "node:os";
|
|
21110
|
-
import
|
|
21183
|
+
import path26 from "node:path";
|
|
21111
21184
|
var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (session) => session.split(":")[0].replace(/-w-.*$/su, "") || session, familyOf = (host) => host.replace(/_(?:cli|desktop)$/u, ""), processAlive = (pid) => {
|
|
21112
21185
|
try {
|
|
21113
21186
|
process.kill(pid, 0);
|
|
@@ -21118,9 +21191,9 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
|
|
|
21118
21191
|
}, processInfo = (pid) => {
|
|
21119
21192
|
try {
|
|
21120
21193
|
if (liveProbe.platform === "linux") {
|
|
21121
|
-
const stat =
|
|
21194
|
+
const stat = fs21.readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
21122
21195
|
const ppid = Number(stat.slice(stat.lastIndexOf(")") + 2).split(" ")[1]);
|
|
21123
|
-
const command =
|
|
21196
|
+
const command = fs21.readFileSync(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ");
|
|
21124
21197
|
return Number.isInteger(ppid) ? { ppid, command: command.trim() } : null;
|
|
21125
21198
|
}
|
|
21126
21199
|
if (liveProbe.platform === "win32")
|
|
@@ -21165,32 +21238,32 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
|
|
|
21165
21238
|
pid: () => hostPid(transport)
|
|
21166
21239
|
};
|
|
21167
21240
|
}, checkoutOf = (target) => {
|
|
21168
|
-
let dir =
|
|
21169
|
-
while (!
|
|
21170
|
-
dir =
|
|
21171
|
-
if (
|
|
21172
|
-
dir =
|
|
21173
|
-
const parts = dir.split(
|
|
21241
|
+
let dir = path26.resolve(target);
|
|
21242
|
+
while (!fs21.existsSync(dir) && path26.dirname(dir) !== dir)
|
|
21243
|
+
dir = path26.dirname(dir);
|
|
21244
|
+
if (fs21.existsSync(dir) && !fs21.statSync(dir).isDirectory())
|
|
21245
|
+
dir = path26.dirname(dir);
|
|
21246
|
+
const parts = dir.split(path26.sep);
|
|
21174
21247
|
const dotGit = parts.lastIndexOf(".git");
|
|
21175
21248
|
if (dotGit > 0)
|
|
21176
|
-
dir = parts.slice(0, dotGit).join(
|
|
21249
|
+
dir = parts.slice(0, dotGit).join(path26.sep) || path26.sep;
|
|
21177
21250
|
const location = resolveStore(dir);
|
|
21178
21251
|
if (location instanceof Error || !location.shared || !location.top)
|
|
21179
21252
|
return null;
|
|
21180
21253
|
let top = location.top;
|
|
21181
21254
|
try {
|
|
21182
|
-
top =
|
|
21255
|
+
top = fs21.realpathSync.native(top);
|
|
21183
21256
|
} catch {}
|
|
21184
21257
|
return top;
|
|
21185
|
-
}, markerFile2 = (top) =>
|
|
21186
|
-
let key =
|
|
21258
|
+
}, markerFile2 = (top) => path26.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`), checkoutKey = (top, platform = process.platform) => {
|
|
21259
|
+
let key = path26.resolve(top);
|
|
21187
21260
|
try {
|
|
21188
|
-
key =
|
|
21261
|
+
key = fs21.realpathSync.native(key);
|
|
21189
21262
|
} catch {}
|
|
21190
21263
|
return platform === "win32" ? key.replaceAll("/", "\\").toLowerCase() : key;
|
|
21191
21264
|
}, readMarker = (file) => {
|
|
21192
21265
|
try {
|
|
21193
|
-
const value = JSON.parse(
|
|
21266
|
+
const value = JSON.parse(fs21.readFileSync(file, "utf8"));
|
|
21194
21267
|
if (value?.version !== 1 || typeof value.session !== "string" || typeof value.host !== "string" || typeof value.heartbeatAt !== "string" || Number.isNaN(Date.parse(value.heartbeatAt)))
|
|
21195
21268
|
return null;
|
|
21196
21269
|
return {
|
|
@@ -21271,10 +21344,10 @@ var LIVE_SESSION_TTL_MS, HEARTBEAT_EVERY_MS = 30000, liveProbe, leadOf = (sessio
|
|
|
21271
21344
|
checkout,
|
|
21272
21345
|
heartbeatAt: now.toISOString()
|
|
21273
21346
|
};
|
|
21274
|
-
|
|
21347
|
+
fs21.mkdirSync(path26.dirname(file), { recursive: true });
|
|
21275
21348
|
const temp = `${file}.${process.pid}.tmp`;
|
|
21276
|
-
|
|
21277
|
-
|
|
21349
|
+
fs21.writeFileSync(temp, JSON.stringify(marker));
|
|
21350
|
+
fs21.renameSync(temp, file);
|
|
21278
21351
|
} catch {}
|
|
21279
21352
|
};
|
|
21280
21353
|
var init_live_session = __esm(() => {
|
|
@@ -21294,7 +21367,7 @@ var init_live_session = __esm(() => {
|
|
|
21294
21367
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
21295
21368
|
import { realpathSync as realpathSync5 } from "node:fs";
|
|
21296
21369
|
import os10 from "node:os";
|
|
21297
|
-
import
|
|
21370
|
+
import path27 from "node:path";
|
|
21298
21371
|
function writeGate(cwd, paths, owner, deps) {
|
|
21299
21372
|
const forged = paths?.length ? issuedTarget(cwd, paths) : null;
|
|
21300
21373
|
if (forged)
|
|
@@ -21322,7 +21395,7 @@ function shellGate(cwd, command, owner, dialect = "posix", deps) {
|
|
|
21322
21395
|
try {
|
|
21323
21396
|
targets = [
|
|
21324
21397
|
...segmentTargets(cwd, command, dialect),
|
|
21325
|
-
...gitMutationDirs(cwd, command, dialect).map((dir) =>
|
|
21398
|
+
...gitMutationDirs(cwd, command, dialect).map((dir) => path27.join(dir, DIR_TARGET))
|
|
21326
21399
|
];
|
|
21327
21400
|
} catch {
|
|
21328
21401
|
targets = [];
|
|
@@ -21360,21 +21433,21 @@ function beforeWriteGate(cwd, paths) {
|
|
|
21360
21433
|
}
|
|
21361
21434
|
var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
21362
21435
|
let rest = "";
|
|
21363
|
-
for (let dir =
|
|
21436
|
+
for (let dir = path27.resolve(file);; dir = path27.dirname(dir)) {
|
|
21364
21437
|
try {
|
|
21365
|
-
return
|
|
21438
|
+
return path27.join(realpathSync5.native(dir), rest);
|
|
21366
21439
|
} catch {
|
|
21367
|
-
if (
|
|
21368
|
-
return
|
|
21369
|
-
rest = rest ?
|
|
21440
|
+
if (path27.dirname(dir) === dir)
|
|
21441
|
+
return path27.resolve(file);
|
|
21442
|
+
rest = rest ? path27.join(path27.basename(dir), rest) : path27.basename(dir);
|
|
21370
21443
|
}
|
|
21371
21444
|
}
|
|
21372
21445
|
}, exempt = (cwd, root, file, plans) => {
|
|
21373
21446
|
const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
|
|
21374
|
-
const relative =
|
|
21375
|
-
if (relative.startsWith("..") ||
|
|
21447
|
+
const relative = path27.relative(fold(canonical2(root)), fold(canonical2(path27.resolve(cwd, file))));
|
|
21448
|
+
if (relative.startsWith("..") || path27.isAbsolute(relative))
|
|
21376
21449
|
return true;
|
|
21377
|
-
const posix = relative.split(
|
|
21450
|
+
const posix = relative.split(path27.sep).join("/");
|
|
21378
21451
|
const segments = posix.split("/");
|
|
21379
21452
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
21380
21453
|
}, PREFIXES2, operands = (words) => words.filter((item) => !item.startsWith("-")), SCRIPT_SHELLS, wrappedScript = (input) => {
|
|
@@ -21487,7 +21560,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21487
21560
|
if (!unknown && targets.length === 0)
|
|
21488
21561
|
return { writes: false, targets: null };
|
|
21489
21562
|
return { writes: true, targets: unknown ? null : targets };
|
|
21490
|
-
}, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(
|
|
21563
|
+
}, cache2, planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path27.resolve(root, file)) ?? "-").join("\x00"), gateFor = (cwd) => {
|
|
21491
21564
|
const store = new TaskStore(cwd);
|
|
21492
21565
|
const listed = store.listTaskIndex();
|
|
21493
21566
|
if (!listed.ok)
|
|
@@ -21540,14 +21613,14 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21540
21613
|
return [];
|
|
21541
21614
|
if (sub === "stash" && ["list", "show"].includes(rest[0] ?? ""))
|
|
21542
21615
|
return [];
|
|
21543
|
-
return [
|
|
21616
|
+
return [path27.resolve(cwd, invocation.dir ?? ".")];
|
|
21544
21617
|
});
|
|
21545
21618
|
}, CD2, PUSHD2, POPD2, cdInto = (dir, words) => {
|
|
21546
21619
|
const named = words.slice(1).find((word) => !word.startsWith("-") || word === "-");
|
|
21547
21620
|
const target = named === undefined ? undefined : homeExpanded(named);
|
|
21548
21621
|
if (dir === undefined || target === "-" || target && /^~|[$`*?]/.test(target))
|
|
21549
21622
|
return;
|
|
21550
|
-
return target === undefined ? os10.homedir() :
|
|
21623
|
+
return target === undefined ? os10.homedir() : path27.resolve(dir, target);
|
|
21551
21624
|
}, quoteWord2 = (word) => /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`, homeExpanded = (file) => {
|
|
21552
21625
|
const match = /^(?:~|\$HOME|\$\{HOME\})(?=\/|$)/.exec(file);
|
|
21553
21626
|
return match ? (process.env.HOME || os10.homedir()) + file.slice(match[0].length) : file;
|
|
@@ -21558,7 +21631,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21558
21631
|
const groups = [];
|
|
21559
21632
|
const at = (file) => {
|
|
21560
21633
|
const home = homeExpanded(file);
|
|
21561
|
-
return
|
|
21634
|
+
return path27.isAbsolute(home) ? home : dir === undefined ? null : path27.resolve(dir, home);
|
|
21562
21635
|
};
|
|
21563
21636
|
for (const segment of segmentsOf(command, dialect)) {
|
|
21564
21637
|
if (segment.group === "open") {
|
|
@@ -21599,7 +21672,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21599
21672
|
const edits = editsOf(segment.words);
|
|
21600
21673
|
if (edits === null) {
|
|
21601
21674
|
if (dir !== undefined)
|
|
21602
|
-
targets.push(
|
|
21675
|
+
targets.push(path27.join(dir, DIR_TARGET));
|
|
21603
21676
|
} else
|
|
21604
21677
|
for (const file of edits) {
|
|
21605
21678
|
const resolved = at(file);
|
|
@@ -21607,7 +21680,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21607
21680
|
targets.push(resolved);
|
|
21608
21681
|
}
|
|
21609
21682
|
if (dir !== undefined && workitInvocations(segment.words.map(quoteWord2).join(" "), "posix").some((args) => args[0] === "git" && MUTATING_WORKIT_GIT.has(args[1] ?? "") && !inert(args.slice(2), "")))
|
|
21610
|
-
targets.push(
|
|
21683
|
+
targets.push(path27.join(dir, DIR_TARGET));
|
|
21611
21684
|
}
|
|
21612
21685
|
return targets;
|
|
21613
21686
|
}, overridden = (command, dialect) => {
|
|
@@ -21630,7 +21703,7 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21630
21703
|
}, guarded = (targets) => {
|
|
21631
21704
|
const seen = new Set;
|
|
21632
21705
|
return targets.filter((target) => {
|
|
21633
|
-
const dir =
|
|
21706
|
+
const dir = path27.dirname(target);
|
|
21634
21707
|
if (seen.has(dir))
|
|
21635
21708
|
return false;
|
|
21636
21709
|
seen.add(dir);
|
|
@@ -21648,13 +21721,13 @@ var NONE3, CASE_INSENSITIVE, canonical2 = (file) => {
|
|
|
21648
21721
|
}, claimAll = (owner, targets, deps) => {
|
|
21649
21722
|
for (const target of guarded(targets))
|
|
21650
21723
|
claimLiveSession(target, owner, deps);
|
|
21651
|
-
}, liveTargets = (cwd, paths) => paths?.length ? paths.map((file) =>
|
|
21724
|
+
}, liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path27.resolve(cwd, file)) : [path27.join(cwd, DIR_TARGET)], issuedTarget = (cwd, targets) => {
|
|
21652
21725
|
const state = resolveStateDir();
|
|
21653
21726
|
const found = targets.find((target) => underIssued(state, cwd, homeExpanded(target), process.platform, canonical2));
|
|
21654
21727
|
return found ?? null;
|
|
21655
21728
|
}, underIssued = (state, cwd, target, platform = process.platform, real = (file) => file) => {
|
|
21656
21729
|
const win = platform === "win32";
|
|
21657
|
-
const p = win ?
|
|
21730
|
+
const p = win ? path27.win32 : path27.posix;
|
|
21658
21731
|
const fold = (value) => win || platform === "darwin" ? value.toLowerCase() : value;
|
|
21659
21732
|
const named = win ? target.replace(/^\/([a-zA-Z])(?=\/|$)/, "$1:") : target;
|
|
21660
21733
|
const relative = p.relative(fold(real(p.resolve(state))), fold(real(p.resolve(cwd, named))));
|
|
@@ -22111,9 +22184,9 @@ var init_skill_nudge = __esm(() => {
|
|
|
22111
22184
|
|
|
22112
22185
|
// packages/workit-core/src/hooks/hosts/fields.ts
|
|
22113
22186
|
import { existsSync as existsSync7, realpathSync as realpathSync6, statSync as statSync2 } from "node:fs";
|
|
22114
|
-
import
|
|
22187
|
+
import path28 from "node:path";
|
|
22115
22188
|
var isRecord6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "", optionalText = (value) => typeof value === "string" ? value : null, existingDirectory = (value) => {
|
|
22116
|
-
if (!nonEmpty2(value) || !
|
|
22189
|
+
if (!nonEmpty2(value) || !path28.isAbsolute(value) || !existsSync7(value))
|
|
22117
22190
|
return null;
|
|
22118
22191
|
try {
|
|
22119
22192
|
return statSync2(value).isDirectory() ? realpathSync6(value) : null;
|
|
@@ -22177,8 +22250,119 @@ var init_fields = __esm(() => {
|
|
|
22177
22250
|
PATCH_HEADER = /^[ \t]*\*\*\* (?:(?:Add|Update|Delete) File|Move to): (.+)$/gm;
|
|
22178
22251
|
});
|
|
22179
22252
|
|
|
22253
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
22254
|
+
import fs22 from "node:fs";
|
|
22255
|
+
import path29 from "node:path";
|
|
22256
|
+
var readPlans = (store) => {
|
|
22257
|
+
const dir = path29.join(store, "fanouts");
|
|
22258
|
+
let names;
|
|
22259
|
+
try {
|
|
22260
|
+
names = fs22.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
22261
|
+
} catch {
|
|
22262
|
+
return [];
|
|
22263
|
+
}
|
|
22264
|
+
const plans = [];
|
|
22265
|
+
for (const name of names) {
|
|
22266
|
+
try {
|
|
22267
|
+
const raw = JSON.parse(fs22.readFileSync(path29.join(dir, name), "utf8"));
|
|
22268
|
+
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
22269
|
+
continue;
|
|
22270
|
+
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
22271
|
+
plans.push({
|
|
22272
|
+
name: raw.name,
|
|
22273
|
+
leads: texts([raw.leadSession, ...texts(raw.formerLeads)]),
|
|
22274
|
+
branches: texts(raw.slices.map((slice) => slice && typeof slice === "object" ? slice.branch : null))
|
|
22275
|
+
});
|
|
22276
|
+
} catch {}
|
|
22277
|
+
}
|
|
22278
|
+
return plans;
|
|
22279
|
+
}, leadOf2 = (input) => input.session.parentId ?? (input.session.agentId ? input.session.id : null) ?? (input.session.id.includes(":") ? input.session.id.split(":")[0] : null), worksFor = (plan, input, branch) => {
|
|
22280
|
+
const session = input.session.id;
|
|
22281
|
+
if (plan.leads.includes(session) && !input.session.agentId)
|
|
22282
|
+
return false;
|
|
22283
|
+
const lead = leadOf2(input);
|
|
22284
|
+
if (lead && plan.leads.includes(lead))
|
|
22285
|
+
return true;
|
|
22286
|
+
if (plan.leads.some((each) => session.startsWith(`${each}-w-`)))
|
|
22287
|
+
return true;
|
|
22288
|
+
const current = branch();
|
|
22289
|
+
return current !== null && plan.branches.includes(current);
|
|
22290
|
+
}, standingFor = (input, store, rev) => {
|
|
22291
|
+
const orders = new Map;
|
|
22292
|
+
const ledger = readLedger(input.cwd);
|
|
22293
|
+
const rows = ledger.ok ? ledger.value.rows : [];
|
|
22294
|
+
let branch;
|
|
22295
|
+
const lazyBranch = () => branch === undefined ? branch = currentBranch(input.cwd) : branch;
|
|
22296
|
+
for (const plan of readPlans(store))
|
|
22297
|
+
if (worksFor(plan, input, lazyBranch))
|
|
22298
|
+
for (const row of activeStanding(rows, plan.name, plan.leads.length ? plan.leads : null))
|
|
22299
|
+
orders.set(row.id, row);
|
|
22300
|
+
return { rev, orders, rows };
|
|
22301
|
+
}, located = (input) => {
|
|
22302
|
+
const store = input.session.id ? gitStoreDir(input.cwd) : null;
|
|
22303
|
+
const rev = store ? readStandingRev(store) : null;
|
|
22304
|
+
if (!store || rev === null)
|
|
22305
|
+
return null;
|
|
22306
|
+
return { store, rev, file: standingSeenFile(store, input.session.id, input.session.agentId) };
|
|
22307
|
+
}, seedStanding = (input) => {
|
|
22308
|
+
try {
|
|
22309
|
+
const where = located(input);
|
|
22310
|
+
if (!where)
|
|
22311
|
+
return;
|
|
22312
|
+
const now = standingFor(input, where.store, where.rev);
|
|
22313
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
22314
|
+
} catch {}
|
|
22315
|
+
}, fanoutOf = (row) => typeof row.fanout === "string" ? row.fanout : "?", changedSince = (now, ids) => {
|
|
22316
|
+
const known = new Set(ids);
|
|
22317
|
+
const added = [...now.orders.values()].filter((row) => !known.has(row.id));
|
|
22318
|
+
const byId = new Map(now.rows.map((row) => [row.id, row]));
|
|
22319
|
+
const dropped = ids.filter((id) => !now.orders.has(id)).map((id) => byId.get(id)).filter((row) => row !== undefined);
|
|
22320
|
+
if (!added.length && !dropped.length)
|
|
22321
|
+
return null;
|
|
22322
|
+
const fanouts = [...new Set([...added, ...dropped].map(fanoutOf))].join(", ");
|
|
22323
|
+
const lines = [
|
|
22324
|
+
`Workit: the lead changed the standing orders for fanout ${fanouts} while you run. They apply to you now and override your brief's STANDING list.`,
|
|
22325
|
+
...added.map((row) => ` - new: ${String(row.what)}`),
|
|
22326
|
+
...dropped.map((row) => ` - no longer in force: ${String(row.what)}${row.stop ? " (the stop is lifted: continue your brief)" : ""}`)
|
|
22327
|
+
];
|
|
22328
|
+
if (added.some((row) => row.stop === true))
|
|
22329
|
+
lines.push("Stop now: make no further changes, close what you opened, and report to the lead with your branch, head SHA, what is done and what is not.");
|
|
22330
|
+
return lines.join(`
|
|
22331
|
+
`);
|
|
22332
|
+
}, standingDelta = (input) => {
|
|
22333
|
+
try {
|
|
22334
|
+
const where = located(input);
|
|
22335
|
+
if (!where)
|
|
22336
|
+
return null;
|
|
22337
|
+
const seen = readStandingSeen(where.file);
|
|
22338
|
+
if (seen.rev === where.rev)
|
|
22339
|
+
return null;
|
|
22340
|
+
const now = standingFor(input, where.store, where.rev);
|
|
22341
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
22342
|
+
return changedSince(now, seen.ids);
|
|
22343
|
+
} catch {
|
|
22344
|
+
return null;
|
|
22345
|
+
}
|
|
22346
|
+
}, sinceStart;
|
|
22347
|
+
var init_standing = __esm(() => {
|
|
22348
|
+
init_rev();
|
|
22349
|
+
init_ledger();
|
|
22350
|
+
init_standing_signal();
|
|
22351
|
+
sinceStart = new Map;
|
|
22352
|
+
});
|
|
22353
|
+
|
|
22180
22354
|
// packages/workit-core/src/hooks/handle.ts
|
|
22181
22355
|
function handleHook(input, deps) {
|
|
22356
|
+
const decision = decide(input, deps);
|
|
22357
|
+
if (deps.descriptor.transport !== "hook-process" || !PRE_TOOL.has(input.event.kind) || decision.kind === "deny")
|
|
22358
|
+
return decision;
|
|
22359
|
+
const delta = standingDelta(input);
|
|
22360
|
+
if (!delta)
|
|
22361
|
+
return decision;
|
|
22362
|
+
return decision.kind === "rewrite" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
22363
|
+
`) } : withContextLine(decision, delta);
|
|
22364
|
+
}
|
|
22365
|
+
function decide(input, deps) {
|
|
22182
22366
|
const { descriptor } = deps;
|
|
22183
22367
|
const event = input.event;
|
|
22184
22368
|
switch (event.kind) {
|
|
@@ -22255,6 +22439,7 @@ function handleHook(input, deps) {
|
|
|
22255
22439
|
case "write.pre":
|
|
22256
22440
|
return usable2(descriptor.events["write.pre"].support) ? writeGate(input.cwd, event.paths, liveOwner(input, descriptor.transport)) : NONE5;
|
|
22257
22441
|
case "subagent.start":
|
|
22442
|
+
seedStanding({ ...input, session: { ...input.session, agentId: event.agentId } });
|
|
22258
22443
|
return {
|
|
22259
22444
|
kind: "context",
|
|
22260
22445
|
text: subagentStartText(input, descriptor, event)
|
|
@@ -22304,7 +22489,7 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
|
22304
22489
|
const line = verdictCommand({ branch: judgeBranch(cwd), judge, session: own, token });
|
|
22305
22490
|
const pick = judge === "verifier" ? ", --kind live when you drove the real surface" : "";
|
|
22306
22491
|
return `${readOnly} Its own Workit session is ${own}, so the ledger tells its verdicts apart from the author's. Record the verdict with exactly this command (pick the result${pick}, name the candidate branch if it differs, say what you ran): \`${line}\`.${token ? " The token is this subagent's alone: never write it into a report, a file or a commit. --token needs a workit CLI at least as new as this plugin; if the CLI answers that --token is an unknown option, update the workit CLI (workit upgrade --cli) and record again." : ""}`;
|
|
22307
|
-
}, failureDecision = (descriptor, event, error) => {
|
|
22492
|
+
}, PRE_TOOL, failureDecision = (descriptor, event, error) => {
|
|
22308
22493
|
if (event === "shell.pre" || event === "tool.pre" || event === "write.pre")
|
|
22309
22494
|
return descriptor.shellPolicy.failClosed ? { kind: "deny", reason: error, unblock: null } : NONE5;
|
|
22310
22495
|
if (event === "session.start" || event === "subagent.start")
|
|
@@ -22341,6 +22526,7 @@ var init_handle = __esm(() => {
|
|
|
22341
22526
|
init_policy();
|
|
22342
22527
|
init_raw_git();
|
|
22343
22528
|
init_skill_nudge();
|
|
22529
|
+
init_standing();
|
|
22344
22530
|
init_stop();
|
|
22345
22531
|
init_live_session();
|
|
22346
22532
|
init_write_gate();
|
|
@@ -22352,18 +22538,19 @@ var init_handle = __esm(() => {
|
|
|
22352
22538
|
reviewer: "judge"
|
|
22353
22539
|
};
|
|
22354
22540
|
CLAUDE_WORKTREE = /[\\/]\.claude[\\/]worktrees[\\/]/;
|
|
22541
|
+
PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
22355
22542
|
});
|
|
22356
22543
|
|
|
22357
22544
|
// packages/workit-core/src/hooks/deadline.ts
|
|
22358
22545
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
22359
|
-
import
|
|
22546
|
+
import path30 from "node:path";
|
|
22360
22547
|
var HOOK_SKIP_TEXT = "workit context skipped: host under load", HOOK_DEADLINE_MS = 8000, HOST_DEADLINES, HOOK_SKIPS_FILE = "hook-skips.jsonl", override = (env) => {
|
|
22361
22548
|
const value = Number(env.WORKIT_HOOK_DEADLINE_MS);
|
|
22362
22549
|
return Number.isFinite(value) && value > 0 ? value : null;
|
|
22363
22550
|
}, hookDeadlineMs = (env, host = "", native) => {
|
|
22364
22551
|
const row = HOST_DEADLINES[host];
|
|
22365
22552
|
return override(env) ?? (row ? native === undefined ? Math.min(...Object.values(row)) : row[native] ?? row[""] : HOOK_DEADLINE_MS);
|
|
22366
|
-
}, skipsFile = (stateDir) =>
|
|
22553
|
+
}, skipsFile = (stateDir) => path30.join(stateDir, HOOK_SKIPS_FILE), recordHookSkip = (skip, stateDir = resolveStateDir()) => {
|
|
22367
22554
|
try {
|
|
22368
22555
|
mkdirSync3(stateDir, { recursive: true });
|
|
22369
22556
|
appendFileSync(skipsFile(stateDir), `${JSON.stringify(skip)}
|
|
@@ -23007,8 +23194,8 @@ var init_codex = __esm(() => {
|
|
|
23007
23194
|
});
|
|
23008
23195
|
|
|
23009
23196
|
// packages/workit-core/src/hooks/hosts/cursor.ts
|
|
23010
|
-
import
|
|
23011
|
-
import
|
|
23197
|
+
import fs23 from "node:fs";
|
|
23198
|
+
import path31 from "node:path";
|
|
23012
23199
|
var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (value) => {
|
|
23013
23200
|
if (!isRecord6(value) || !Object.hasOwn(EVENTS3, String(value.hook_event_name)))
|
|
23014
23201
|
return { ok: false, error: "hook_event_name is required" };
|
|
@@ -23089,17 +23276,17 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
|
|
|
23089
23276
|
};
|
|
23090
23277
|
}
|
|
23091
23278
|
}, TRANSCRIPT_TAIL_BYTES, lastAssistantText = (file) => {
|
|
23092
|
-
if (!file || !
|
|
23279
|
+
if (!file || !path31.isAbsolute(file))
|
|
23093
23280
|
return null;
|
|
23094
23281
|
try {
|
|
23095
|
-
const size =
|
|
23282
|
+
const size = fs23.statSync(file).size;
|
|
23096
23283
|
const start = Math.max(0, size - TRANSCRIPT_TAIL_BYTES);
|
|
23097
23284
|
const buffer = Buffer.alloc(size - start);
|
|
23098
|
-
const fd =
|
|
23285
|
+
const fd = fs23.openSync(file, "r");
|
|
23099
23286
|
try {
|
|
23100
|
-
|
|
23287
|
+
fs23.readSync(fd, buffer, 0, buffer.length, start);
|
|
23101
23288
|
} finally {
|
|
23102
|
-
|
|
23289
|
+
fs23.closeSync(fd);
|
|
23103
23290
|
}
|
|
23104
23291
|
const lines = buffer.toString("utf8").split(`
|
|
23105
23292
|
`);
|
|
@@ -23125,7 +23312,7 @@ var undocumented, none, CURSOR_DESCRIPTOR, EVENTS3, parseCursorHookInput = (valu
|
|
|
23125
23312
|
} catch {
|
|
23126
23313
|
return null;
|
|
23127
23314
|
}
|
|
23128
|
-
}, within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(
|
|
23315
|
+
}, within2 = (root, dir) => dir === root || dir.startsWith(root.endsWith(path31.sep) ? root : `${root}${path31.sep}`), hookCwd = (input) => {
|
|
23129
23316
|
const cwd = existingDirectory(input.cwd);
|
|
23130
23317
|
if (cwd && input.hook_event_name === "beforeShellExecution")
|
|
23131
23318
|
return cwd;
|
|
@@ -23359,6 +23546,7 @@ var init_hooks = __esm(async () => {
|
|
|
23359
23546
|
init_raw_git();
|
|
23360
23547
|
init_skill_nudge();
|
|
23361
23548
|
init_fields();
|
|
23549
|
+
init_standing();
|
|
23362
23550
|
init_handle();
|
|
23363
23551
|
init_claude_code();
|
|
23364
23552
|
init_codex();
|