@brainervirus/workit-pi 8.19.2 → 8.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker.js +596 -7
- package/dist/workit.js +464 -245
- package/package.json +1 -1
package/dist/workit.js
CHANGED
|
@@ -5,7 +5,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
5
5
|
// packages/workit-core/src/core.ts
|
|
6
6
|
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
7
7
|
import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
8
|
-
import
|
|
8
|
+
import path25 from "node:path";
|
|
9
9
|
|
|
10
10
|
// packages/workit-core/src/core/task-contract.ts
|
|
11
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -14381,10 +14381,10 @@ var isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state);
|
|
|
14381
14381
|
var workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state);
|
|
14382
14382
|
|
|
14383
14383
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
14384
|
-
import { createHash as
|
|
14385
|
-
import * as
|
|
14384
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
14385
|
+
import * as fs14 from "node:fs";
|
|
14386
14386
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
14387
|
-
import
|
|
14387
|
+
import path17 from "node:path";
|
|
14388
14388
|
|
|
14389
14389
|
// packages/workit-core/src/check-config.ts
|
|
14390
14390
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
@@ -14615,13 +14615,70 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
14615
14615
|
|
|
14616
14616
|
// packages/workit-core/src/core/policy/derive.ts
|
|
14617
14617
|
import { existsSync as existsSync4 } from "node:fs";
|
|
14618
|
-
import
|
|
14618
|
+
import path16 from "node:path";
|
|
14619
14619
|
|
|
14620
14620
|
// packages/workit-core/src/ledger.ts
|
|
14621
14621
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
14622
|
-
import { createHash as
|
|
14622
|
+
import { createHash as createHash11, randomBytes as randomBytes3 } from "node:crypto";
|
|
14623
|
+
import fs13 from "node:fs";
|
|
14624
|
+
import path15 from "node:path";
|
|
14625
|
+
|
|
14626
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
14627
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
14623
14628
|
import fs12 from "node:fs";
|
|
14624
14629
|
import path14 from "node:path";
|
|
14630
|
+
var gitStoreDir = (cwd) => {
|
|
14631
|
+
try {
|
|
14632
|
+
for (let dir = path14.resolve(cwd);; dir = path14.dirname(dir)) {
|
|
14633
|
+
const dotGit = path14.join(dir, ".git");
|
|
14634
|
+
if (fs12.existsSync(dotGit)) {
|
|
14635
|
+
let gitDir = dotGit;
|
|
14636
|
+
if (fs12.statSync(dotGit).isFile()) {
|
|
14637
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs12.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
14638
|
+
if (!target)
|
|
14639
|
+
return null;
|
|
14640
|
+
gitDir = path14.resolve(dir, target);
|
|
14641
|
+
const common = path14.join(gitDir, "commondir");
|
|
14642
|
+
if (fs12.existsSync(common))
|
|
14643
|
+
gitDir = path14.resolve(gitDir, fs12.readFileSync(common, "utf8").trim());
|
|
14644
|
+
}
|
|
14645
|
+
return path14.join(gitDir, "workit");
|
|
14646
|
+
}
|
|
14647
|
+
if (path14.dirname(dir) === dir)
|
|
14648
|
+
return null;
|
|
14649
|
+
}
|
|
14650
|
+
} catch {
|
|
14651
|
+
return null;
|
|
14652
|
+
}
|
|
14653
|
+
};
|
|
14654
|
+
var standingRevFile = (store) => path14.join(store, "standing", "rev");
|
|
14655
|
+
var standingSeenFile = (store, session, agentId) => path14.join(store, "standing", "seen", `${createHash10("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
14656
|
+
var readStandingRev = (store) => {
|
|
14657
|
+
try {
|
|
14658
|
+
return fs12.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
14659
|
+
} catch {
|
|
14660
|
+
return null;
|
|
14661
|
+
}
|
|
14662
|
+
};
|
|
14663
|
+
var readStandingSeen = (file) => {
|
|
14664
|
+
try {
|
|
14665
|
+
const value = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
14666
|
+
return {
|
|
14667
|
+
rev: typeof value.rev === "string" ? value.rev : null,
|
|
14668
|
+
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
14669
|
+
};
|
|
14670
|
+
} catch {
|
|
14671
|
+
return { rev: null, ids: [] };
|
|
14672
|
+
}
|
|
14673
|
+
};
|
|
14674
|
+
var writeStandingSeen = (file, seen) => {
|
|
14675
|
+
try {
|
|
14676
|
+
fs12.mkdirSync(path14.dirname(file), { recursive: true });
|
|
14677
|
+
fs12.writeFileSync(file, JSON.stringify(seen));
|
|
14678
|
+
} catch {}
|
|
14679
|
+
};
|
|
14680
|
+
|
|
14681
|
+
// packages/workit-core/src/ledger.ts
|
|
14625
14682
|
var LEDGER_VERSION = 1;
|
|
14626
14683
|
var MAX_LINE_BYTES = 4096;
|
|
14627
14684
|
var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
|
|
@@ -14731,7 +14788,7 @@ function diffHash(cwd, base, head) {
|
|
|
14731
14788
|
], GIT_TIMEOUTS.worktree);
|
|
14732
14789
|
if (!diff.ok || !diff.stdout)
|
|
14733
14790
|
return null;
|
|
14734
|
-
const hash =
|
|
14791
|
+
const hash = createHash11("sha256");
|
|
14735
14792
|
for (const line of diff.stdout.split(`
|
|
14736
14793
|
`)) {
|
|
14737
14794
|
if (line.startsWith("index "))
|
|
@@ -14743,14 +14800,14 @@ function diffHash(cwd, base, head) {
|
|
|
14743
14800
|
return `sha256:${hash.digest("hex")}`;
|
|
14744
14801
|
}
|
|
14745
14802
|
function storeRoot(cwd) {
|
|
14746
|
-
const location = resolveStore(
|
|
14803
|
+
const location = resolveStore(path15.resolve(cwd));
|
|
14747
14804
|
if (location instanceof Error)
|
|
14748
14805
|
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");
|
|
14749
14806
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
14750
14807
|
}
|
|
14751
14808
|
function ledgerPath(cwd) {
|
|
14752
14809
|
const root = storeRoot(cwd);
|
|
14753
|
-
return root.ok ? { ok: true, value:
|
|
14810
|
+
return root.ok ? { ok: true, value: path15.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
14754
14811
|
}
|
|
14755
14812
|
var newId2 = () => `${Date.now().toString(36)}-${randomBytes3(6).toString("hex")}`;
|
|
14756
14813
|
var NETWORK_FS_TYPES = new Set([
|
|
@@ -14770,7 +14827,7 @@ var onNetworkFs = (dir) => {
|
|
|
14770
14827
|
if (process.platform !== "linux")
|
|
14771
14828
|
return false;
|
|
14772
14829
|
try {
|
|
14773
|
-
return isNetworkFsType(
|
|
14830
|
+
return isNetworkFsType(fs13.statfsSync(dir).type);
|
|
14774
14831
|
} catch {
|
|
14775
14832
|
return false;
|
|
14776
14833
|
}
|
|
@@ -14780,15 +14837,15 @@ var LOCK_STALE_MS = 30000;
|
|
|
14780
14837
|
var LOCK_OWNER = "owner";
|
|
14781
14838
|
var lockToken = (lock) => {
|
|
14782
14839
|
try {
|
|
14783
|
-
return
|
|
14840
|
+
return fs13.readFileSync(path15.join(lock, LOCK_OWNER), "utf8");
|
|
14784
14841
|
} catch {
|
|
14785
14842
|
return null;
|
|
14786
14843
|
}
|
|
14787
14844
|
};
|
|
14788
14845
|
var lockAgeMs = (lock) => {
|
|
14789
|
-
for (const target of [
|
|
14846
|
+
for (const target of [path15.join(lock, LOCK_OWNER), lock]) {
|
|
14790
14847
|
try {
|
|
14791
|
-
return Date.now() -
|
|
14848
|
+
return Date.now() - fs13.statSync(target).mtimeMs;
|
|
14792
14849
|
} catch {}
|
|
14793
14850
|
}
|
|
14794
14851
|
return null;
|
|
@@ -14796,14 +14853,14 @@ var lockAgeMs = (lock) => {
|
|
|
14796
14853
|
var ledgerLock = {
|
|
14797
14854
|
acquire(lock) {
|
|
14798
14855
|
try {
|
|
14799
|
-
|
|
14856
|
+
fs13.mkdirSync(lock);
|
|
14800
14857
|
} catch (error) {
|
|
14801
14858
|
if (error.code === "EEXIST")
|
|
14802
14859
|
return null;
|
|
14803
14860
|
throw error;
|
|
14804
14861
|
}
|
|
14805
14862
|
const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
|
|
14806
|
-
|
|
14863
|
+
fs13.writeFileSync(path15.join(lock, LOCK_OWNER), token);
|
|
14807
14864
|
return token;
|
|
14808
14865
|
},
|
|
14809
14866
|
release(lock, token) {
|
|
@@ -14811,35 +14868,35 @@ var ledgerLock = {
|
|
|
14811
14868
|
return false;
|
|
14812
14869
|
const tomb = `${lock}.release-${randomBytes3(6).toString("hex")}`;
|
|
14813
14870
|
try {
|
|
14814
|
-
|
|
14871
|
+
fs13.renameSync(lock, tomb);
|
|
14815
14872
|
} catch {
|
|
14816
14873
|
return false;
|
|
14817
14874
|
}
|
|
14818
14875
|
if (lockToken(tomb) !== token) {
|
|
14819
14876
|
try {
|
|
14820
|
-
|
|
14877
|
+
fs13.renameSync(tomb, lock);
|
|
14821
14878
|
} catch {}
|
|
14822
14879
|
return false;
|
|
14823
14880
|
}
|
|
14824
|
-
|
|
14881
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14825
14882
|
return true;
|
|
14826
14883
|
},
|
|
14827
14884
|
token: lockToken,
|
|
14828
14885
|
reap(lock, observed) {
|
|
14829
14886
|
const tomb = `${lock}.reap-${randomBytes3(6).toString("hex")}`;
|
|
14830
14887
|
try {
|
|
14831
|
-
|
|
14888
|
+
fs13.renameSync(lock, tomb);
|
|
14832
14889
|
} catch {
|
|
14833
14890
|
return false;
|
|
14834
14891
|
}
|
|
14835
14892
|
if (lockToken(tomb) === observed) {
|
|
14836
|
-
|
|
14893
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14837
14894
|
return true;
|
|
14838
14895
|
}
|
|
14839
14896
|
try {
|
|
14840
|
-
|
|
14897
|
+
fs13.renameSync(tomb, lock);
|
|
14841
14898
|
} catch {
|
|
14842
|
-
|
|
14899
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14843
14900
|
}
|
|
14844
14901
|
return false;
|
|
14845
14902
|
}
|
|
@@ -14866,14 +14923,14 @@ function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
|
|
|
14866
14923
|
ledgerLock.release(lock, token);
|
|
14867
14924
|
}
|
|
14868
14925
|
}
|
|
14869
|
-
var sha2562 = (text) =>
|
|
14926
|
+
var sha2562 = (text) => createHash11("sha256").update(text).digest("hex");
|
|
14870
14927
|
var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
|
|
14871
14928
|
${body}`);
|
|
14872
14929
|
var TAIL_BYTES = 64 * 1024;
|
|
14873
14930
|
var lastLine = (fd, size) => {
|
|
14874
14931
|
for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
|
|
14875
14932
|
const buffer = Buffer.alloc(span);
|
|
14876
|
-
|
|
14933
|
+
fs13.readSync(fd, buffer, 0, span, size - span);
|
|
14877
14934
|
const end = buffer.lastIndexOf(10);
|
|
14878
14935
|
if (end < 0) {
|
|
14879
14936
|
if (span === size)
|
|
@@ -14904,21 +14961,21 @@ var lastLine = (fd, size) => {
|
|
|
14904
14961
|
};
|
|
14905
14962
|
var tighten = (fd) => {
|
|
14906
14963
|
try {
|
|
14907
|
-
if ((
|
|
14908
|
-
|
|
14964
|
+
if ((fs13.fstatSync(fd).mode & 63) !== 0)
|
|
14965
|
+
fs13.fchmodSync(fd, 384);
|
|
14909
14966
|
} catch {}
|
|
14910
14967
|
};
|
|
14911
14968
|
function appendLine(file, build, options) {
|
|
14912
14969
|
const write = () => {
|
|
14913
|
-
const fd =
|
|
14970
|
+
const fd = fs13.openSync(file, "a+", 384);
|
|
14914
14971
|
try {
|
|
14915
14972
|
if (process.platform !== "win32")
|
|
14916
14973
|
tighten(fd);
|
|
14917
|
-
const size =
|
|
14974
|
+
const size = fs13.fstatSync(fd).size;
|
|
14918
14975
|
let fence = "";
|
|
14919
14976
|
if (size > 0) {
|
|
14920
14977
|
const last = Buffer.alloc(1);
|
|
14921
|
-
|
|
14978
|
+
fs13.readSync(fd, last, 0, 1, size - 1);
|
|
14922
14979
|
if (last[0] !== 10)
|
|
14923
14980
|
fence = `
|
|
14924
14981
|
`;
|
|
@@ -14927,17 +14984,17 @@ function appendLine(file, build, options) {
|
|
|
14927
14984
|
if (!line.ok)
|
|
14928
14985
|
return line;
|
|
14929
14986
|
const bytes = Buffer.from(fence + line.value);
|
|
14930
|
-
const written =
|
|
14987
|
+
const written = fs13.writeSync(fd, bytes);
|
|
14931
14988
|
if (written !== bytes.length)
|
|
14932
14989
|
return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
|
|
14933
14990
|
return { ok: true, value: undefined };
|
|
14934
14991
|
} finally {
|
|
14935
|
-
|
|
14992
|
+
fs13.closeSync(fd);
|
|
14936
14993
|
}
|
|
14937
14994
|
};
|
|
14938
14995
|
try {
|
|
14939
|
-
|
|
14940
|
-
if (!options.forceLock && !onNetworkFs(
|
|
14996
|
+
fs13.mkdirSync(path15.dirname(file), { recursive: true });
|
|
14997
|
+
if (!options.forceLock && !onNetworkFs(path15.dirname(file)))
|
|
14941
14998
|
return write();
|
|
14942
14999
|
const locked = withLedgerLock(file, write);
|
|
14943
15000
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -15010,8 +15067,8 @@ function readLedger(cwd, options = {}) {
|
|
|
15010
15067
|
let text = "";
|
|
15011
15068
|
let stat = null;
|
|
15012
15069
|
try {
|
|
15013
|
-
stat =
|
|
15014
|
-
text =
|
|
15070
|
+
stat = fs13.statSync(file.value);
|
|
15071
|
+
text = fs13.readFileSync(file.value, "utf8");
|
|
15015
15072
|
} catch (error) {
|
|
15016
15073
|
if (error.code === "ENOENT")
|
|
15017
15074
|
return {
|
|
@@ -15146,7 +15203,7 @@ function ledgerTampering(cwd) {
|
|
|
15146
15203
|
if (!file.ok)
|
|
15147
15204
|
return [];
|
|
15148
15205
|
try {
|
|
15149
|
-
const stat =
|
|
15206
|
+
const stat = fs13.statSync(file.value);
|
|
15150
15207
|
const cached = tamperCache.get(file.value);
|
|
15151
15208
|
if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
|
|
15152
15209
|
return cached.breaks;
|
|
@@ -15477,6 +15534,28 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15477
15534
|
warnings
|
|
15478
15535
|
};
|
|
15479
15536
|
}
|
|
15537
|
+
var fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session);
|
|
15538
|
+
function activeStanding(rows, fanout, leads = null) {
|
|
15539
|
+
const active = [];
|
|
15540
|
+
for (const row of rows) {
|
|
15541
|
+
if (row.fanout !== fanout || !fromLead(row, leads))
|
|
15542
|
+
continue;
|
|
15543
|
+
if (row.type === "standing" && typeof row.what === "string" && row.what.trim()) {
|
|
15544
|
+
if (!row.superseded)
|
|
15545
|
+
active.push(row);
|
|
15546
|
+
} else if (row.type === "standing.cleared") {
|
|
15547
|
+
const target = str2(row.target);
|
|
15548
|
+
if (target === null)
|
|
15549
|
+
active.length = 0;
|
|
15550
|
+
else {
|
|
15551
|
+
const index = active.findIndex((order) => order.id === target);
|
|
15552
|
+
if (index >= 0)
|
|
15553
|
+
active.splice(index, 1);
|
|
15554
|
+
}
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15557
|
+
return active;
|
|
15558
|
+
}
|
|
15480
15559
|
var OBSERVED_ONLY = new Set([
|
|
15481
15560
|
"check",
|
|
15482
15561
|
"merge.unverified",
|
|
@@ -15625,7 +15704,7 @@ var productDecision = (task, ledger) => {
|
|
|
15625
15704
|
};
|
|
15626
15705
|
};
|
|
15627
15706
|
var planRecorded = (task, root) => {
|
|
15628
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(
|
|
15707
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path16.resolve(root, ref.path)));
|
|
15629
15708
|
if (cited)
|
|
15630
15709
|
return {
|
|
15631
15710
|
met: true,
|
|
@@ -15684,15 +15763,15 @@ function writeBlockers(task, root) {
|
|
|
15684
15763
|
}
|
|
15685
15764
|
|
|
15686
15765
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
15687
|
-
var digestBytes = (value) =>
|
|
15688
|
-
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
15689
|
-
var relative = (root, candidate) =>
|
|
15766
|
+
var digestBytes = (value) => createHash12("sha256").update(value).digest("hex");
|
|
15767
|
+
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`);
|
|
15768
|
+
var relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".";
|
|
15690
15769
|
var canonicalPath = (value) => {
|
|
15691
15770
|
if (typeof value !== "string" || !value)
|
|
15692
15771
|
return null;
|
|
15693
15772
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
15694
15773
|
return null;
|
|
15695
|
-
const normalized =
|
|
15774
|
+
const normalized = path17.posix.normalize(value);
|
|
15696
15775
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
15697
15776
|
return null;
|
|
15698
15777
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -15740,21 +15819,21 @@ var gitPaths = (root) => {
|
|
|
15740
15819
|
git: !/not a git repository/i.test(stderr)
|
|
15741
15820
|
};
|
|
15742
15821
|
}
|
|
15743
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15822
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
|
|
15744
15823
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
15745
15824
|
if (stagedDeleted.status !== 0) {
|
|
15746
15825
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
15747
15826
|
if (!/not a git repository/i.test(stderr))
|
|
15748
15827
|
return { paths, uncertain: true, git: true };
|
|
15749
15828
|
} else if (stagedDeleted.stdout) {
|
|
15750
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15829
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
|
|
15751
15830
|
}
|
|
15752
15831
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
15753
15832
|
};
|
|
15754
15833
|
var walk = (root, directory, output) => {
|
|
15755
15834
|
let names;
|
|
15756
15835
|
try {
|
|
15757
|
-
names =
|
|
15836
|
+
names = fs14.readdirSync(directory);
|
|
15758
15837
|
} catch {
|
|
15759
15838
|
return true;
|
|
15760
15839
|
}
|
|
@@ -15762,10 +15841,10 @@ var walk = (root, directory, output) => {
|
|
|
15762
15841
|
for (const name of names) {
|
|
15763
15842
|
if (name === ".git" || name === ".workit")
|
|
15764
15843
|
continue;
|
|
15765
|
-
const target =
|
|
15844
|
+
const target = path17.join(directory, name);
|
|
15766
15845
|
let stat;
|
|
15767
15846
|
try {
|
|
15768
|
-
stat =
|
|
15847
|
+
stat = fs14.lstatSync(target);
|
|
15769
15848
|
} catch {
|
|
15770
15849
|
uncertain = true;
|
|
15771
15850
|
continue;
|
|
@@ -15780,14 +15859,14 @@ var walk = (root, directory, output) => {
|
|
|
15780
15859
|
var scopeRoots = (root, scope) => {
|
|
15781
15860
|
const roots = [];
|
|
15782
15861
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
15783
|
-
const target =
|
|
15862
|
+
const target = path17.resolve(root, item);
|
|
15784
15863
|
if (!inside(root, target))
|
|
15785
15864
|
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` }] });
|
|
15786
15865
|
let ancestor = target;
|
|
15787
|
-
while (!
|
|
15788
|
-
ancestor =
|
|
15866
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
15867
|
+
ancestor = path17.dirname(ancestor);
|
|
15789
15868
|
try {
|
|
15790
|
-
if (!inside(root,
|
|
15869
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
15791
15870
|
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` }] });
|
|
15792
15871
|
} catch {
|
|
15793
15872
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -15799,7 +15878,7 @@ var scopeRoots = (root, scope) => {
|
|
|
15799
15878
|
function captureCandidate(root, scope, environment = []) {
|
|
15800
15879
|
let checkout;
|
|
15801
15880
|
try {
|
|
15802
|
-
checkout =
|
|
15881
|
+
checkout = fs14.realpathSync(root);
|
|
15803
15882
|
} catch {
|
|
15804
15883
|
return failure2("invalid_input", "candidate root does not exist");
|
|
15805
15884
|
}
|
|
@@ -15817,11 +15896,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15817
15896
|
if (item === ".git" || item === ".workit")
|
|
15818
15897
|
continue;
|
|
15819
15898
|
names.add(item);
|
|
15820
|
-
if (!
|
|
15899
|
+
if (!fs14.existsSync(target))
|
|
15821
15900
|
continue;
|
|
15822
15901
|
let stat;
|
|
15823
15902
|
try {
|
|
15824
|
-
stat =
|
|
15903
|
+
stat = fs14.lstatSync(target);
|
|
15825
15904
|
} catch {
|
|
15826
15905
|
uncertain = true;
|
|
15827
15906
|
continue;
|
|
@@ -15837,17 +15916,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15837
15916
|
for (const item of [...names].toSorted()) {
|
|
15838
15917
|
if (!scopeMatches(item, normalizedScope))
|
|
15839
15918
|
continue;
|
|
15840
|
-
const target =
|
|
15919
|
+
const target = path17.join(checkout, item);
|
|
15841
15920
|
try {
|
|
15842
|
-
const stat =
|
|
15921
|
+
const stat = fs14.lstatSync(target);
|
|
15843
15922
|
if (stat.isSymbolicLink()) {
|
|
15844
|
-
const link =
|
|
15923
|
+
const link = fs14.readlinkSync(target);
|
|
15845
15924
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
15846
15925
|
} else if (stat.isFile()) {
|
|
15847
15926
|
files.push({
|
|
15848
15927
|
path: item,
|
|
15849
15928
|
kind: "file",
|
|
15850
|
-
digest: digestBytes(
|
|
15929
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
15851
15930
|
executable: (stat.mode & 73) !== 0
|
|
15852
15931
|
});
|
|
15853
15932
|
} else if (!stat.isDirectory()) {
|
|
@@ -16012,7 +16091,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
|
|
|
16012
16091
|
var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
16013
16092
|
let root;
|
|
16014
16093
|
try {
|
|
16015
|
-
root =
|
|
16094
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
16016
16095
|
} catch {
|
|
16017
16096
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
16018
16097
|
}
|
|
@@ -16021,23 +16100,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
16021
16100
|
continue;
|
|
16022
16101
|
if (!reference.digest)
|
|
16023
16102
|
return failure2("invalid_input", "document references require a byte digest");
|
|
16024
|
-
const target =
|
|
16025
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
16103
|
+
const target = path17.resolve(root, reference.path);
|
|
16104
|
+
if (target !== root && !target.startsWith(`${root}${path17.sep}`))
|
|
16026
16105
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16027
16106
|
fields: [
|
|
16028
16107
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
16029
16108
|
]
|
|
16030
16109
|
});
|
|
16031
16110
|
try {
|
|
16032
|
-
const below =
|
|
16111
|
+
const below = path17.relative(root, target);
|
|
16033
16112
|
let current = root;
|
|
16034
|
-
for (const segment of below.split(
|
|
16113
|
+
for (const segment of below.split(path17.sep)) {
|
|
16035
16114
|
if (!segment)
|
|
16036
16115
|
continue;
|
|
16037
|
-
current =
|
|
16038
|
-
const stat =
|
|
16039
|
-
const real =
|
|
16040
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
16116
|
+
current = path17.join(current, segment);
|
|
16117
|
+
const stat = fs14.lstatSync(current);
|
|
16118
|
+
const real = fs14.realpathSync(current);
|
|
16119
|
+
if (real !== root && !real.startsWith(`${root}${path17.sep}`))
|
|
16041
16120
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16042
16121
|
fields: [
|
|
16043
16122
|
{
|
|
@@ -16053,7 +16132,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
16053
16132
|
if (current !== target && !stat.isDirectory())
|
|
16054
16133
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
16055
16134
|
}
|
|
16056
|
-
if (digestBytes(
|
|
16135
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
16057
16136
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
16058
16137
|
} catch {
|
|
16059
16138
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -16637,19 +16716,19 @@ var exportDigest = (bundle) => sha256({
|
|
|
16637
16716
|
// packages/workit-core/src/core/route-intent.ts
|
|
16638
16717
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
16639
16718
|
import { existsSync as existsSync6 } from "node:fs";
|
|
16640
|
-
import
|
|
16719
|
+
import path20 from "node:path";
|
|
16641
16720
|
|
|
16642
16721
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
16643
16722
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
16644
|
-
import { createHash as
|
|
16645
|
-
import
|
|
16723
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
16724
|
+
import fs16 from "node:fs";
|
|
16646
16725
|
import os4 from "node:os";
|
|
16647
|
-
import
|
|
16726
|
+
import path19 from "node:path";
|
|
16648
16727
|
|
|
16649
16728
|
// packages/workit-core/src/hooks/session-marker.ts
|
|
16650
|
-
import { createHash as
|
|
16651
|
-
import
|
|
16652
|
-
import
|
|
16729
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
16730
|
+
import fs15 from "node:fs";
|
|
16731
|
+
import path18 from "node:path";
|
|
16653
16732
|
var sessionMarkerFile = (input, session, store) => {
|
|
16654
16733
|
let dir = store;
|
|
16655
16734
|
if (dir === undefined) {
|
|
@@ -16658,13 +16737,13 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
16658
16737
|
return null;
|
|
16659
16738
|
dir = location.dir;
|
|
16660
16739
|
}
|
|
16661
|
-
const name =
|
|
16662
|
-
return
|
|
16740
|
+
const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
16741
|
+
return path18.join(dir, "hooks", `skills-${name}.json`);
|
|
16663
16742
|
};
|
|
16664
16743
|
var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
16665
16744
|
var readSessionMarker = (file) => {
|
|
16666
16745
|
try {
|
|
16667
|
-
const value = JSON.parse(
|
|
16746
|
+
const value = JSON.parse(fs15.readFileSync(file, "utf8"));
|
|
16668
16747
|
return { nudged: list2(value.nudged), loaded: list2(value.loaded), raw: list2(value.raw) };
|
|
16669
16748
|
} catch {
|
|
16670
16749
|
return { nudged: [], loaded: [], raw: [] };
|
|
@@ -16672,8 +16751,8 @@ var readSessionMarker = (file) => {
|
|
|
16672
16751
|
};
|
|
16673
16752
|
var writeSessionMarker = (file, marker) => {
|
|
16674
16753
|
try {
|
|
16675
|
-
|
|
16676
|
-
|
|
16754
|
+
fs15.mkdirSync(path18.dirname(file), { recursive: true });
|
|
16755
|
+
fs15.writeFileSync(file, JSON.stringify(marker));
|
|
16677
16756
|
} catch {}
|
|
16678
16757
|
};
|
|
16679
16758
|
|
|
@@ -17170,14 +17249,14 @@ var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
|
|
|
17170
17249
|
var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
|
|
17171
17250
|
var MAX_DEPTH = 4;
|
|
17172
17251
|
var MAX_EXPANSIONS = 16;
|
|
17173
|
-
var isAbsolute = (value) =>
|
|
17252
|
+
var isAbsolute = (value) => path19.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
17174
17253
|
var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
|
|
17175
17254
|
var joinDir = (base, raw) => {
|
|
17176
17255
|
const next = raw.replace(HERE, ".");
|
|
17177
17256
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
17178
17257
|
return;
|
|
17179
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
17180
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
17258
|
+
const expanded = next === "~" || next.startsWith("~/") ? path19.join(os4.homedir(), next.slice(1)) : next;
|
|
17259
|
+
return base === null || isAbsolute(expanded) ? expanded : path19.join(base, expanded);
|
|
17181
17260
|
};
|
|
17182
17261
|
var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
|
|
17183
17262
|
var cdTarget = (words) => {
|
|
@@ -17989,7 +18068,7 @@ var repoAt = (dir) => {
|
|
|
17989
18068
|
return { location, dir, branch: resolveTaskKey(dir, location).branch };
|
|
17990
18069
|
};
|
|
17991
18070
|
var isWorkitWorkspace = (repo) => {
|
|
17992
|
-
if (
|
|
18071
|
+
if (fs16.existsSync(repo.location.dir))
|
|
17993
18072
|
return true;
|
|
17994
18073
|
try {
|
|
17995
18074
|
return resolveRuntimeWorkspaceVcs(repo.location.top ?? repo.dir) !== null;
|
|
@@ -18010,17 +18089,17 @@ var headSha2 = (repo) => {
|
|
|
18010
18089
|
if (!git || git.reftable)
|
|
18011
18090
|
return null;
|
|
18012
18091
|
try {
|
|
18013
|
-
const head =
|
|
18092
|
+
const head = fs16.readFileSync(path19.join(git.gitDir, "HEAD"), "utf8").trim();
|
|
18014
18093
|
if (/^[0-9a-f]{40,64}$/.test(head))
|
|
18015
18094
|
return head;
|
|
18016
18095
|
const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
|
|
18017
18096
|
if (!ref)
|
|
18018
18097
|
return null;
|
|
18019
|
-
const common =
|
|
18098
|
+
const common = path19.dirname(repo.location.dir);
|
|
18020
18099
|
try {
|
|
18021
|
-
return
|
|
18100
|
+
return fs16.readFileSync(path19.join(common, ref), "utf8").trim() || null;
|
|
18022
18101
|
} catch {}
|
|
18023
|
-
const packed =
|
|
18102
|
+
const packed = fs16.readFileSync(path19.join(common, "packed-refs"), "utf8");
|
|
18024
18103
|
return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
|
|
18025
18104
|
} catch {
|
|
18026
18105
|
return null;
|
|
@@ -18108,8 +18187,8 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
|
18108
18187
|
const sub = invocation.args[0];
|
|
18109
18188
|
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
18110
18189
|
return [invocation];
|
|
18111
|
-
const dir =
|
|
18112
|
-
if (!
|
|
18190
|
+
const dir = path19.resolve(root, invocation.dir ?? ".");
|
|
18191
|
+
if (!fs16.existsSync(dir))
|
|
18113
18192
|
return [invocation];
|
|
18114
18193
|
const config = gitConfig(dir, invocation, cache);
|
|
18115
18194
|
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
@@ -18131,11 +18210,11 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
|
18131
18210
|
var normalizedUrl = (url, dir) => {
|
|
18132
18211
|
const trimmed = url.trim();
|
|
18133
18212
|
if (/^file:\/\//i.test(trimmed))
|
|
18134
|
-
return
|
|
18213
|
+
return path19.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18135
18214
|
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
18136
18215
|
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
18137
18216
|
if (!scheme && !scp)
|
|
18138
|
-
return
|
|
18217
|
+
return path19.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18139
18218
|
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
18140
18219
|
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18141
18220
|
};
|
|
@@ -18359,7 +18438,7 @@ var actionsIn = (cwd, command, dialect, cache = new Map) => {
|
|
|
18359
18438
|
const out = [];
|
|
18360
18439
|
const repos = new Map;
|
|
18361
18440
|
const repoFor = (relative) => {
|
|
18362
|
-
const dir =
|
|
18441
|
+
const dir = path19.resolve(cwd, relative ?? ".");
|
|
18363
18442
|
if (!repos.has(dir)) {
|
|
18364
18443
|
const repo = repoAt(dir);
|
|
18365
18444
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
@@ -18445,8 +18524,8 @@ var analysisDenial = (error) => ({
|
|
|
18445
18524
|
});
|
|
18446
18525
|
var NEXT_COMMAND = "next";
|
|
18447
18526
|
var MARKER_TTL_SECONDS = 3600;
|
|
18448
|
-
var markerFile = (repo, session, key) =>
|
|
18449
|
-
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${
|
|
18527
|
+
var markerFile = (repo, session, key) => path19.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
18528
|
+
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
|
|
18450
18529
|
function noteRawCommit(input, command, key) {
|
|
18451
18530
|
try {
|
|
18452
18531
|
if (!input.session.id || !/\bcommit\b/.test(command))
|
|
@@ -18456,8 +18535,8 @@ function noteRawCommit(input, command, key) {
|
|
|
18456
18535
|
if (action.kind !== "commit")
|
|
18457
18536
|
continue;
|
|
18458
18537
|
const file = markerFile(repo, input.session.id, key);
|
|
18459
|
-
|
|
18460
|
-
|
|
18538
|
+
fs16.mkdirSync(path19.dirname(file), { recursive: true });
|
|
18539
|
+
fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
|
|
18461
18540
|
`);
|
|
18462
18541
|
}
|
|
18463
18542
|
} catch {}
|
|
@@ -18480,11 +18559,11 @@ var headCommit = (dir) => {
|
|
|
18480
18559
|
var settle2 = (input, repo, file) => {
|
|
18481
18560
|
let marker;
|
|
18482
18561
|
try {
|
|
18483
|
-
marker = JSON.parse(
|
|
18562
|
+
marker = JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
18484
18563
|
} catch {
|
|
18485
18564
|
return;
|
|
18486
18565
|
}
|
|
18487
|
-
|
|
18566
|
+
fs16.rmSync(file, { force: true });
|
|
18488
18567
|
const session = input.session.id;
|
|
18489
18568
|
const now = Date.now() / 1000;
|
|
18490
18569
|
if (typeof marker.at !== "number" || now - marker.at > MARKER_TTL_SECONDS)
|
|
@@ -18533,7 +18612,7 @@ function settlePendingCommit(input) {
|
|
|
18533
18612
|
if (!repo)
|
|
18534
18613
|
return;
|
|
18535
18614
|
const file = markerFile(repo, input.session.id, NEXT_COMMAND);
|
|
18536
|
-
if (
|
|
18615
|
+
if (fs16.existsSync(file))
|
|
18537
18616
|
settle2(input, repo, file);
|
|
18538
18617
|
} catch {}
|
|
18539
18618
|
}
|
|
@@ -18687,7 +18766,7 @@ var judgedDir = (root, dir) => {
|
|
|
18687
18766
|
return null;
|
|
18688
18767
|
if (dir === null)
|
|
18689
18768
|
return root;
|
|
18690
|
-
const resolved =
|
|
18769
|
+
const resolved = path20.resolve(root, dir);
|
|
18691
18770
|
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
18692
18771
|
};
|
|
18693
18772
|
var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
@@ -18923,7 +19002,7 @@ var judgeInputSummary = (raw) => {
|
|
|
18923
19002
|
|
|
18924
19003
|
// packages/workit-core/src/autonomy.ts
|
|
18925
19004
|
import os5 from "node:os";
|
|
18926
|
-
import
|
|
19005
|
+
import path21 from "node:path";
|
|
18927
19006
|
var accountHome = () => {
|
|
18928
19007
|
try {
|
|
18929
19008
|
return os5.userInfo().homedir;
|
|
@@ -18932,10 +19011,10 @@ var accountHome = () => {
|
|
|
18932
19011
|
}
|
|
18933
19012
|
};
|
|
18934
19013
|
var grantsHome = { resolve: accountHome };
|
|
18935
|
-
var grantsDir = () =>
|
|
19014
|
+
var grantsDir = () => path21.join(grantsHome.resolve(), ".config", "workit");
|
|
18936
19015
|
var grantsOverride = () => {
|
|
18937
|
-
const configured =
|
|
18938
|
-
return configured ===
|
|
19016
|
+
const configured = path21.resolve(resolveConfigDir());
|
|
19017
|
+
return configured === path21.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 ${path21.join(grantsDir(), "workspaces.json")}, so the D4 defaults apply`;
|
|
18939
19018
|
};
|
|
18940
19019
|
var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
|
|
18941
19020
|
var DEFAULT_GRANTS = Object.freeze({
|
|
@@ -20738,7 +20817,7 @@ class WorkitCore {
|
|
|
20738
20817
|
// packages/workit-core/src/core/repo-context.ts
|
|
20739
20818
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
20740
20819
|
import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
20741
|
-
import
|
|
20820
|
+
import path22 from "node:path";
|
|
20742
20821
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
20743
20822
|
try {
|
|
20744
20823
|
gitRevisionParts(value);
|
|
@@ -20872,7 +20951,7 @@ var findPrTemplate = (cwd) => {
|
|
|
20872
20951
|
]) {
|
|
20873
20952
|
const parts = rel.split("/");
|
|
20874
20953
|
const base = parts[parts.length - 1];
|
|
20875
|
-
const dir = parts.length > 1 ?
|
|
20954
|
+
const dir = parts.length > 1 ? path22.join(cwd, ...parts.slice(0, -1)) : cwd;
|
|
20876
20955
|
const actual = probeCaseInsensitive(dir, base);
|
|
20877
20956
|
if (actual)
|
|
20878
20957
|
return [...parts.slice(0, -1), actual].join("/");
|
|
@@ -20903,7 +20982,7 @@ var diffStatForRange = (cwd, range) => {
|
|
|
20903
20982
|
return runGit(cwd, ["diff", "--stat", "--"]).stdout;
|
|
20904
20983
|
};
|
|
20905
20984
|
var packageScripts = (cwd, keys) => {
|
|
20906
|
-
const pkgPath =
|
|
20985
|
+
const pkgPath = path22.join(cwd, "package.json");
|
|
20907
20986
|
if (!existsSync7(pkgPath))
|
|
20908
20987
|
return [];
|
|
20909
20988
|
try {
|
|
@@ -20929,9 +21008,9 @@ var documentationFiles = (cwd) => {
|
|
|
20929
21008
|
if (entry.isDirectory()) {
|
|
20930
21009
|
if (excluded.has(entry.name))
|
|
20931
21010
|
continue;
|
|
20932
|
-
walk(
|
|
21011
|
+
walk(path22.join(dir, entry.name), depth + 1);
|
|
20933
21012
|
} else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
|
|
20934
|
-
matches.push("./" +
|
|
21013
|
+
matches.push("./" + path22.relative(cwd, path22.join(dir, entry.name)).replaceAll("\\", "/"));
|
|
20935
21014
|
}
|
|
20936
21015
|
}
|
|
20937
21016
|
};
|
|
@@ -20947,7 +21026,7 @@ var readTrimmed2 = (file, maxLines) => {
|
|
|
20947
21026
|
`);
|
|
20948
21027
|
};
|
|
20949
21028
|
function prReadyContext(root, range) {
|
|
20950
|
-
const cwd =
|
|
21029
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
20951
21030
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
20952
21031
|
return invalidRange(cwd);
|
|
20953
21032
|
let stdout = "";
|
|
@@ -21005,7 +21084,7 @@ ${status.stderr}` : "");
|
|
|
21005
21084
|
stdout += `template_path: ${template}
|
|
21006
21085
|
|
|
21007
21086
|
`;
|
|
21008
|
-
stdout += readTrimmed2(
|
|
21087
|
+
stdout += readTrimmed2(path22.join(cwd, template), 220);
|
|
21009
21088
|
} else {
|
|
21010
21089
|
stdout += `template_path: none
|
|
21011
21090
|
|
|
@@ -21015,7 +21094,7 @@ ${status.stderr}` : "");
|
|
|
21015
21094
|
stdout += `
|
|
21016
21095
|
`;
|
|
21017
21096
|
stdout += printSection("Recent Validation Signals");
|
|
21018
|
-
if (existsSync7(
|
|
21097
|
+
if (existsSync7(path22.join(cwd, "package.json"))) {
|
|
21019
21098
|
stdout += `package.json detected. Common scripts:
|
|
21020
21099
|
`;
|
|
21021
21100
|
const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
|
|
@@ -21024,7 +21103,7 @@ ${status.stderr}` : "");
|
|
|
21024
21103
|
`) + `
|
|
21025
21104
|
`;
|
|
21026
21105
|
}
|
|
21027
|
-
if (existsSync7(
|
|
21106
|
+
if (existsSync7(path22.join(cwd, "Cargo.toml")) || existsSync7(path22.join(cwd, "src-tauri/Cargo.toml"))) {
|
|
21028
21107
|
stdout += `Rust project detected.
|
|
21029
21108
|
`;
|
|
21030
21109
|
}
|
|
@@ -21057,7 +21136,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
|
|
|
21057
21136
|
- Apply with the host-native editor, preserving the repository changelog conventions.
|
|
21058
21137
|
- If Unreleased already has duplicate category headings, normalize_only first.`;
|
|
21059
21138
|
function changelogContext(root, range) {
|
|
21060
|
-
const cwd =
|
|
21139
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21061
21140
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
21062
21141
|
return invalidRange(cwd);
|
|
21063
21142
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -21075,7 +21154,7 @@ function changelogContext(root, range) {
|
|
|
21075
21154
|
stdout += CHANGELOG_RULES + `
|
|
21076
21155
|
`;
|
|
21077
21156
|
stdout += printSection("Existing CHANGELOG.md");
|
|
21078
|
-
const changelogPath =
|
|
21157
|
+
const changelogPath = path22.join(cwd, "CHANGELOG.md");
|
|
21079
21158
|
if (existsSync7(changelogPath)) {
|
|
21080
21159
|
stdout += readTrimmed2(changelogPath, 260) + `
|
|
21081
21160
|
`;
|
|
@@ -21095,7 +21174,7 @@ function changelogContext(root, range) {
|
|
|
21095
21174
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
21096
21175
|
}
|
|
21097
21176
|
function docsRefreshContext(root, range) {
|
|
21098
|
-
const cwd =
|
|
21177
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21099
21178
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
21100
21179
|
return invalidRange(cwd);
|
|
21101
21180
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -21117,7 +21196,7 @@ function docsRefreshContext(root, range) {
|
|
|
21117
21196
|
`) + `
|
|
21118
21197
|
`;
|
|
21119
21198
|
stdout += printSection("README Preview");
|
|
21120
|
-
const readme =
|
|
21199
|
+
const readme = path22.join(cwd, "README.md");
|
|
21121
21200
|
if (existsSync7(readme)) {
|
|
21122
21201
|
stdout += readTrimmed2(readme, 220) + `
|
|
21123
21202
|
`;
|
|
@@ -21126,7 +21205,7 @@ function docsRefreshContext(root, range) {
|
|
|
21126
21205
|
`;
|
|
21127
21206
|
}
|
|
21128
21207
|
stdout += printSection("Package Scripts");
|
|
21129
|
-
const pkgPath =
|
|
21208
|
+
const pkgPath = path22.join(cwd, "package.json");
|
|
21130
21209
|
if (existsSync7(pkgPath)) {
|
|
21131
21210
|
try {
|
|
21132
21211
|
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
@@ -21140,7 +21219,7 @@ function docsRefreshContext(root, range) {
|
|
|
21140
21219
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
21141
21220
|
}
|
|
21142
21221
|
function releaseNotesContext(root, rangeOrTag) {
|
|
21143
|
-
const cwd =
|
|
21222
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21144
21223
|
if (!rangeOrTag) {
|
|
21145
21224
|
return { stdout: "", stderr: `ERROR: release tag or range required
|
|
21146
21225
|
`, exitCode: 1, cwd };
|
|
@@ -21178,7 +21257,7 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
21178
21257
|
`;
|
|
21179
21258
|
stdout += printSection("Existing Release Files");
|
|
21180
21259
|
for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
|
|
21181
|
-
if (existsSync7(
|
|
21260
|
+
if (existsSync7(path22.join(cwd, rel)))
|
|
21182
21261
|
stdout += rel + `
|
|
21183
21262
|
`;
|
|
21184
21263
|
}
|
|
@@ -21209,8 +21288,8 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
21209
21288
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
21210
21289
|
|
|
21211
21290
|
// packages/workit-core/src/core/pr-create.ts
|
|
21212
|
-
import
|
|
21213
|
-
import
|
|
21291
|
+
import fs17 from "node:fs";
|
|
21292
|
+
import path23 from "node:path";
|
|
21214
21293
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
21215
21294
|
// packages/workit-core/src/forge/pr-body.ts
|
|
21216
21295
|
function parseGhIssue(value) {
|
|
@@ -21221,13 +21300,13 @@ function parseGhIssue(value) {
|
|
|
21221
21300
|
// packages/workit-core/src/core/pr-create.ts
|
|
21222
21301
|
function whichOnPath(tool) {
|
|
21223
21302
|
const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
|
|
21224
|
-
for (const dir of (process.env.PATH ?? "").split(
|
|
21303
|
+
for (const dir of (process.env.PATH ?? "").split(path23.delimiter)) {
|
|
21225
21304
|
if (!dir)
|
|
21226
21305
|
continue;
|
|
21227
21306
|
for (const name of names) {
|
|
21228
|
-
const candidate =
|
|
21307
|
+
const candidate = path23.join(dir, name);
|
|
21229
21308
|
try {
|
|
21230
|
-
|
|
21309
|
+
fs17.accessSync(candidate, fs17.constants.X_OK);
|
|
21231
21310
|
return candidate;
|
|
21232
21311
|
} catch {}
|
|
21233
21312
|
}
|
|
@@ -21345,8 +21424,8 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
|
|
|
21345
21424
|
};
|
|
21346
21425
|
|
|
21347
21426
|
// packages/workit-core/src/core/youtrack.ts
|
|
21348
|
-
import
|
|
21349
|
-
import
|
|
21427
|
+
import fs18 from "node:fs";
|
|
21428
|
+
import path24 from "node:path";
|
|
21350
21429
|
|
|
21351
21430
|
// packages/workit-core/src/core/templates.ts
|
|
21352
21431
|
var repoRoot2 = assetRoot();
|
|
@@ -21359,22 +21438,22 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
|
|
|
21359
21438
|
// packages/workit-core/src/core/youtrack.ts
|
|
21360
21439
|
var ISSUE_RE = /^[A-Z]+-\d+$/;
|
|
21361
21440
|
var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
|
|
21362
|
-
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
21363
|
-
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
21441
|
+
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(configDir(), "youtrack.json");
|
|
21442
|
+
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(resolveConfigDir(), "youtrack.json");
|
|
21364
21443
|
var youTrackTokenModeOk = (p) => {
|
|
21365
21444
|
if (process.platform === "win32")
|
|
21366
21445
|
return true;
|
|
21367
|
-
const mode =
|
|
21446
|
+
const mode = fs18.statSync(p).mode & 511;
|
|
21368
21447
|
return mode === 384;
|
|
21369
21448
|
};
|
|
21370
21449
|
function readYouTrackConfig(required) {
|
|
21371
21450
|
const cfgPath = youTrackConfigPath();
|
|
21372
|
-
if (!
|
|
21451
|
+
if (!fs18.existsSync(cfgPath)) {
|
|
21373
21452
|
return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
|
|
21374
21453
|
}
|
|
21375
21454
|
let parsed;
|
|
21376
21455
|
try {
|
|
21377
|
-
parsed = JSON.parse(
|
|
21456
|
+
parsed = JSON.parse(fs18.readFileSync(cfgPath, "utf8"));
|
|
21378
21457
|
} catch {
|
|
21379
21458
|
return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
|
|
21380
21459
|
}
|
|
@@ -21385,11 +21464,11 @@ function readYouTrackConfig(required) {
|
|
|
21385
21464
|
}
|
|
21386
21465
|
var readYouTrackContextConfig = () => {
|
|
21387
21466
|
const cfgPath = youTrackReadOnlyConfigPath();
|
|
21388
|
-
if (!
|
|
21467
|
+
if (!fs18.existsSync(cfgPath))
|
|
21389
21468
|
return { data: {} };
|
|
21390
21469
|
let parsed;
|
|
21391
21470
|
try {
|
|
21392
|
-
parsed = JSON.parse(
|
|
21471
|
+
parsed = JSON.parse(fs18.readFileSync(cfgPath, "utf8"));
|
|
21393
21472
|
} catch {
|
|
21394
21473
|
return { error: "YouTrack configuration is unavailable" };
|
|
21395
21474
|
}
|
|
@@ -21428,12 +21507,12 @@ var youTrackToken = () => {
|
|
|
21428
21507
|
if ("error" in loaded)
|
|
21429
21508
|
return loaded;
|
|
21430
21509
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
21431
|
-
const tokenPath = tokenFile ?
|
|
21432
|
-
if (!tokenPath || !
|
|
21510
|
+
const tokenPath = tokenFile ? path24.isAbsolute(tokenFile) ? path24.resolve(tokenFile) : path24.resolve(process.cwd(), tokenFile) : "";
|
|
21511
|
+
if (!tokenPath || !fs18.existsSync(tokenPath))
|
|
21433
21512
|
return { error: "missing youtrack.token" };
|
|
21434
21513
|
if (!youTrackTokenModeOk(tokenPath))
|
|
21435
21514
|
return { error: "youtrack.token mode must be 0600" };
|
|
21436
|
-
const token =
|
|
21515
|
+
const token = fs18.readFileSync(tokenPath, "utf8").trim();
|
|
21437
21516
|
if (!token)
|
|
21438
21517
|
return { error: "empty token file" };
|
|
21439
21518
|
if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
|
|
@@ -21498,9 +21577,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
|
|
|
21498
21577
|
} catch {
|
|
21499
21578
|
continue;
|
|
21500
21579
|
}
|
|
21501
|
-
if (!
|
|
21580
|
+
if (!fs18.existsSync(full))
|
|
21502
21581
|
continue;
|
|
21503
|
-
const text =
|
|
21582
|
+
const text = fs18.readFileSync(full, "utf8");
|
|
21504
21583
|
const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
|
|
21505
21584
|
if (m)
|
|
21506
21585
|
return m[1];
|
|
@@ -21785,15 +21864,15 @@ function resolveGitRevision(root, value) {
|
|
|
21785
21864
|
}
|
|
21786
21865
|
function resolveInside(root, candidate) {
|
|
21787
21866
|
const base = realpathSync5(root);
|
|
21788
|
-
const target =
|
|
21789
|
-
if (target !== base && !target.startsWith(base +
|
|
21867
|
+
const target = path25.resolve(base, candidate);
|
|
21868
|
+
if (target !== base && !target.startsWith(base + path25.sep)) {
|
|
21790
21869
|
throw new Error("path must stay inside repository root");
|
|
21791
21870
|
}
|
|
21792
21871
|
let ancestor = target;
|
|
21793
21872
|
while (!existsSync8(ancestor))
|
|
21794
|
-
ancestor =
|
|
21873
|
+
ancestor = path25.dirname(ancestor);
|
|
21795
21874
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
21796
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
21875
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path25.sep)) {
|
|
21797
21876
|
throw new Error("path must stay inside repository root");
|
|
21798
21877
|
}
|
|
21799
21878
|
return target;
|
|
@@ -21837,9 +21916,9 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
|
|
|
21837
21916
|
};
|
|
21838
21917
|
});
|
|
21839
21918
|
// packages/workit-core/src/hooks/context.ts
|
|
21840
|
-
import { createHash as
|
|
21841
|
-
import
|
|
21842
|
-
import
|
|
21919
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
21920
|
+
import fs19 from "node:fs";
|
|
21921
|
+
import path26 from "node:path";
|
|
21843
21922
|
var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
|
|
21844
21923
|
var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
|
|
21845
21924
|
var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
|
|
@@ -21924,7 +22003,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
21924
22003
|
return null;
|
|
21925
22004
|
const freshness = { mode: "signal", current: () => recentSignal(store.root) };
|
|
21926
22005
|
const observed = task?.data.evidence.some(isObservedCheck) ?? false;
|
|
21927
|
-
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [
|
|
22006
|
+
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path26.resolve(store.root, ref.path)] : []));
|
|
21928
22007
|
const observedFiles = filesKey(files);
|
|
21929
22008
|
const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
|
|
21930
22009
|
if (!compact.ok || !compact.data)
|
|
@@ -21993,7 +22072,7 @@ var turnContextText = (input, descriptor) => {
|
|
|
21993
22072
|
}
|
|
21994
22073
|
};
|
|
21995
22074
|
var TURN_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
21996
|
-
var digestOf = (text) =>
|
|
22075
|
+
var digestOf = (text) => createHash15("sha256").update(text).digest("hex");
|
|
21997
22076
|
var turnMarker = (input) => {
|
|
21998
22077
|
if (!input.session.id)
|
|
21999
22078
|
return null;
|
|
@@ -22002,32 +22081,32 @@ var turnMarker = (input) => {
|
|
|
22002
22081
|
if (location instanceof Error)
|
|
22003
22082
|
return null;
|
|
22004
22083
|
const session = [input.host, input.session.id, input.session.agentId ?? ""].join("\x00");
|
|
22005
|
-
return
|
|
22084
|
+
return path26.join(location.dir, "hooks", `turn-${digestOf(session).slice(0, 32)}.json`);
|
|
22006
22085
|
} catch {
|
|
22007
22086
|
return null;
|
|
22008
22087
|
}
|
|
22009
22088
|
};
|
|
22010
22089
|
var writeTurnDigest = (file, digest) => {
|
|
22011
22090
|
try {
|
|
22012
|
-
|
|
22013
|
-
|
|
22091
|
+
fs19.mkdirSync(path26.dirname(file), { recursive: true });
|
|
22092
|
+
fs19.writeFileSync(file, `${JSON.stringify({ digest })}
|
|
22014
22093
|
`);
|
|
22015
22094
|
} catch {}
|
|
22016
22095
|
};
|
|
22017
22096
|
var clearTurnDigest = (file) => {
|
|
22018
22097
|
try {
|
|
22019
|
-
|
|
22098
|
+
fs19.rmSync(file, { force: true });
|
|
22020
22099
|
} catch {}
|
|
22021
22100
|
};
|
|
22022
22101
|
var pruneTurnDigests = (dir, now) => {
|
|
22023
22102
|
try {
|
|
22024
|
-
for (const name of
|
|
22103
|
+
for (const name of fs19.readdirSync(dir)) {
|
|
22025
22104
|
if (!name.startsWith("turn-"))
|
|
22026
22105
|
continue;
|
|
22027
|
-
const file =
|
|
22106
|
+
const file = path26.join(dir, name);
|
|
22028
22107
|
try {
|
|
22029
|
-
if (now -
|
|
22030
|
-
|
|
22108
|
+
if (now - fs19.statSync(file).mtimeMs > TURN_TTL_MS)
|
|
22109
|
+
fs19.rmSync(file, { force: true });
|
|
22031
22110
|
} catch {}
|
|
22032
22111
|
}
|
|
22033
22112
|
} catch {}
|
|
@@ -22043,7 +22122,7 @@ var changedTurnContext = (input, text) => {
|
|
|
22043
22122
|
return text;
|
|
22044
22123
|
const digest = digestOf(text);
|
|
22045
22124
|
try {
|
|
22046
|
-
const previous = JSON.parse(
|
|
22125
|
+
const previous = JSON.parse(fs19.readFileSync(file, "utf8"));
|
|
22047
22126
|
if (previous.digest === digest)
|
|
22048
22127
|
return null;
|
|
22049
22128
|
} catch {}
|
|
@@ -22054,7 +22133,7 @@ var seedTurnContext = (input, descriptor, text = turnContextText(input, descript
|
|
|
22054
22133
|
const file = turnMarker(input);
|
|
22055
22134
|
if (!file)
|
|
22056
22135
|
return;
|
|
22057
|
-
pruneTurnDigests(
|
|
22136
|
+
pruneTurnDigests(path26.dirname(file), Date.now());
|
|
22058
22137
|
if (text)
|
|
22059
22138
|
writeTurnDigest(file, digestOf(text));
|
|
22060
22139
|
else
|
|
@@ -22073,13 +22152,13 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
|
22073
22152
|
return policy && !policy.ok ? { kind: "deny", reason: `branch_policy_denied: ${policy.error}`, unblock: null } : { kind: "none" };
|
|
22074
22153
|
};
|
|
22075
22154
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
22076
|
-
import
|
|
22155
|
+
import fs20 from "node:fs";
|
|
22077
22156
|
import os6 from "node:os";
|
|
22078
|
-
import
|
|
22157
|
+
import path27 from "node:path";
|
|
22079
22158
|
var EMPTY = () => ({ deny: [], allow: [] });
|
|
22080
22159
|
var readText2 = (file) => {
|
|
22081
22160
|
try {
|
|
22082
|
-
return
|
|
22161
|
+
return fs20.readFileSync(file, "utf8");
|
|
22083
22162
|
} catch (error) {
|
|
22084
22163
|
if (error.code === "ENOENT")
|
|
22085
22164
|
return null;
|
|
@@ -22116,19 +22195,19 @@ function parseJsonc(text) {
|
|
|
22116
22195
|
return JSON.parse(out.replace(/,(\s*[}\]])/gu, "$1"));
|
|
22117
22196
|
}
|
|
22118
22197
|
function gitTop(cwd) {
|
|
22119
|
-
for (let dir =
|
|
22120
|
-
if (
|
|
22198
|
+
for (let dir = path27.resolve(cwd);; dir = path27.dirname(dir)) {
|
|
22199
|
+
if (fs20.existsSync(path27.join(dir, ".git")))
|
|
22121
22200
|
return dir;
|
|
22122
|
-
if (
|
|
22201
|
+
if (path27.dirname(dir) === dir)
|
|
22123
22202
|
return null;
|
|
22124
22203
|
}
|
|
22125
22204
|
}
|
|
22126
22205
|
var projectDirs = (cwd) => {
|
|
22127
22206
|
const top = gitTop(cwd);
|
|
22128
22207
|
const dirs = [];
|
|
22129
|
-
for (let dir =
|
|
22208
|
+
for (let dir = path27.resolve(cwd);; dir = path27.dirname(dir)) {
|
|
22130
22209
|
dirs.push(dir);
|
|
22131
|
-
if (!top || dir === top ||
|
|
22210
|
+
if (!top || dir === top || path27.dirname(dir) === dir)
|
|
22132
22211
|
return dirs;
|
|
22133
22212
|
}
|
|
22134
22213
|
};
|
|
@@ -22140,12 +22219,12 @@ var CLAUDE_MANAGED = {
|
|
|
22140
22219
|
};
|
|
22141
22220
|
function claudeSettingsFiles(cwd, env, platform = process.platform) {
|
|
22142
22221
|
const project = env.CLAUDE_PROJECT_DIR || gitTop(cwd) || cwd;
|
|
22143
|
-
const user = env.CLAUDE_CONFIG_DIR ||
|
|
22222
|
+
const user = env.CLAUDE_CONFIG_DIR || path27.join(homeOf(env), ".claude");
|
|
22144
22223
|
return [
|
|
22145
22224
|
...CLAUDE_MANAGED[platform] ? [CLAUDE_MANAGED[platform]] : [],
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22225
|
+
path27.join(user, "settings.json"),
|
|
22226
|
+
path27.join(project, ".claude", "settings.json"),
|
|
22227
|
+
path27.join(project, ".claude", "settings.local.json")
|
|
22149
22228
|
];
|
|
22150
22229
|
}
|
|
22151
22230
|
var bashPattern = (entry) => {
|
|
@@ -22235,10 +22314,10 @@ var opencodeConfig = (value, rules) => {
|
|
|
22235
22314
|
function opencodeRules(cwd, env = process.env) {
|
|
22236
22315
|
const rules = EMPTY();
|
|
22237
22316
|
try {
|
|
22238
|
-
const config = env.XDG_CONFIG_HOME ||
|
|
22317
|
+
const config = env.XDG_CONFIG_HOME || path27.join(homeOf(env), ".config");
|
|
22239
22318
|
const files = [
|
|
22240
|
-
...OPENCODE_NAMES.map((name) =>
|
|
22241
|
-
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [
|
|
22319
|
+
...OPENCODE_NAMES.map((name) => path27.join(config, "opencode", name)),
|
|
22320
|
+
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path27.join(dir, name), path27.join(dir, ".opencode", name)])),
|
|
22242
22321
|
...env.OPENCODE_CONFIG ? [env.OPENCODE_CONFIG] : []
|
|
22243
22322
|
];
|
|
22244
22323
|
for (const file of files) {
|
|
@@ -22282,19 +22361,19 @@ var codexRule = (body) => {
|
|
|
22282
22361
|
function codexRules(cwd, env = process.env) {
|
|
22283
22362
|
const rules = EMPTY();
|
|
22284
22363
|
try {
|
|
22285
|
-
const home = env.CODEX_HOME ||
|
|
22364
|
+
const home = env.CODEX_HOME || path27.join(homeOf(env), ".codex");
|
|
22286
22365
|
const top = gitTop(cwd) ?? cwd;
|
|
22287
|
-
for (const dir of [
|
|
22366
|
+
for (const dir of [path27.join(home, "rules"), path27.join(top, ".codex", "rules")]) {
|
|
22288
22367
|
let files;
|
|
22289
22368
|
try {
|
|
22290
|
-
files =
|
|
22369
|
+
files = fs20.readdirSync(dir).filter((name) => name.endsWith(".rules"));
|
|
22291
22370
|
} catch (error) {
|
|
22292
22371
|
if (error.code === "ENOENT")
|
|
22293
22372
|
continue;
|
|
22294
22373
|
return "unreadable";
|
|
22295
22374
|
}
|
|
22296
22375
|
for (const name of files) {
|
|
22297
|
-
const text = readText2(
|
|
22376
|
+
const text = readText2(path27.join(dir, name)) ?? "";
|
|
22298
22377
|
for (const part of text.split(/\bprefix_rule\s*\(/u).slice(1)) {
|
|
22299
22378
|
const rule = codexRule(part);
|
|
22300
22379
|
if (!rule)
|
|
@@ -22313,8 +22392,8 @@ function cursorRules(cwd, env = process.env) {
|
|
|
22313
22392
|
try {
|
|
22314
22393
|
const top = gitTop(cwd) ?? cwd;
|
|
22315
22394
|
for (const file of [
|
|
22316
|
-
|
|
22317
|
-
|
|
22395
|
+
path27.join(homeOf(env), ".cursor", "cli-config.json"),
|
|
22396
|
+
path27.join(top, ".cursor", "cli.json")
|
|
22318
22397
|
]) {
|
|
22319
22398
|
const text = readText2(file);
|
|
22320
22399
|
if (text === null)
|
|
@@ -22388,23 +22467,23 @@ function wrapAllowed(read, words, command, options = {}) {
|
|
|
22388
22467
|
}
|
|
22389
22468
|
|
|
22390
22469
|
// packages/workit-core/src/core/heavy.ts
|
|
22391
|
-
import
|
|
22470
|
+
import fs21 from "node:fs";
|
|
22392
22471
|
import os7 from "node:os";
|
|
22393
|
-
import
|
|
22472
|
+
import path28 from "node:path";
|
|
22394
22473
|
function stateDir(env, platform = process.platform) {
|
|
22395
22474
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
22396
22475
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
22397
22476
|
if (env.XDG_STATE_HOME)
|
|
22398
|
-
return
|
|
22477
|
+
return path28.join(env.XDG_STATE_HOME, "workit");
|
|
22399
22478
|
const home = env.HOME || os7.homedir();
|
|
22400
22479
|
if (platform === "darwin")
|
|
22401
|
-
return
|
|
22480
|
+
return path28.join(home, "Library", "Application Support", "workit");
|
|
22402
22481
|
if (platform === "win32")
|
|
22403
|
-
return
|
|
22404
|
-
return
|
|
22482
|
+
return path28.join(env.LOCALAPPDATA ?? path28.join(home, "AppData", "Local"), "workit");
|
|
22483
|
+
return path28.join(home, ".local", "state", "workit");
|
|
22405
22484
|
}
|
|
22406
22485
|
var HEAVY_COMMANDS_FILE = "heavy-commands.json";
|
|
22407
|
-
var heavyCommandsFile = (env) =>
|
|
22486
|
+
var heavyCommandsFile = (env) => path28.join(stateDir(env), HEAVY_COMMANDS_FILE);
|
|
22408
22487
|
var HEAVY_SCRIPT = /^(?:test|tests|t|tst|unit|integration|e2e|coverage|cov|lint|eslint|typecheck|type-check|types|tsc|check|verify|validate|build|compile|bundle|ci|sonar|cypress|playwright|jest|vitest|mocha|bench|benchmark|all)(?:$|[:_.-])/iu;
|
|
22409
22488
|
var INFO_FLAGS = new Set(["--version", "-v", "-V", "--help", "-h", "help", "version"]);
|
|
22410
22489
|
var WATCH_FLAG = /^(?:--watch(?:All)?(?:=.*)?|-w|--serve)$/u;
|
|
@@ -22667,7 +22746,7 @@ function parsePattern(pattern) {
|
|
|
22667
22746
|
var 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]));
|
|
22668
22747
|
var readJson = (file) => {
|
|
22669
22748
|
try {
|
|
22670
|
-
return JSON.parse(
|
|
22749
|
+
return JSON.parse(fs21.readFileSync(file, "utf8"));
|
|
22671
22750
|
} catch {
|
|
22672
22751
|
return;
|
|
22673
22752
|
}
|
|
@@ -22679,7 +22758,7 @@ function machinePatterns(env) {
|
|
|
22679
22758
|
return isRecord5(value) ? stringList(value.patterns) : [];
|
|
22680
22759
|
}
|
|
22681
22760
|
function repoPatterns(cwd) {
|
|
22682
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
22761
|
+
return repoHeavyCommands(gitTop(cwd) ?? path28.resolve(cwd));
|
|
22683
22762
|
}
|
|
22684
22763
|
function heavyLines(lines, options) {
|
|
22685
22764
|
const found = [];
|
|
@@ -22757,12 +22836,12 @@ function heavyPlan(command, options) {
|
|
|
22757
22836
|
}
|
|
22758
22837
|
function workitOnPath2(env = process.env) {
|
|
22759
22838
|
const names = process.platform === "win32" ? ["workit.exe", "workit.cmd", "workit"] : ["workit"];
|
|
22760
|
-
for (const dir of (env.PATH ?? "").split(
|
|
22839
|
+
for (const dir of (env.PATH ?? "").split(path28.delimiter))
|
|
22761
22840
|
for (const name of names) {
|
|
22762
22841
|
if (!dir)
|
|
22763
22842
|
continue;
|
|
22764
22843
|
try {
|
|
22765
|
-
|
|
22844
|
+
fs21.accessSync(path28.join(dir, name), fs21.constants.X_OK);
|
|
22766
22845
|
return true;
|
|
22767
22846
|
} catch {}
|
|
22768
22847
|
}
|
|
@@ -22779,41 +22858,41 @@ function leaseRewrite(command) {
|
|
|
22779
22858
|
}
|
|
22780
22859
|
|
|
22781
22860
|
// packages/workit-core/src/core/heavy-words.ts
|
|
22782
|
-
import
|
|
22861
|
+
import fs22 from "node:fs";
|
|
22783
22862
|
import os8 from "node:os";
|
|
22784
|
-
import
|
|
22863
|
+
import path29 from "node:path";
|
|
22785
22864
|
var HEAVY_WORDS = new Set(("npm npx pnpm pnpx yarn bun bunx deno corepack make gmake docker podman nerdctl " + "python python3 py uv poetry pdm pipenv hatch rye bundle rake nx " + "jest vitest mocha ava tap karma jasmine nyc c8 tsc vue-tsc svelte-check eslint stylelint " + "tslint webpack webpack-cli rollup parcel tsup vite next nuxt nuxi astro ng react-scripts " + "playwright cypress wdio testcafe turbo lerna sonar-scanner sonarless sonarless-mcp go " + "golangci-lint gotestsum staticcheck cargo mvn mvnw gradle gradlew ant sbt bazel bazelisk " + "buck2 dotnet msbuild pytest py.test tox nox mypy pyright pylint coverage maturin pip pip3 " + "rspec rails phpunit pest phpstan psalm composer mix swift xcodebuild flutter dart pod cmake " + "ninja meson ctest scons docker-compose buildah earthly").split(" "));
|
|
22786
22865
|
var wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((word) => (word.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat)$/u, "")).filter(Boolean);
|
|
22787
22866
|
var stateDir2 = (env) => {
|
|
22788
22867
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
22789
22868
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
22790
22869
|
if (env.XDG_STATE_HOME)
|
|
22791
|
-
return
|
|
22870
|
+
return path29.join(env.XDG_STATE_HOME, "workit");
|
|
22792
22871
|
const home = env.HOME || os8.homedir();
|
|
22793
22872
|
if (process.platform === "darwin")
|
|
22794
|
-
return
|
|
22873
|
+
return path29.join(home, "Library", "Application Support", "workit");
|
|
22795
22874
|
if (process.platform === "win32")
|
|
22796
|
-
return
|
|
22797
|
-
return
|
|
22875
|
+
return path29.join(env.LOCALAPPDATA ?? path29.join(home, "AppData", "Local"), "workit");
|
|
22876
|
+
return path29.join(home, ".local", "state", "workit");
|
|
22798
22877
|
};
|
|
22799
22878
|
var readJson2 = (file) => {
|
|
22800
22879
|
try {
|
|
22801
|
-
return JSON.parse(
|
|
22880
|
+
return JSON.parse(fs22.readFileSync(file, "utf8"));
|
|
22802
22881
|
} catch {
|
|
22803
22882
|
return;
|
|
22804
22883
|
}
|
|
22805
22884
|
};
|
|
22806
22885
|
var patternWords = (cwd, env) => {
|
|
22807
22886
|
const patterns = [];
|
|
22808
|
-
const machine = readJson2(
|
|
22887
|
+
const machine = readJson2(path29.join(stateDir2(env), "heavy-commands.json"));
|
|
22809
22888
|
if (Array.isArray(machine?.patterns))
|
|
22810
22889
|
patterns.push(...machine.patterns);
|
|
22811
|
-
for (let dir =
|
|
22812
|
-
if (
|
|
22890
|
+
for (let dir = path29.resolve(cwd);; dir = path29.dirname(dir)) {
|
|
22891
|
+
if (fs22.existsSync(path29.join(dir, ".git"))) {
|
|
22813
22892
|
patterns.push(...repoHeavyCommands(dir));
|
|
22814
22893
|
break;
|
|
22815
22894
|
}
|
|
22816
|
-
if (
|
|
22895
|
+
if (path29.dirname(dir) === dir)
|
|
22817
22896
|
break;
|
|
22818
22897
|
}
|
|
22819
22898
|
const words = new Set;
|
|
@@ -22885,14 +22964,14 @@ var splitDenial = (plan) => ({
|
|
|
22885
22964
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
22886
22965
|
import { realpathSync as realpathSync6 } from "node:fs";
|
|
22887
22966
|
import os10 from "node:os";
|
|
22888
|
-
import
|
|
22967
|
+
import path31 from "node:path";
|
|
22889
22968
|
|
|
22890
22969
|
// packages/workit-core/src/core/live-session.ts
|
|
22891
22970
|
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
22892
|
-
import { createHash as
|
|
22893
|
-
import
|
|
22971
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
22972
|
+
import fs23 from "node:fs";
|
|
22894
22973
|
import os9 from "node:os";
|
|
22895
|
-
import
|
|
22974
|
+
import path30 from "node:path";
|
|
22896
22975
|
var LIVE_SESSION_TTL_MS = 15 * 60000;
|
|
22897
22976
|
var HEARTBEAT_EVERY_MS = 30000;
|
|
22898
22977
|
var liveProbe = {
|
|
@@ -22913,9 +22992,9 @@ var processAlive = (pid) => {
|
|
|
22913
22992
|
var processInfo = (pid) => {
|
|
22914
22993
|
try {
|
|
22915
22994
|
if (liveProbe.platform === "linux") {
|
|
22916
|
-
const stat =
|
|
22995
|
+
const stat = fs23.readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
22917
22996
|
const ppid = Number(stat.slice(stat.lastIndexOf(")") + 2).split(" ")[1]);
|
|
22918
|
-
const command =
|
|
22997
|
+
const command = fs23.readFileSync(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ");
|
|
22919
22998
|
return Number.isInteger(ppid) ? { ppid, command: command.trim() } : null;
|
|
22920
22999
|
}
|
|
22921
23000
|
if (liveProbe.platform === "win32")
|
|
@@ -22966,35 +23045,35 @@ var liveOwner = (input, transport, env = process.env) => {
|
|
|
22966
23045
|
};
|
|
22967
23046
|
};
|
|
22968
23047
|
var checkoutOf = (target) => {
|
|
22969
|
-
let dir =
|
|
22970
|
-
while (!
|
|
22971
|
-
dir =
|
|
22972
|
-
if (
|
|
22973
|
-
dir =
|
|
22974
|
-
const parts = dir.split(
|
|
23048
|
+
let dir = path30.resolve(target);
|
|
23049
|
+
while (!fs23.existsSync(dir) && path30.dirname(dir) !== dir)
|
|
23050
|
+
dir = path30.dirname(dir);
|
|
23051
|
+
if (fs23.existsSync(dir) && !fs23.statSync(dir).isDirectory())
|
|
23052
|
+
dir = path30.dirname(dir);
|
|
23053
|
+
const parts = dir.split(path30.sep);
|
|
22975
23054
|
const dotGit = parts.lastIndexOf(".git");
|
|
22976
23055
|
if (dotGit > 0)
|
|
22977
|
-
dir = parts.slice(0, dotGit).join(
|
|
23056
|
+
dir = parts.slice(0, dotGit).join(path30.sep) || path30.sep;
|
|
22978
23057
|
const location = resolveStore(dir);
|
|
22979
23058
|
if (location instanceof Error || !location.shared || !location.top)
|
|
22980
23059
|
return null;
|
|
22981
23060
|
let top = location.top;
|
|
22982
23061
|
try {
|
|
22983
|
-
top =
|
|
23062
|
+
top = fs23.realpathSync.native(top);
|
|
22984
23063
|
} catch {}
|
|
22985
23064
|
return top;
|
|
22986
23065
|
};
|
|
22987
|
-
var markerFile2 = (top) =>
|
|
23066
|
+
var markerFile2 = (top) => path30.join(resolveStateDir(), "live-sessions", `${createHash16("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`);
|
|
22988
23067
|
var checkoutKey = (top, platform = process.platform) => {
|
|
22989
|
-
let key =
|
|
23068
|
+
let key = path30.resolve(top);
|
|
22990
23069
|
try {
|
|
22991
|
-
key =
|
|
23070
|
+
key = fs23.realpathSync.native(key);
|
|
22992
23071
|
} catch {}
|
|
22993
23072
|
return platform === "win32" ? key.replaceAll("/", "\\").toLowerCase() : key;
|
|
22994
23073
|
};
|
|
22995
23074
|
var readMarker = (file) => {
|
|
22996
23075
|
try {
|
|
22997
|
-
const value = JSON.parse(
|
|
23076
|
+
const value = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
22998
23077
|
if (value?.version !== 1 || typeof value.session !== "string" || typeof value.host !== "string" || typeof value.heartbeatAt !== "string" || Number.isNaN(Date.parse(value.heartbeatAt)))
|
|
22999
23078
|
return null;
|
|
23000
23079
|
return {
|
|
@@ -23081,10 +23160,10 @@ var claimLiveSession = (target, owner, deps = {}) => {
|
|
|
23081
23160
|
checkout,
|
|
23082
23161
|
heartbeatAt: now.toISOString()
|
|
23083
23162
|
};
|
|
23084
|
-
|
|
23163
|
+
fs23.mkdirSync(path30.dirname(file), { recursive: true });
|
|
23085
23164
|
const temp = `${file}.${process.pid}.tmp`;
|
|
23086
|
-
|
|
23087
|
-
|
|
23165
|
+
fs23.writeFileSync(temp, JSON.stringify(marker));
|
|
23166
|
+
fs23.renameSync(temp, file);
|
|
23088
23167
|
} catch {}
|
|
23089
23168
|
};
|
|
23090
23169
|
|
|
@@ -23093,22 +23172,22 @@ var NONE3 = { kind: "none" };
|
|
|
23093
23172
|
var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
|
|
23094
23173
|
var canonical2 = (file) => {
|
|
23095
23174
|
let rest = "";
|
|
23096
|
-
for (let dir =
|
|
23175
|
+
for (let dir = path31.resolve(file);; dir = path31.dirname(dir)) {
|
|
23097
23176
|
try {
|
|
23098
|
-
return
|
|
23177
|
+
return path31.join(realpathSync6.native(dir), rest);
|
|
23099
23178
|
} catch {
|
|
23100
|
-
if (
|
|
23101
|
-
return
|
|
23102
|
-
rest = rest ?
|
|
23179
|
+
if (path31.dirname(dir) === dir)
|
|
23180
|
+
return path31.resolve(file);
|
|
23181
|
+
rest = rest ? path31.join(path31.basename(dir), rest) : path31.basename(dir);
|
|
23103
23182
|
}
|
|
23104
23183
|
}
|
|
23105
23184
|
};
|
|
23106
23185
|
var exempt = (cwd, root, file, plans) => {
|
|
23107
23186
|
const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
|
|
23108
|
-
const relative =
|
|
23109
|
-
if (relative.startsWith("..") ||
|
|
23187
|
+
const relative = path31.relative(fold(canonical2(root)), fold(canonical2(path31.resolve(cwd, file))));
|
|
23188
|
+
if (relative.startsWith("..") || path31.isAbsolute(relative))
|
|
23110
23189
|
return true;
|
|
23111
|
-
const posix = relative.split(
|
|
23190
|
+
const posix = relative.split(path31.sep).join("/");
|
|
23112
23191
|
const segments = posix.split("/");
|
|
23113
23192
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
23114
23193
|
};
|
|
@@ -23229,7 +23308,7 @@ var shellWrites = (command, depth = 0) => {
|
|
|
23229
23308
|
return { writes: true, targets: unknown ? null : targets };
|
|
23230
23309
|
};
|
|
23231
23310
|
var cache2 = new Map;
|
|
23232
|
-
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(
|
|
23311
|
+
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path31.resolve(root, file)) ?? "-").join("\x00");
|
|
23233
23312
|
var gateFor = (cwd) => {
|
|
23234
23313
|
const store = new TaskStore(cwd);
|
|
23235
23314
|
const listed = store.listTaskIndex();
|
|
@@ -23308,7 +23387,7 @@ var gitMutationDirs = (cwd, command, dialect) => {
|
|
|
23308
23387
|
return [];
|
|
23309
23388
|
if (sub === "stash" && ["list", "show"].includes(rest[0] ?? ""))
|
|
23310
23389
|
return [];
|
|
23311
|
-
return [
|
|
23390
|
+
return [path31.resolve(cwd, invocation.dir ?? ".")];
|
|
23312
23391
|
});
|
|
23313
23392
|
};
|
|
23314
23393
|
var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
@@ -23319,7 +23398,7 @@ var cdInto = (dir, words) => {
|
|
|
23319
23398
|
const target = named === undefined ? undefined : homeExpanded(named);
|
|
23320
23399
|
if (dir === undefined || target === "-" || target && /^~|[$`*?]/.test(target))
|
|
23321
23400
|
return;
|
|
23322
|
-
return target === undefined ? os10.homedir() :
|
|
23401
|
+
return target === undefined ? os10.homedir() : path31.resolve(dir, target);
|
|
23323
23402
|
};
|
|
23324
23403
|
var quoteWord2 = (word) => /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`;
|
|
23325
23404
|
var homeExpanded = (file) => {
|
|
@@ -23333,7 +23412,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23333
23412
|
const groups = [];
|
|
23334
23413
|
const at = (file) => {
|
|
23335
23414
|
const home = homeExpanded(file);
|
|
23336
|
-
return
|
|
23415
|
+
return path31.isAbsolute(home) ? home : dir === undefined ? null : path31.resolve(dir, home);
|
|
23337
23416
|
};
|
|
23338
23417
|
for (const segment of segmentsOf(command, dialect)) {
|
|
23339
23418
|
if (segment.group === "open") {
|
|
@@ -23374,7 +23453,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23374
23453
|
const edits = editsOf(segment.words);
|
|
23375
23454
|
if (edits === null) {
|
|
23376
23455
|
if (dir !== undefined)
|
|
23377
|
-
targets.push(
|
|
23456
|
+
targets.push(path31.join(dir, DIR_TARGET));
|
|
23378
23457
|
} else
|
|
23379
23458
|
for (const file of edits) {
|
|
23380
23459
|
const resolved = at(file);
|
|
@@ -23382,7 +23461,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23382
23461
|
targets.push(resolved);
|
|
23383
23462
|
}
|
|
23384
23463
|
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), "")))
|
|
23385
|
-
targets.push(
|
|
23464
|
+
targets.push(path31.join(dir, DIR_TARGET));
|
|
23386
23465
|
}
|
|
23387
23466
|
return targets;
|
|
23388
23467
|
};
|
|
@@ -23417,7 +23496,7 @@ var liveDeny = ({ marker, checkout, ageMs, file }) => {
|
|
|
23417
23496
|
var guarded = (targets) => {
|
|
23418
23497
|
const seen = new Set;
|
|
23419
23498
|
return targets.filter((target) => {
|
|
23420
|
-
const dir =
|
|
23499
|
+
const dir = path31.dirname(target);
|
|
23421
23500
|
if (seen.has(dir))
|
|
23422
23501
|
return false;
|
|
23423
23502
|
seen.add(dir);
|
|
@@ -23438,7 +23517,7 @@ var claimAll = (owner, targets, deps) => {
|
|
|
23438
23517
|
for (const target of guarded(targets))
|
|
23439
23518
|
claimLiveSession(target, owner, deps);
|
|
23440
23519
|
};
|
|
23441
|
-
var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) =>
|
|
23520
|
+
var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path31.resolve(cwd, file)) : [path31.join(cwd, DIR_TARGET)];
|
|
23442
23521
|
var issuedTarget = (cwd, targets) => {
|
|
23443
23522
|
const state = resolveStateDir();
|
|
23444
23523
|
const found = targets.find((target) => underIssued(state, cwd, homeExpanded(target), process.platform, canonical2));
|
|
@@ -23446,7 +23525,7 @@ var issuedTarget = (cwd, targets) => {
|
|
|
23446
23525
|
};
|
|
23447
23526
|
var underIssued = (state, cwd, target, platform = process.platform, real = (file) => file) => {
|
|
23448
23527
|
const win = platform === "win32";
|
|
23449
|
-
const p = win ?
|
|
23528
|
+
const p = win ? path31.win32 : path31.posix;
|
|
23450
23529
|
const fold = (value) => win || platform === "darwin" ? value.toLowerCase() : value;
|
|
23451
23530
|
const named = win ? target.replace(/^\/([a-zA-Z])(?=\/|$)/, "$1:") : target;
|
|
23452
23531
|
const relative = p.relative(fold(real(p.resolve(state))), fold(real(p.resolve(cwd, named))));
|
|
@@ -23495,7 +23574,7 @@ function shellGate(cwd, command, owner, dialect = "posix", deps) {
|
|
|
23495
23574
|
try {
|
|
23496
23575
|
targets = [
|
|
23497
23576
|
...segmentTargets(cwd, command, dialect),
|
|
23498
|
-
...gitMutationDirs(cwd, command, dialect).map((dir) =>
|
|
23577
|
+
...gitMutationDirs(cwd, command, dialect).map((dir) => path31.join(dir, DIR_TARGET))
|
|
23499
23578
|
];
|
|
23500
23579
|
} catch {
|
|
23501
23580
|
targets = [];
|
|
@@ -23963,6 +24042,109 @@ var writePaths = (input) => {
|
|
|
23963
24042
|
paths.push(match[1].trim());
|
|
23964
24043
|
return [...new Set(paths)];
|
|
23965
24044
|
};
|
|
24045
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
24046
|
+
import fs24 from "node:fs";
|
|
24047
|
+
import path32 from "node:path";
|
|
24048
|
+
var readPlans = (store) => {
|
|
24049
|
+
const dir = path32.join(store, "fanouts");
|
|
24050
|
+
let names;
|
|
24051
|
+
try {
|
|
24052
|
+
names = fs24.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
24053
|
+
} catch {
|
|
24054
|
+
return [];
|
|
24055
|
+
}
|
|
24056
|
+
const plans = [];
|
|
24057
|
+
for (const name of names) {
|
|
24058
|
+
try {
|
|
24059
|
+
const raw = JSON.parse(fs24.readFileSync(path32.join(dir, name), "utf8"));
|
|
24060
|
+
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
24061
|
+
continue;
|
|
24062
|
+
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
24063
|
+
plans.push({
|
|
24064
|
+
name: raw.name,
|
|
24065
|
+
leads: texts([raw.leadSession, ...texts(raw.formerLeads)]),
|
|
24066
|
+
branches: texts(raw.slices.map((slice) => slice && typeof slice === "object" ? slice.branch : null))
|
|
24067
|
+
});
|
|
24068
|
+
} catch {}
|
|
24069
|
+
}
|
|
24070
|
+
return plans;
|
|
24071
|
+
};
|
|
24072
|
+
var leadOf2 = (input) => input.session.parentId ?? (input.session.agentId ? input.session.id : null) ?? (input.session.id.includes(":") ? input.session.id.split(":")[0] : null);
|
|
24073
|
+
var worksFor = (plan, input, branch) => {
|
|
24074
|
+
const session = input.session.id;
|
|
24075
|
+
if (plan.leads.includes(session) && !input.session.agentId)
|
|
24076
|
+
return false;
|
|
24077
|
+
const lead = leadOf2(input);
|
|
24078
|
+
if (lead && plan.leads.includes(lead))
|
|
24079
|
+
return true;
|
|
24080
|
+
if (plan.leads.some((each) => session.startsWith(`${each}-w-`)))
|
|
24081
|
+
return true;
|
|
24082
|
+
const current = branch();
|
|
24083
|
+
return current !== null && plan.branches.includes(current);
|
|
24084
|
+
};
|
|
24085
|
+
var standingFor = (input, store, rev) => {
|
|
24086
|
+
const orders = new Map;
|
|
24087
|
+
const ledger = readLedger(input.cwd);
|
|
24088
|
+
const rows = ledger.ok ? ledger.value.rows : [];
|
|
24089
|
+
let branch;
|
|
24090
|
+
const lazyBranch = () => branch === undefined ? branch = currentBranch(input.cwd) : branch;
|
|
24091
|
+
for (const plan of readPlans(store))
|
|
24092
|
+
if (worksFor(plan, input, lazyBranch))
|
|
24093
|
+
for (const row of activeStanding(rows, plan.name, plan.leads.length ? plan.leads : null))
|
|
24094
|
+
orders.set(row.id, row);
|
|
24095
|
+
return { rev, orders, rows };
|
|
24096
|
+
};
|
|
24097
|
+
var located = (input) => {
|
|
24098
|
+
const store = input.session.id ? gitStoreDir(input.cwd) : null;
|
|
24099
|
+
const rev = store ? readStandingRev(store) : null;
|
|
24100
|
+
if (!store || rev === null)
|
|
24101
|
+
return null;
|
|
24102
|
+
return { store, rev, file: standingSeenFile(store, input.session.id, input.session.agentId) };
|
|
24103
|
+
};
|
|
24104
|
+
var seedStanding = (input) => {
|
|
24105
|
+
try {
|
|
24106
|
+
const where = located(input);
|
|
24107
|
+
if (!where)
|
|
24108
|
+
return;
|
|
24109
|
+
const now = standingFor(input, where.store, where.rev);
|
|
24110
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
24111
|
+
} catch {}
|
|
24112
|
+
};
|
|
24113
|
+
var fanoutOf = (row) => typeof row.fanout === "string" ? row.fanout : "?";
|
|
24114
|
+
var changedSince = (now, ids) => {
|
|
24115
|
+
const known = new Set(ids);
|
|
24116
|
+
const added = [...now.orders.values()].filter((row) => !known.has(row.id));
|
|
24117
|
+
const byId = new Map(now.rows.map((row) => [row.id, row]));
|
|
24118
|
+
const dropped = ids.filter((id) => !now.orders.has(id)).map((id) => byId.get(id)).filter((row) => row !== undefined);
|
|
24119
|
+
if (!added.length && !dropped.length)
|
|
24120
|
+
return null;
|
|
24121
|
+
const fanouts = [...new Set([...added, ...dropped].map(fanoutOf))].join(", ");
|
|
24122
|
+
const lines = [
|
|
24123
|
+
`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.`,
|
|
24124
|
+
...added.map((row) => ` - new: ${String(row.what)}`),
|
|
24125
|
+
...dropped.map((row) => ` - no longer in force: ${String(row.what)}${row.stop ? " (the stop is lifted: continue your brief)" : ""}`)
|
|
24126
|
+
];
|
|
24127
|
+
if (added.some((row) => row.stop === true))
|
|
24128
|
+
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.");
|
|
24129
|
+
return lines.join(`
|
|
24130
|
+
`);
|
|
24131
|
+
};
|
|
24132
|
+
var standingDelta = (input) => {
|
|
24133
|
+
try {
|
|
24134
|
+
const where = located(input);
|
|
24135
|
+
if (!where)
|
|
24136
|
+
return null;
|
|
24137
|
+
const seen = readStandingSeen(where.file);
|
|
24138
|
+
if (seen.rev === where.rev)
|
|
24139
|
+
return null;
|
|
24140
|
+
const now = standingFor(input, where.store, where.rev);
|
|
24141
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
24142
|
+
return changedSince(now, seen.ids);
|
|
24143
|
+
} catch {
|
|
24144
|
+
return null;
|
|
24145
|
+
}
|
|
24146
|
+
};
|
|
24147
|
+
var sinceStart = new Map;
|
|
23966
24148
|
// packages/workit-core/src/hooks/handle.ts
|
|
23967
24149
|
var usable2 = (value) => value === "native" || value === "partial";
|
|
23968
24150
|
var NONE5 = { kind: "none" };
|
|
@@ -24007,7 +24189,18 @@ ${subagentStartText({ ...input, cwd: "" }, descriptor, event)}`;
|
|
|
24007
24189
|
const pick = judge === "verifier" ? ", --kind live when you drove the real surface" : "";
|
|
24008
24190
|
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." : ""}`;
|
|
24009
24191
|
};
|
|
24192
|
+
var PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
24010
24193
|
function handleHook(input, deps) {
|
|
24194
|
+
const decision = decide(input, deps);
|
|
24195
|
+
if (deps.descriptor.transport !== "hook-process" || !PRE_TOOL.has(input.event.kind) || decision.kind === "deny")
|
|
24196
|
+
return decision;
|
|
24197
|
+
const delta = standingDelta(input);
|
|
24198
|
+
if (!delta)
|
|
24199
|
+
return decision;
|
|
24200
|
+
return decision.kind === "rewrite" ? { ...decision, text: [decision.text, delta].filter(Boolean).join(`
|
|
24201
|
+
`) } : withContextLine(decision, delta);
|
|
24202
|
+
}
|
|
24203
|
+
function decide(input, deps) {
|
|
24011
24204
|
const { descriptor } = deps;
|
|
24012
24205
|
const event = input.event;
|
|
24013
24206
|
switch (event.kind) {
|
|
@@ -24084,6 +24277,7 @@ function handleHook(input, deps) {
|
|
|
24084
24277
|
case "write.pre":
|
|
24085
24278
|
return usable2(descriptor.events["write.pre"].support) ? writeGate(input.cwd, event.paths, liveOwner(input, descriptor.transport)) : NONE5;
|
|
24086
24279
|
case "subagent.start":
|
|
24280
|
+
seedStanding({ ...input, session: { ...input.session, agentId: event.agentId } });
|
|
24087
24281
|
return {
|
|
24088
24282
|
kind: "context",
|
|
24089
24283
|
text: subagentStartText(input, descriptor, event)
|
|
@@ -24243,6 +24437,13 @@ var turnInput = (ctx) => ({
|
|
|
24243
24437
|
transcriptPath: null,
|
|
24244
24438
|
event: { kind: "context.turn" }
|
|
24245
24439
|
});
|
|
24440
|
+
var standingNotice = (ctx) => {
|
|
24441
|
+
if (!ctx.isProjectTrusted())
|
|
24442
|
+
return null;
|
|
24443
|
+
const worker = process.env.WORKIT_PI_WORKER_SESSION && process.env.WORKIT_SESSION_ID?.trim();
|
|
24444
|
+
const input = turnInput(ctx);
|
|
24445
|
+
return standingDelta(worker ? { ...input, session: { ...input.session, id: worker } } : input);
|
|
24446
|
+
};
|
|
24246
24447
|
var workitContext = (ctx, taskContext = turnContext(ctx)) => {
|
|
24247
24448
|
const session = ctx.sessionManager.getSessionId();
|
|
24248
24449
|
if (!ctx.isProjectTrusted())
|
|
@@ -24403,12 +24604,12 @@ var skillPromptNudge = (prompt, ctx) => process.env.WORKIT_PI_WORKER_SESSION ? n
|
|
|
24403
24604
|
// packages/workit-pi/src/launches.ts
|
|
24404
24605
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
24405
24606
|
import os11 from "node:os";
|
|
24406
|
-
import
|
|
24607
|
+
import path33 from "node:path";
|
|
24407
24608
|
var launchDir = (root) => {
|
|
24408
24609
|
const location = resolveStore(root);
|
|
24409
|
-
return location instanceof Error ? null :
|
|
24610
|
+
return location instanceof Error ? null : path33.join(location.dir, "pi-launches");
|
|
24410
24611
|
};
|
|
24411
|
-
var fileFor = (dir, workerId) =>
|
|
24612
|
+
var fileFor = (dir, workerId) => path33.join(dir, `${workerId.replace(/[^A-Za-z0-9-]/g, "_")}.json`);
|
|
24412
24613
|
var recordLaunch = (root, attempt) => {
|
|
24413
24614
|
const dir = launchDir(root);
|
|
24414
24615
|
if (!dir)
|
|
@@ -24454,7 +24655,7 @@ var abandonedLaunches = (root) => {
|
|
|
24454
24655
|
const found = [];
|
|
24455
24656
|
for (const name of names) {
|
|
24456
24657
|
try {
|
|
24457
|
-
const attempt = JSON.parse(readFileSync6(
|
|
24658
|
+
const attempt = JSON.parse(readFileSync6(path33.join(dir, name), "utf8"));
|
|
24458
24659
|
if (typeof attempt.workerId === "string" && typeof attempt.session === "string") {
|
|
24459
24660
|
if (!alive(attempt))
|
|
24460
24661
|
found.push(attempt);
|
|
@@ -24632,6 +24833,14 @@ function launchWorker(assignment, options) {
|
|
|
24632
24833
|
WORKIT_PI_WORKER_ROLE: assignment.role,
|
|
24633
24834
|
WORKIT_PI_WORKER_SCOPE: JSON.stringify(assignment.scope)
|
|
24634
24835
|
};
|
|
24836
|
+
seedStanding({
|
|
24837
|
+
host: "pi",
|
|
24838
|
+
cwd: spec.cwd,
|
|
24839
|
+
session: { id: env.WORKIT_SESSION_ID, agentId: null, agentType: null, parentId: null },
|
|
24840
|
+
permissionMode: null,
|
|
24841
|
+
transcriptPath: null,
|
|
24842
|
+
event: { kind: "session.start", source: "startup" }
|
|
24843
|
+
});
|
|
24635
24844
|
try {
|
|
24636
24845
|
const spawn = options.spawn ?? ((command, args, spawnOptions) => nodeSpawn(command, args, spawnOptions));
|
|
24637
24846
|
handle.spec = { ...spec, env };
|
|
@@ -25361,6 +25570,16 @@ ${nudge}` : content) };
|
|
|
25361
25570
|
});
|
|
25362
25571
|
pi.on("tool_call", (event, ctx) => enforceToolPolicy(event, ctx));
|
|
25363
25572
|
pi.on("tool_result", (event, ctx) => {
|
|
25573
|
+
const observed = observeResult(event, ctx);
|
|
25574
|
+
let standing = null;
|
|
25575
|
+
try {
|
|
25576
|
+
standing = standingNotice(ctx);
|
|
25577
|
+
} catch {}
|
|
25578
|
+
if (!standing)
|
|
25579
|
+
return observed;
|
|
25580
|
+
return { content: [...observed?.content ?? event.content, { type: "text", text: standing }] };
|
|
25581
|
+
});
|
|
25582
|
+
const observeResult = (event, ctx) => {
|
|
25364
25583
|
if (childWorker && event.toolName === "workit_worker") {
|
|
25365
25584
|
const details = event.details;
|
|
25366
25585
|
const report = typeof details === "object" && details !== null && "data" in details && typeof details.data === "object" && details.data.data?.report;
|
|
@@ -25382,7 +25601,7 @@ ${nudge}` : content) };
|
|
|
25382
25601
|
isError: event.isError
|
|
25383
25602
|
});
|
|
25384
25603
|
return observeToolResult(event, ctx);
|
|
25385
|
-
}
|
|
25604
|
+
};
|
|
25386
25605
|
pi.on("session_shutdown", (_event, ctx) => {
|
|
25387
25606
|
sessions.delete(ctx.sessionManager.getSessionId());
|
|
25388
25607
|
});
|