@brainervirus/workit-opencode 8.20.0 → 8.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin.js +506 -314
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -6,7 +6,7 @@ function define(plugin) {
|
|
|
6
6
|
// packages/workit-core/src/core.ts
|
|
7
7
|
import { spawnSync as spawnSync16 } from "node:child_process";
|
|
8
8
|
import { existsSync as existsSync8, realpathSync as realpathSync5 } from "node:fs";
|
|
9
|
-
import
|
|
9
|
+
import path25 from "node:path";
|
|
10
10
|
|
|
11
11
|
// packages/workit-core/src/core/task-contract.ts
|
|
12
12
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -14414,10 +14414,10 @@ var workerBlocksTransition = (transition, state) => transition === "pause" ? fal
|
|
|
14414
14414
|
var holdsLiveState = (state, dirty) => state === "running" || dirty === true;
|
|
14415
14415
|
|
|
14416
14416
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
14417
|
-
import { createHash as
|
|
14418
|
-
import * as
|
|
14417
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
14418
|
+
import * as fs14 from "node:fs";
|
|
14419
14419
|
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
14420
|
-
import
|
|
14420
|
+
import path17 from "node:path";
|
|
14421
14421
|
|
|
14422
14422
|
// packages/workit-core/src/check-config.ts
|
|
14423
14423
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
@@ -14648,13 +14648,70 @@ function checkCommand(args, version, onPath = workitAvailable()) {
|
|
|
14648
14648
|
|
|
14649
14649
|
// packages/workit-core/src/core/policy/derive.ts
|
|
14650
14650
|
import { existsSync as existsSync4 } from "node:fs";
|
|
14651
|
-
import
|
|
14651
|
+
import path16 from "node:path";
|
|
14652
14652
|
|
|
14653
14653
|
// packages/workit-core/src/ledger.ts
|
|
14654
14654
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
14655
|
-
import { createHash as
|
|
14655
|
+
import { createHash as createHash11, randomBytes as randomBytes3 } from "node:crypto";
|
|
14656
|
+
import fs13 from "node:fs";
|
|
14657
|
+
import path15 from "node:path";
|
|
14658
|
+
|
|
14659
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
14660
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
14656
14661
|
import fs12 from "node:fs";
|
|
14657
14662
|
import path14 from "node:path";
|
|
14663
|
+
var gitStoreDir = (cwd) => {
|
|
14664
|
+
try {
|
|
14665
|
+
for (let dir = path14.resolve(cwd);; dir = path14.dirname(dir)) {
|
|
14666
|
+
const dotGit = path14.join(dir, ".git");
|
|
14667
|
+
if (fs12.existsSync(dotGit)) {
|
|
14668
|
+
let gitDir = dotGit;
|
|
14669
|
+
if (fs12.statSync(dotGit).isFile()) {
|
|
14670
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs12.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
14671
|
+
if (!target)
|
|
14672
|
+
return null;
|
|
14673
|
+
gitDir = path14.resolve(dir, target);
|
|
14674
|
+
const common = path14.join(gitDir, "commondir");
|
|
14675
|
+
if (fs12.existsSync(common))
|
|
14676
|
+
gitDir = path14.resolve(gitDir, fs12.readFileSync(common, "utf8").trim());
|
|
14677
|
+
}
|
|
14678
|
+
return path14.join(gitDir, "workit");
|
|
14679
|
+
}
|
|
14680
|
+
if (path14.dirname(dir) === dir)
|
|
14681
|
+
return null;
|
|
14682
|
+
}
|
|
14683
|
+
} catch {
|
|
14684
|
+
return null;
|
|
14685
|
+
}
|
|
14686
|
+
};
|
|
14687
|
+
var standingRevFile = (store) => path14.join(store, "standing", "rev");
|
|
14688
|
+
var standingSeenFile = (store, session, agentId) => path14.join(store, "standing", "seen", `${createHash10("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
14689
|
+
var readStandingRev = (store) => {
|
|
14690
|
+
try {
|
|
14691
|
+
return fs12.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
14692
|
+
} catch {
|
|
14693
|
+
return null;
|
|
14694
|
+
}
|
|
14695
|
+
};
|
|
14696
|
+
var readStandingSeen = (file) => {
|
|
14697
|
+
try {
|
|
14698
|
+
const value = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
14699
|
+
return {
|
|
14700
|
+
rev: typeof value.rev === "string" ? value.rev : null,
|
|
14701
|
+
ids: Array.isArray(value.ids) ? value.ids.filter((id) => typeof id === "string") : []
|
|
14702
|
+
};
|
|
14703
|
+
} catch {
|
|
14704
|
+
return { rev: null, ids: [] };
|
|
14705
|
+
}
|
|
14706
|
+
};
|
|
14707
|
+
var writeStandingSeen = (file, seen) => {
|
|
14708
|
+
try {
|
|
14709
|
+
fs12.mkdirSync(path14.dirname(file), { recursive: true });
|
|
14710
|
+
fs12.writeFileSync(file, JSON.stringify(seen));
|
|
14711
|
+
} catch {}
|
|
14712
|
+
};
|
|
14713
|
+
|
|
14714
|
+
// packages/workit-core/src/ledger.ts
|
|
14658
14715
|
var LEDGER_VERSION = 1;
|
|
14659
14716
|
var MAX_LINE_BYTES = 4096;
|
|
14660
14717
|
var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
|
|
@@ -14764,7 +14821,7 @@ function diffHash(cwd, base, head) {
|
|
|
14764
14821
|
], GIT_TIMEOUTS.worktree);
|
|
14765
14822
|
if (!diff.ok || !diff.stdout)
|
|
14766
14823
|
return null;
|
|
14767
|
-
const hash =
|
|
14824
|
+
const hash = createHash11("sha256");
|
|
14768
14825
|
for (const line of diff.stdout.split(`
|
|
14769
14826
|
`)) {
|
|
14770
14827
|
if (line.startsWith("index "))
|
|
@@ -14776,14 +14833,14 @@ function diffHash(cwd, base, head) {
|
|
|
14776
14833
|
return `sha256:${hash.digest("hex")}`;
|
|
14777
14834
|
}
|
|
14778
14835
|
function storeRoot(cwd) {
|
|
14779
|
-
const location = resolveStore(
|
|
14836
|
+
const location = resolveStore(path15.resolve(cwd));
|
|
14780
14837
|
if (location instanceof Error)
|
|
14781
14838
|
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");
|
|
14782
14839
|
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
14783
14840
|
}
|
|
14784
14841
|
function ledgerPath(cwd) {
|
|
14785
14842
|
const root = storeRoot(cwd);
|
|
14786
|
-
return root.ok ? { ok: true, value:
|
|
14843
|
+
return root.ok ? { ok: true, value: path15.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
14787
14844
|
}
|
|
14788
14845
|
var newId2 = () => `${Date.now().toString(36)}-${randomBytes3(6).toString("hex")}`;
|
|
14789
14846
|
var NETWORK_FS_TYPES = new Set([
|
|
@@ -14803,7 +14860,7 @@ var onNetworkFs = (dir) => {
|
|
|
14803
14860
|
if (process.platform !== "linux")
|
|
14804
14861
|
return false;
|
|
14805
14862
|
try {
|
|
14806
|
-
return isNetworkFsType(
|
|
14863
|
+
return isNetworkFsType(fs13.statfsSync(dir).type);
|
|
14807
14864
|
} catch {
|
|
14808
14865
|
return false;
|
|
14809
14866
|
}
|
|
@@ -14813,15 +14870,15 @@ var LOCK_STALE_MS = 30000;
|
|
|
14813
14870
|
var LOCK_OWNER = "owner";
|
|
14814
14871
|
var lockToken = (lock) => {
|
|
14815
14872
|
try {
|
|
14816
|
-
return
|
|
14873
|
+
return fs13.readFileSync(path15.join(lock, LOCK_OWNER), "utf8");
|
|
14817
14874
|
} catch {
|
|
14818
14875
|
return null;
|
|
14819
14876
|
}
|
|
14820
14877
|
};
|
|
14821
14878
|
var lockAgeMs = (lock) => {
|
|
14822
|
-
for (const target of [
|
|
14879
|
+
for (const target of [path15.join(lock, LOCK_OWNER), lock]) {
|
|
14823
14880
|
try {
|
|
14824
|
-
return Date.now() -
|
|
14881
|
+
return Date.now() - fs13.statSync(target).mtimeMs;
|
|
14825
14882
|
} catch {}
|
|
14826
14883
|
}
|
|
14827
14884
|
return null;
|
|
@@ -14829,14 +14886,14 @@ var lockAgeMs = (lock) => {
|
|
|
14829
14886
|
var ledgerLock = {
|
|
14830
14887
|
acquire(lock) {
|
|
14831
14888
|
try {
|
|
14832
|
-
|
|
14889
|
+
fs13.mkdirSync(lock);
|
|
14833
14890
|
} catch (error) {
|
|
14834
14891
|
if (error.code === "EEXIST")
|
|
14835
14892
|
return null;
|
|
14836
14893
|
throw error;
|
|
14837
14894
|
}
|
|
14838
14895
|
const token = `${process.pid}-${randomBytes3(8).toString("hex")}`;
|
|
14839
|
-
|
|
14896
|
+
fs13.writeFileSync(path15.join(lock, LOCK_OWNER), token);
|
|
14840
14897
|
return token;
|
|
14841
14898
|
},
|
|
14842
14899
|
release(lock, token) {
|
|
@@ -14844,35 +14901,35 @@ var ledgerLock = {
|
|
|
14844
14901
|
return false;
|
|
14845
14902
|
const tomb = `${lock}.release-${randomBytes3(6).toString("hex")}`;
|
|
14846
14903
|
try {
|
|
14847
|
-
|
|
14904
|
+
fs13.renameSync(lock, tomb);
|
|
14848
14905
|
} catch {
|
|
14849
14906
|
return false;
|
|
14850
14907
|
}
|
|
14851
14908
|
if (lockToken(tomb) !== token) {
|
|
14852
14909
|
try {
|
|
14853
|
-
|
|
14910
|
+
fs13.renameSync(tomb, lock);
|
|
14854
14911
|
} catch {}
|
|
14855
14912
|
return false;
|
|
14856
14913
|
}
|
|
14857
|
-
|
|
14914
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14858
14915
|
return true;
|
|
14859
14916
|
},
|
|
14860
14917
|
token: lockToken,
|
|
14861
14918
|
reap(lock, observed) {
|
|
14862
14919
|
const tomb = `${lock}.reap-${randomBytes3(6).toString("hex")}`;
|
|
14863
14920
|
try {
|
|
14864
|
-
|
|
14921
|
+
fs13.renameSync(lock, tomb);
|
|
14865
14922
|
} catch {
|
|
14866
14923
|
return false;
|
|
14867
14924
|
}
|
|
14868
14925
|
if (lockToken(tomb) === observed) {
|
|
14869
|
-
|
|
14926
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14870
14927
|
return true;
|
|
14871
14928
|
}
|
|
14872
14929
|
try {
|
|
14873
|
-
|
|
14930
|
+
fs13.renameSync(tomb, lock);
|
|
14874
14931
|
} catch {
|
|
14875
|
-
|
|
14932
|
+
fs13.rmSync(tomb, { recursive: true, force: true });
|
|
14876
14933
|
}
|
|
14877
14934
|
return false;
|
|
14878
14935
|
}
|
|
@@ -14899,14 +14956,14 @@ function withLedgerLock(file, fn, waitMs = hostAwareLockTimeout(LOCK_WAIT_MS)) {
|
|
|
14899
14956
|
ledgerLock.release(lock, token);
|
|
14900
14957
|
}
|
|
14901
14958
|
}
|
|
14902
|
-
var sha2562 = (text) =>
|
|
14959
|
+
var sha2562 = (text) => createHash11("sha256").update(text).digest("hex");
|
|
14903
14960
|
var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
|
|
14904
14961
|
${body}`);
|
|
14905
14962
|
var TAIL_BYTES = 64 * 1024;
|
|
14906
14963
|
var lastLine = (fd, size) => {
|
|
14907
14964
|
for (let span = Math.min(size, TAIL_BYTES);span > 0; span = Math.min(size, span * 2)) {
|
|
14908
14965
|
const buffer = Buffer.alloc(span);
|
|
14909
|
-
|
|
14966
|
+
fs13.readSync(fd, buffer, 0, span, size - span);
|
|
14910
14967
|
const end = buffer.lastIndexOf(10);
|
|
14911
14968
|
if (end < 0) {
|
|
14912
14969
|
if (span === size)
|
|
@@ -14937,21 +14994,21 @@ var lastLine = (fd, size) => {
|
|
|
14937
14994
|
};
|
|
14938
14995
|
var tighten = (fd) => {
|
|
14939
14996
|
try {
|
|
14940
|
-
if ((
|
|
14941
|
-
|
|
14997
|
+
if ((fs13.fstatSync(fd).mode & 63) !== 0)
|
|
14998
|
+
fs13.fchmodSync(fd, 384);
|
|
14942
14999
|
} catch {}
|
|
14943
15000
|
};
|
|
14944
15001
|
function appendLine(file, build, options) {
|
|
14945
15002
|
const write = () => {
|
|
14946
|
-
const fd =
|
|
15003
|
+
const fd = fs13.openSync(file, "a+", 384);
|
|
14947
15004
|
try {
|
|
14948
15005
|
if (process.platform !== "win32")
|
|
14949
15006
|
tighten(fd);
|
|
14950
|
-
const size =
|
|
15007
|
+
const size = fs13.fstatSync(fd).size;
|
|
14951
15008
|
let fence = "";
|
|
14952
15009
|
if (size > 0) {
|
|
14953
15010
|
const last = Buffer.alloc(1);
|
|
14954
|
-
|
|
15011
|
+
fs13.readSync(fd, last, 0, 1, size - 1);
|
|
14955
15012
|
if (last[0] !== 10)
|
|
14956
15013
|
fence = `
|
|
14957
15014
|
`;
|
|
@@ -14960,17 +15017,17 @@ function appendLine(file, build, options) {
|
|
|
14960
15017
|
if (!line.ok)
|
|
14961
15018
|
return line;
|
|
14962
15019
|
const bytes = Buffer.from(fence + line.value);
|
|
14963
|
-
const written =
|
|
15020
|
+
const written = fs13.writeSync(fd, bytes);
|
|
14964
15021
|
if (written !== bytes.length)
|
|
14965
15022
|
return err("unavailable", `short write to ${file}: ${written} of ${bytes.length} bytes; the row is torn and will be skipped`);
|
|
14966
15023
|
return { ok: true, value: undefined };
|
|
14967
15024
|
} finally {
|
|
14968
|
-
|
|
15025
|
+
fs13.closeSync(fd);
|
|
14969
15026
|
}
|
|
14970
15027
|
};
|
|
14971
15028
|
try {
|
|
14972
|
-
|
|
14973
|
-
if (!options.forceLock && !onNetworkFs(
|
|
15029
|
+
fs13.mkdirSync(path15.dirname(file), { recursive: true });
|
|
15030
|
+
if (!options.forceLock && !onNetworkFs(path15.dirname(file)))
|
|
14974
15031
|
return write();
|
|
14975
15032
|
const locked = withLedgerLock(file, write);
|
|
14976
15033
|
return locked ?? err("busy", `ledger lock ${file}.lock is held`, "retry; remove the .lock directory if no workit process is running");
|
|
@@ -15043,8 +15100,8 @@ function readLedger(cwd, options = {}) {
|
|
|
15043
15100
|
let text = "";
|
|
15044
15101
|
let stat = null;
|
|
15045
15102
|
try {
|
|
15046
|
-
stat =
|
|
15047
|
-
text =
|
|
15103
|
+
stat = fs13.statSync(file.value);
|
|
15104
|
+
text = fs13.readFileSync(file.value, "utf8");
|
|
15048
15105
|
} catch (error) {
|
|
15049
15106
|
if (error.code === "ENOENT")
|
|
15050
15107
|
return {
|
|
@@ -15179,7 +15236,7 @@ function ledgerTampering(cwd) {
|
|
|
15179
15236
|
if (!file.ok)
|
|
15180
15237
|
return [];
|
|
15181
15238
|
try {
|
|
15182
|
-
const stat =
|
|
15239
|
+
const stat = fs13.statSync(file.value);
|
|
15183
15240
|
const cached = tamperCache.get(file.value);
|
|
15184
15241
|
if (cached && cached.size === stat.size && cached.stamp === fileStamp(stat))
|
|
15185
15242
|
return cached.breaks;
|
|
@@ -15510,6 +15567,28 @@ function checkVerdicts(cwd, branch, ledgerRows) {
|
|
|
15510
15567
|
warnings
|
|
15511
15568
|
};
|
|
15512
15569
|
}
|
|
15570
|
+
var fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session);
|
|
15571
|
+
function activeStanding(rows, fanout, leads = null) {
|
|
15572
|
+
const active = [];
|
|
15573
|
+
for (const row of rows) {
|
|
15574
|
+
if (row.fanout !== fanout || !fromLead(row, leads))
|
|
15575
|
+
continue;
|
|
15576
|
+
if (row.type === "standing" && typeof row.what === "string" && row.what.trim()) {
|
|
15577
|
+
if (!row.superseded)
|
|
15578
|
+
active.push(row);
|
|
15579
|
+
} else if (row.type === "standing.cleared") {
|
|
15580
|
+
const target = str2(row.target);
|
|
15581
|
+
if (target === null)
|
|
15582
|
+
active.length = 0;
|
|
15583
|
+
else {
|
|
15584
|
+
const index = active.findIndex((order) => order.id === target);
|
|
15585
|
+
if (index >= 0)
|
|
15586
|
+
active.splice(index, 1);
|
|
15587
|
+
}
|
|
15588
|
+
}
|
|
15589
|
+
}
|
|
15590
|
+
return active;
|
|
15591
|
+
}
|
|
15513
15592
|
var OBSERVED_ONLY = new Set([
|
|
15514
15593
|
"check",
|
|
15515
15594
|
"merge.unverified",
|
|
@@ -15658,7 +15737,7 @@ var productDecision = (task, ledger) => {
|
|
|
15658
15737
|
};
|
|
15659
15738
|
};
|
|
15660
15739
|
var planRecorded = (task, root) => {
|
|
15661
|
-
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(
|
|
15740
|
+
const cited = (latestJudgment(task)?.refs ?? []).find((ref) => ref.kind === "external" || ref.kind === "file" && existsSync4(path16.resolve(root, ref.path)));
|
|
15662
15741
|
if (cited)
|
|
15663
15742
|
return {
|
|
15664
15743
|
met: true,
|
|
@@ -15717,15 +15796,15 @@ function writeBlockers(task, root) {
|
|
|
15717
15796
|
}
|
|
15718
15797
|
|
|
15719
15798
|
// packages/workit-core/src/core/task-evaluation.ts
|
|
15720
|
-
var digestBytes = (value) =>
|
|
15721
|
-
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${
|
|
15722
|
-
var relative = (root, candidate) =>
|
|
15799
|
+
var digestBytes = (value) => createHash12("sha256").update(value).digest("hex");
|
|
15800
|
+
var inside = (root, candidate) => candidate === root || candidate.startsWith(`${root}${path17.sep}`);
|
|
15801
|
+
var relative = (root, candidate) => path17.relative(root, candidate).split(path17.sep).join("/") || ".";
|
|
15723
15802
|
var canonicalPath = (value) => {
|
|
15724
15803
|
if (typeof value !== "string" || !value)
|
|
15725
15804
|
return null;
|
|
15726
15805
|
if (value.includes("\\") || value.split("/").includes(".."))
|
|
15727
15806
|
return null;
|
|
15728
|
-
const normalized =
|
|
15807
|
+
const normalized = path17.posix.normalize(value);
|
|
15729
15808
|
if (normalized === ".." || normalized.startsWith("../") || normalized.startsWith("/"))
|
|
15730
15809
|
return null;
|
|
15731
15810
|
return normalized === "." ? "." : normalized.replace(/\/$/, "");
|
|
@@ -15773,21 +15852,21 @@ var gitPaths = (root) => {
|
|
|
15773
15852
|
git: !/not a git repository/i.test(stderr)
|
|
15774
15853
|
};
|
|
15775
15854
|
}
|
|
15776
|
-
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15855
|
+
const paths = result.stdout ? result.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")) : [];
|
|
15777
15856
|
const stagedDeleted = spawnSync10("git", ["diff", "--cached", "--name-only", "--diff-filter=D", "-z"], { cwd: root, encoding: "buffer" });
|
|
15778
15857
|
if (stagedDeleted.status !== 0) {
|
|
15779
15858
|
const stderr = stagedDeleted.stderr?.toString("utf8") ?? "";
|
|
15780
15859
|
if (!/not a git repository/i.test(stderr))
|
|
15781
15860
|
return { paths, uncertain: true, git: true };
|
|
15782
15861
|
} else if (stagedDeleted.stdout) {
|
|
15783
|
-
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(
|
|
15862
|
+
paths.push(...stagedDeleted.stdout.toString("utf8").split("\x00").filter(Boolean).map((item) => item.split(path17.sep).join("/")));
|
|
15784
15863
|
}
|
|
15785
15864
|
return { paths: [...new Set(paths)], uncertain: false, git: true };
|
|
15786
15865
|
};
|
|
15787
15866
|
var walk = (root, directory, output) => {
|
|
15788
15867
|
let names;
|
|
15789
15868
|
try {
|
|
15790
|
-
names =
|
|
15869
|
+
names = fs14.readdirSync(directory);
|
|
15791
15870
|
} catch {
|
|
15792
15871
|
return true;
|
|
15793
15872
|
}
|
|
@@ -15795,10 +15874,10 @@ var walk = (root, directory, output) => {
|
|
|
15795
15874
|
for (const name of names) {
|
|
15796
15875
|
if (name === ".git" || name === ".workit")
|
|
15797
15876
|
continue;
|
|
15798
|
-
const target =
|
|
15877
|
+
const target = path17.join(directory, name);
|
|
15799
15878
|
let stat;
|
|
15800
15879
|
try {
|
|
15801
|
-
stat =
|
|
15880
|
+
stat = fs14.lstatSync(target);
|
|
15802
15881
|
} catch {
|
|
15803
15882
|
uncertain = true;
|
|
15804
15883
|
continue;
|
|
@@ -15813,14 +15892,14 @@ var walk = (root, directory, output) => {
|
|
|
15813
15892
|
var scopeRoots = (root, scope) => {
|
|
15814
15893
|
const roots = [];
|
|
15815
15894
|
for (const item of scope.paths.length ? scope.paths : ["."]) {
|
|
15816
|
-
const target =
|
|
15895
|
+
const target = path17.resolve(root, item);
|
|
15817
15896
|
if (!inside(root, target))
|
|
15818
15897
|
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` }] });
|
|
15819
15898
|
let ancestor = target;
|
|
15820
|
-
while (!
|
|
15821
|
-
ancestor =
|
|
15899
|
+
while (!fs14.existsSync(ancestor) && ancestor !== root)
|
|
15900
|
+
ancestor = path17.dirname(ancestor);
|
|
15822
15901
|
try {
|
|
15823
|
-
if (!inside(root,
|
|
15902
|
+
if (!inside(root, fs14.realpathSync(ancestor)))
|
|
15824
15903
|
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` }] });
|
|
15825
15904
|
} catch {
|
|
15826
15905
|
return failure2("invalid_input", `candidate scope cannot be inspected: ${item}`);
|
|
@@ -15832,7 +15911,7 @@ var scopeRoots = (root, scope) => {
|
|
|
15832
15911
|
function captureCandidate(root, scope, environment = []) {
|
|
15833
15912
|
let checkout;
|
|
15834
15913
|
try {
|
|
15835
|
-
checkout =
|
|
15914
|
+
checkout = fs14.realpathSync(root);
|
|
15836
15915
|
} catch {
|
|
15837
15916
|
return failure2("invalid_input", "candidate root does not exist");
|
|
15838
15917
|
}
|
|
@@ -15850,11 +15929,11 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15850
15929
|
if (item === ".git" || item === ".workit")
|
|
15851
15930
|
continue;
|
|
15852
15931
|
names.add(item);
|
|
15853
|
-
if (!
|
|
15932
|
+
if (!fs14.existsSync(target))
|
|
15854
15933
|
continue;
|
|
15855
15934
|
let stat;
|
|
15856
15935
|
try {
|
|
15857
|
-
stat =
|
|
15936
|
+
stat = fs14.lstatSync(target);
|
|
15858
15937
|
} catch {
|
|
15859
15938
|
uncertain = true;
|
|
15860
15939
|
continue;
|
|
@@ -15870,17 +15949,17 @@ function captureCandidate(root, scope, environment = []) {
|
|
|
15870
15949
|
for (const item of [...names].toSorted()) {
|
|
15871
15950
|
if (!scopeMatches(item, normalizedScope))
|
|
15872
15951
|
continue;
|
|
15873
|
-
const target =
|
|
15952
|
+
const target = path17.join(checkout, item);
|
|
15874
15953
|
try {
|
|
15875
|
-
const stat =
|
|
15954
|
+
const stat = fs14.lstatSync(target);
|
|
15876
15955
|
if (stat.isSymbolicLink()) {
|
|
15877
|
-
const link =
|
|
15956
|
+
const link = fs14.readlinkSync(target);
|
|
15878
15957
|
files.push({ path: item, kind: "symlink", digest: digestBytes(link), executable: null });
|
|
15879
15958
|
} else if (stat.isFile()) {
|
|
15880
15959
|
files.push({
|
|
15881
15960
|
path: item,
|
|
15882
15961
|
kind: "file",
|
|
15883
|
-
digest: digestBytes(
|
|
15962
|
+
digest: digestBytes(fs14.readFileSync(target)),
|
|
15884
15963
|
executable: (stat.mode & 73) !== 0
|
|
15885
15964
|
});
|
|
15886
15965
|
} else if (!stat.isDirectory()) {
|
|
@@ -16045,7 +16124,7 @@ var findingVerificationPasses = (findingCandidateId, evidence) => evidence.statu
|
|
|
16045
16124
|
var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
16046
16125
|
let root;
|
|
16047
16126
|
try {
|
|
16048
|
-
root =
|
|
16127
|
+
root = fs14.realpathSync(checkoutRoot);
|
|
16049
16128
|
} catch {
|
|
16050
16129
|
return failure2("permission_denied", "checkout root is unavailable");
|
|
16051
16130
|
}
|
|
@@ -16054,23 +16133,23 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
16054
16133
|
continue;
|
|
16055
16134
|
if (!reference.digest)
|
|
16056
16135
|
return failure2("invalid_input", "document references require a byte digest");
|
|
16057
|
-
const target =
|
|
16058
|
-
if (target !== root && !target.startsWith(`${root}${
|
|
16136
|
+
const target = path17.resolve(root, reference.path);
|
|
16137
|
+
if (target !== root && !target.startsWith(`${root}${path17.sep}`))
|
|
16059
16138
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16060
16139
|
fields: [
|
|
16061
16140
|
{ path: "contentRefs.path", reason: `${reference.path} is outside the checkout` }
|
|
16062
16141
|
]
|
|
16063
16142
|
});
|
|
16064
16143
|
try {
|
|
16065
|
-
const below =
|
|
16144
|
+
const below = path17.relative(root, target);
|
|
16066
16145
|
let current = root;
|
|
16067
|
-
for (const segment of below.split(
|
|
16146
|
+
for (const segment of below.split(path17.sep)) {
|
|
16068
16147
|
if (!segment)
|
|
16069
16148
|
continue;
|
|
16070
|
-
current =
|
|
16071
|
-
const stat =
|
|
16072
|
-
const real =
|
|
16073
|
-
if (real !== root && !real.startsWith(`${root}${
|
|
16149
|
+
current = path17.join(current, segment);
|
|
16150
|
+
const stat = fs14.lstatSync(current);
|
|
16151
|
+
const real = fs14.realpathSync(current);
|
|
16152
|
+
if (real !== root && !real.startsWith(`${root}${path17.sep}`))
|
|
16074
16153
|
return failure2("invalid_input", "document reference escapes checkout; cite it as an external file:// reference instead", {
|
|
16075
16154
|
fields: [
|
|
16076
16155
|
{
|
|
@@ -16086,7 +16165,7 @@ var verifyDecisionContentAtRoot = (checkoutRoot, binding) => {
|
|
|
16086
16165
|
if (current !== target && !stat.isDirectory())
|
|
16087
16166
|
return failure2("invalid_input", "document reference ancestor is not a directory");
|
|
16088
16167
|
}
|
|
16089
|
-
if (digestBytes(
|
|
16168
|
+
if (digestBytes(fs14.readFileSync(target)) !== reference.digest)
|
|
16090
16169
|
return failure2("permission_denied", "decision document bytes have changed");
|
|
16091
16170
|
} catch {
|
|
16092
16171
|
return failure2("invalid_input", "decision document is unavailable");
|
|
@@ -16666,19 +16745,19 @@ var exportDigest = (bundle) => sha256({
|
|
|
16666
16745
|
// packages/workit-core/src/core/route-intent.ts
|
|
16667
16746
|
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
16668
16747
|
import { existsSync as existsSync6 } from "node:fs";
|
|
16669
|
-
import
|
|
16748
|
+
import path20 from "node:path";
|
|
16670
16749
|
|
|
16671
16750
|
// packages/workit-core/src/hooks/raw-git.ts
|
|
16672
16751
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
16673
|
-
import { createHash as
|
|
16674
|
-
import
|
|
16752
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
16753
|
+
import fs16 from "node:fs";
|
|
16675
16754
|
import os4 from "node:os";
|
|
16676
|
-
import
|
|
16755
|
+
import path19 from "node:path";
|
|
16677
16756
|
|
|
16678
16757
|
// packages/workit-core/src/hooks/session-marker.ts
|
|
16679
|
-
import { createHash as
|
|
16680
|
-
import
|
|
16681
|
-
import
|
|
16758
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
16759
|
+
import fs15 from "node:fs";
|
|
16760
|
+
import path18 from "node:path";
|
|
16682
16761
|
var sessionMarkerFile = (input, session, store) => {
|
|
16683
16762
|
let dir = store;
|
|
16684
16763
|
if (dir === undefined) {
|
|
@@ -16687,13 +16766,13 @@ var sessionMarkerFile = (input, session, store) => {
|
|
|
16687
16766
|
return null;
|
|
16688
16767
|
dir = location.dir;
|
|
16689
16768
|
}
|
|
16690
|
-
const name =
|
|
16691
|
-
return
|
|
16769
|
+
const name = createHash13("sha256").update(`${input.host}\x00${session}`).digest("hex").slice(0, 32);
|
|
16770
|
+
return path18.join(dir, "hooks", `skills-${name}.json`);
|
|
16692
16771
|
};
|
|
16693
16772
|
var list2 = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
16694
16773
|
var readSessionMarker = (file) => {
|
|
16695
16774
|
try {
|
|
16696
|
-
const value = JSON.parse(
|
|
16775
|
+
const value = JSON.parse(fs15.readFileSync(file, "utf8"));
|
|
16697
16776
|
return { nudged: list2(value.nudged), loaded: list2(value.loaded), raw: list2(value.raw) };
|
|
16698
16777
|
} catch {
|
|
16699
16778
|
return { nudged: [], loaded: [], raw: [] };
|
|
@@ -16701,8 +16780,8 @@ var readSessionMarker = (file) => {
|
|
|
16701
16780
|
};
|
|
16702
16781
|
var writeSessionMarker = (file, marker) => {
|
|
16703
16782
|
try {
|
|
16704
|
-
|
|
16705
|
-
|
|
16783
|
+
fs15.mkdirSync(path18.dirname(file), { recursive: true });
|
|
16784
|
+
fs15.writeFileSync(file, JSON.stringify(marker));
|
|
16706
16785
|
} catch {}
|
|
16707
16786
|
};
|
|
16708
16787
|
|
|
@@ -17199,14 +17278,14 @@ var GIT_CONFIG_ENV = /^GIT_(?:CONFIG\w*|DIR|COMMON_DIR|WORK_TREE)$/;
|
|
|
17199
17278
|
var ASSIGNMENT = /^([A-Za-z_]\w*)=([\s\S]*)$/;
|
|
17200
17279
|
var MAX_DEPTH = 4;
|
|
17201
17280
|
var MAX_EXPANSIONS = 16;
|
|
17202
|
-
var isAbsolute = (value) =>
|
|
17281
|
+
var isAbsolute = (value) => path19.isAbsolute(value) || /^[A-Za-z]:[\\/]/.test(value) || value.startsWith("\\\\");
|
|
17203
17282
|
var HERE = /^(?:\$PWD|\$\{PWD\}|\$\(\s*pwd\s*\)|`pwd`|\$\(\s*git\s+rev-parse\s+--show-toplevel\s*\))(?=$|[\\/])/;
|
|
17204
17283
|
var joinDir = (base, raw) => {
|
|
17205
17284
|
const next = raw.replace(HERE, ".");
|
|
17206
17285
|
if (base === undefined || /[$`*?]/.test(next) || next === "-")
|
|
17207
17286
|
return;
|
|
17208
|
-
const expanded = next === "~" || next.startsWith("~/") ?
|
|
17209
|
-
return base === null || isAbsolute(expanded) ? expanded :
|
|
17287
|
+
const expanded = next === "~" || next.startsWith("~/") ? path19.join(os4.homedir(), next.slice(1)) : next;
|
|
17288
|
+
return base === null || isAbsolute(expanded) ? expanded : path19.join(base, expanded);
|
|
17210
17289
|
};
|
|
17211
17290
|
var rebase = (base, inner) => inner === null ? base : inner === undefined ? undefined : joinDir(base, inner);
|
|
17212
17291
|
var cdTarget = (words) => {
|
|
@@ -18018,7 +18097,7 @@ var repoAt = (dir) => {
|
|
|
18018
18097
|
return { location, dir, branch: resolveTaskKey(dir, location).branch };
|
|
18019
18098
|
};
|
|
18020
18099
|
var isWorkitWorkspace = (repo) => {
|
|
18021
|
-
if (
|
|
18100
|
+
if (fs16.existsSync(repo.location.dir))
|
|
18022
18101
|
return true;
|
|
18023
18102
|
try {
|
|
18024
18103
|
return resolveRuntimeWorkspaceVcs(repo.location.top ?? repo.dir) !== null;
|
|
@@ -18039,17 +18118,17 @@ var headSha2 = (repo) => {
|
|
|
18039
18118
|
if (!git || git.reftable)
|
|
18040
18119
|
return null;
|
|
18041
18120
|
try {
|
|
18042
|
-
const head =
|
|
18121
|
+
const head = fs16.readFileSync(path19.join(git.gitDir, "HEAD"), "utf8").trim();
|
|
18043
18122
|
if (/^[0-9a-f]{40,64}$/.test(head))
|
|
18044
18123
|
return head;
|
|
18045
18124
|
const ref = /^ref: (refs\/.+)$/.exec(head)?.[1];
|
|
18046
18125
|
if (!ref)
|
|
18047
18126
|
return null;
|
|
18048
|
-
const common =
|
|
18127
|
+
const common = path19.dirname(repo.location.dir);
|
|
18049
18128
|
try {
|
|
18050
|
-
return
|
|
18129
|
+
return fs16.readFileSync(path19.join(common, ref), "utf8").trim() || null;
|
|
18051
18130
|
} catch {}
|
|
18052
|
-
const packed =
|
|
18131
|
+
const packed = fs16.readFileSync(path19.join(common, "packed-refs"), "utf8");
|
|
18053
18132
|
return new RegExp(`^([0-9a-f]{40,64}) ${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`, "m").exec(packed)?.[1] ?? null;
|
|
18054
18133
|
} catch {
|
|
18055
18134
|
return null;
|
|
@@ -18137,8 +18216,8 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
|
18137
18216
|
const sub = invocation.args[0];
|
|
18138
18217
|
if (invocation.tool !== "git" || invocation.dir === undefined || !sub || sub.startsWith("-") || GIT_COMMANDS.has(sub) || depth >= MAX_DEPTH)
|
|
18139
18218
|
return [invocation];
|
|
18140
|
-
const dir =
|
|
18141
|
-
if (!
|
|
18219
|
+
const dir = path19.resolve(root, invocation.dir ?? ".");
|
|
18220
|
+
if (!fs16.existsSync(dir))
|
|
18142
18221
|
return [invocation];
|
|
18143
18222
|
const config = gitConfig(dir, invocation, cache);
|
|
18144
18223
|
const alias = configValue(config, `alias.${sub.toLowerCase()}`);
|
|
@@ -18160,11 +18239,11 @@ var expandGitAliases = (root, invocation, cache = new Map, depth = 0) => {
|
|
|
18160
18239
|
var normalizedUrl = (url, dir) => {
|
|
18161
18240
|
const trimmed = url.trim();
|
|
18162
18241
|
if (/^file:\/\//i.test(trimmed))
|
|
18163
|
-
return
|
|
18242
|
+
return path19.resolve(dir, trimmed.slice(7)).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18164
18243
|
const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed);
|
|
18165
18244
|
const scp = !scheme && /^(?:[^@/\\]+@)?[^/\\:]{2,}:/.test(trimmed);
|
|
18166
18245
|
if (!scheme && !scp)
|
|
18167
|
-
return
|
|
18246
|
+
return path19.resolve(dir, trimmed).replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18168
18247
|
const value = scheme ? trimmed.slice(scheme[0].length).replace(/^[^@/]*@/, "").replace(/^([^/:]+):\d+(?=\/)/, "$1") : trimmed.replace(/^[^@/]*@/, "").replace(":", "/");
|
|
18169
18248
|
return value.toLowerCase().replace(/\/{2,}/g, "/").replace(/^www\./, "").replace(/\/+$/, "").replace(/\.git$/, "");
|
|
18170
18249
|
};
|
|
@@ -18388,7 +18467,7 @@ var actionsIn = (cwd, command, dialect, cache = new Map) => {
|
|
|
18388
18467
|
const out = [];
|
|
18389
18468
|
const repos = new Map;
|
|
18390
18469
|
const repoFor = (relative) => {
|
|
18391
|
-
const dir =
|
|
18470
|
+
const dir = path19.resolve(cwd, relative ?? ".");
|
|
18392
18471
|
if (!repos.has(dir)) {
|
|
18393
18472
|
const repo = repoAt(dir);
|
|
18394
18473
|
repos.set(dir, repo && isWorkitWorkspace(repo) ? repo : null);
|
|
@@ -18473,8 +18552,8 @@ var analysisDenial = (error) => ({
|
|
|
18473
18552
|
unblock: SPLIT_IT
|
|
18474
18553
|
});
|
|
18475
18554
|
var MARKER_TTL_SECONDS = 3600;
|
|
18476
|
-
var markerFile = (repo, session, key) =>
|
|
18477
|
-
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${
|
|
18555
|
+
var markerFile = (repo, session, key) => path19.join(repo.location.dir, "hooks", `commit-${createHash14("sha256").update(`${session}\x00${key}`).digest("hex").slice(0, 32)}.json`);
|
|
18556
|
+
var callKey = (toolUseId, command) => toolUseId ?? `cmd:${createHash14("sha256").update(command).digest("hex")}`;
|
|
18478
18557
|
function noteRawCommit(input, command, key) {
|
|
18479
18558
|
try {
|
|
18480
18559
|
if (!input.session.id || !/\bcommit\b/.test(command))
|
|
@@ -18484,8 +18563,8 @@ function noteRawCommit(input, command, key) {
|
|
|
18484
18563
|
if (action.kind !== "commit")
|
|
18485
18564
|
continue;
|
|
18486
18565
|
const file = markerFile(repo, input.session.id, key);
|
|
18487
|
-
|
|
18488
|
-
|
|
18566
|
+
fs16.mkdirSync(path19.dirname(file), { recursive: true });
|
|
18567
|
+
fs16.writeFileSync(file, `${JSON.stringify({ head: headSha2(repo), at })}
|
|
18489
18568
|
`);
|
|
18490
18569
|
}
|
|
18491
18570
|
} catch {}
|
|
@@ -18508,11 +18587,11 @@ var headCommit = (dir) => {
|
|
|
18508
18587
|
var settle2 = (input, repo, file) => {
|
|
18509
18588
|
let marker;
|
|
18510
18589
|
try {
|
|
18511
|
-
marker = JSON.parse(
|
|
18590
|
+
marker = JSON.parse(fs16.readFileSync(file, "utf8"));
|
|
18512
18591
|
} catch {
|
|
18513
18592
|
return;
|
|
18514
18593
|
}
|
|
18515
|
-
|
|
18594
|
+
fs16.rmSync(file, { force: true });
|
|
18516
18595
|
const session = input.session.id;
|
|
18517
18596
|
const now = Date.now() / 1000;
|
|
18518
18597
|
if (typeof marker.at !== "number" || now - marker.at > MARKER_TTL_SECONDS)
|
|
@@ -18703,7 +18782,7 @@ var judgedDir = (root, dir) => {
|
|
|
18703
18782
|
return null;
|
|
18704
18783
|
if (dir === null)
|
|
18705
18784
|
return root;
|
|
18706
|
-
const resolved =
|
|
18785
|
+
const resolved = path20.resolve(root, dir);
|
|
18707
18786
|
return existsSync6(resolved) && inWorkitWorkspace(resolved) ? resolved : null;
|
|
18708
18787
|
};
|
|
18709
18788
|
var shellBranchPolicyViolation = (root, command, dialect = "posix") => {
|
|
@@ -18939,7 +19018,7 @@ var judgeInputSummary = (raw) => {
|
|
|
18939
19018
|
|
|
18940
19019
|
// packages/workit-core/src/autonomy.ts
|
|
18941
19020
|
import os5 from "node:os";
|
|
18942
|
-
import
|
|
19021
|
+
import path21 from "node:path";
|
|
18943
19022
|
|
|
18944
19023
|
// packages/workit-core/src/core/safe-write.ts
|
|
18945
19024
|
import {
|
|
@@ -18973,10 +19052,10 @@ var accountHome = () => {
|
|
|
18973
19052
|
}
|
|
18974
19053
|
};
|
|
18975
19054
|
var grantsHome = { resolve: accountHome };
|
|
18976
|
-
var grantsDir = () =>
|
|
19055
|
+
var grantsDir = () => path21.join(grantsHome.resolve(), ".config", "workit");
|
|
18977
19056
|
var grantsOverride = () => {
|
|
18978
|
-
const configured =
|
|
18979
|
-
return configured ===
|
|
19057
|
+
const configured = path21.resolve(resolveConfigDir());
|
|
19058
|
+
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`;
|
|
18980
19059
|
};
|
|
18981
19060
|
var GRANT_KINDS = ["push", "pr", "merge", "release", "rerun"];
|
|
18982
19061
|
var DEFAULT_GRANTS = Object.freeze({
|
|
@@ -20779,7 +20858,7 @@ class WorkitCore {
|
|
|
20779
20858
|
// packages/workit-core/src/core/repo-context.ts
|
|
20780
20859
|
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
20781
20860
|
import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
20782
|
-
import
|
|
20861
|
+
import path22 from "node:path";
|
|
20783
20862
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
20784
20863
|
try {
|
|
20785
20864
|
gitRevisionParts(value);
|
|
@@ -20913,7 +20992,7 @@ var findPrTemplate = (cwd) => {
|
|
|
20913
20992
|
]) {
|
|
20914
20993
|
const parts = rel.split("/");
|
|
20915
20994
|
const base = parts[parts.length - 1];
|
|
20916
|
-
const dir = parts.length > 1 ?
|
|
20995
|
+
const dir = parts.length > 1 ? path22.join(cwd, ...parts.slice(0, -1)) : cwd;
|
|
20917
20996
|
const actual = probeCaseInsensitive(dir, base);
|
|
20918
20997
|
if (actual)
|
|
20919
20998
|
return [...parts.slice(0, -1), actual].join("/");
|
|
@@ -20944,7 +21023,7 @@ var diffStatForRange = (cwd, range) => {
|
|
|
20944
21023
|
return runGit(cwd, ["diff", "--stat", "--"]).stdout;
|
|
20945
21024
|
};
|
|
20946
21025
|
var packageScripts = (cwd, keys) => {
|
|
20947
|
-
const pkgPath =
|
|
21026
|
+
const pkgPath = path22.join(cwd, "package.json");
|
|
20948
21027
|
if (!existsSync7(pkgPath))
|
|
20949
21028
|
return [];
|
|
20950
21029
|
try {
|
|
@@ -20970,9 +21049,9 @@ var documentationFiles = (cwd) => {
|
|
|
20970
21049
|
if (entry.isDirectory()) {
|
|
20971
21050
|
if (excluded.has(entry.name))
|
|
20972
21051
|
continue;
|
|
20973
|
-
walk(
|
|
21052
|
+
walk(path22.join(dir, entry.name), depth + 1);
|
|
20974
21053
|
} else if (entry.isFile() && (entry.name === "README.md" || entry.name.endsWith(".md"))) {
|
|
20975
|
-
matches.push("./" +
|
|
21054
|
+
matches.push("./" + path22.relative(cwd, path22.join(dir, entry.name)).replaceAll("\\", "/"));
|
|
20976
21055
|
}
|
|
20977
21056
|
}
|
|
20978
21057
|
};
|
|
@@ -20988,7 +21067,7 @@ var readTrimmed2 = (file, maxLines) => {
|
|
|
20988
21067
|
`);
|
|
20989
21068
|
};
|
|
20990
21069
|
function prReadyContext(root, range) {
|
|
20991
|
-
const cwd =
|
|
21070
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
20992
21071
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
20993
21072
|
return invalidRange(cwd);
|
|
20994
21073
|
let stdout = "";
|
|
@@ -21046,7 +21125,7 @@ ${status.stderr}` : "");
|
|
|
21046
21125
|
stdout += `template_path: ${template}
|
|
21047
21126
|
|
|
21048
21127
|
`;
|
|
21049
|
-
stdout += readTrimmed2(
|
|
21128
|
+
stdout += readTrimmed2(path22.join(cwd, template), 220);
|
|
21050
21129
|
} else {
|
|
21051
21130
|
stdout += `template_path: none
|
|
21052
21131
|
|
|
@@ -21056,7 +21135,7 @@ ${status.stderr}` : "");
|
|
|
21056
21135
|
stdout += `
|
|
21057
21136
|
`;
|
|
21058
21137
|
stdout += printSection("Recent Validation Signals");
|
|
21059
|
-
if (existsSync7(
|
|
21138
|
+
if (existsSync7(path22.join(cwd, "package.json"))) {
|
|
21060
21139
|
stdout += `package.json detected. Common scripts:
|
|
21061
21140
|
`;
|
|
21062
21141
|
const found = packageScripts(cwd, ["lint", "format:check", "test", "build"]);
|
|
@@ -21065,7 +21144,7 @@ ${status.stderr}` : "");
|
|
|
21065
21144
|
`) + `
|
|
21066
21145
|
`;
|
|
21067
21146
|
}
|
|
21068
|
-
if (existsSync7(
|
|
21147
|
+
if (existsSync7(path22.join(cwd, "Cargo.toml")) || existsSync7(path22.join(cwd, "src-tauri/Cargo.toml"))) {
|
|
21069
21148
|
stdout += `Rust project detected.
|
|
21070
21149
|
`;
|
|
21071
21150
|
}
|
|
@@ -21098,7 +21177,7 @@ var CHANGELOG_RULES = `- Use an [Unreleased] section.
|
|
|
21098
21177
|
- Apply with the host-native editor, preserving the repository changelog conventions.
|
|
21099
21178
|
- If Unreleased already has duplicate category headings, normalize_only first.`;
|
|
21100
21179
|
function changelogContext(root, range) {
|
|
21101
|
-
const cwd =
|
|
21180
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21102
21181
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
21103
21182
|
return invalidRange(cwd);
|
|
21104
21183
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -21116,7 +21195,7 @@ function changelogContext(root, range) {
|
|
|
21116
21195
|
stdout += CHANGELOG_RULES + `
|
|
21117
21196
|
`;
|
|
21118
21197
|
stdout += printSection("Existing CHANGELOG.md");
|
|
21119
|
-
const changelogPath =
|
|
21198
|
+
const changelogPath = path22.join(cwd, "CHANGELOG.md");
|
|
21120
21199
|
if (existsSync7(changelogPath)) {
|
|
21121
21200
|
stdout += readTrimmed2(changelogPath, 260) + `
|
|
21122
21201
|
`;
|
|
@@ -21136,7 +21215,7 @@ function changelogContext(root, range) {
|
|
|
21136
21215
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
21137
21216
|
}
|
|
21138
21217
|
function docsRefreshContext(root, range) {
|
|
21139
|
-
const cwd =
|
|
21218
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21140
21219
|
if (range !== undefined && !isResolvableContextRange(cwd, range))
|
|
21141
21220
|
return invalidRange(cwd);
|
|
21142
21221
|
const resolvedRange = rangeArgOrDefault(range, cwd);
|
|
@@ -21158,7 +21237,7 @@ function docsRefreshContext(root, range) {
|
|
|
21158
21237
|
`) + `
|
|
21159
21238
|
`;
|
|
21160
21239
|
stdout += printSection("README Preview");
|
|
21161
|
-
const readme =
|
|
21240
|
+
const readme = path22.join(cwd, "README.md");
|
|
21162
21241
|
if (existsSync7(readme)) {
|
|
21163
21242
|
stdout += readTrimmed2(readme, 220) + `
|
|
21164
21243
|
`;
|
|
@@ -21167,7 +21246,7 @@ function docsRefreshContext(root, range) {
|
|
|
21167
21246
|
`;
|
|
21168
21247
|
}
|
|
21169
21248
|
stdout += printSection("Package Scripts");
|
|
21170
|
-
const pkgPath =
|
|
21249
|
+
const pkgPath = path22.join(cwd, "package.json");
|
|
21171
21250
|
if (existsSync7(pkgPath)) {
|
|
21172
21251
|
try {
|
|
21173
21252
|
const pkg = JSON.parse(readFileSync5(pkgPath, "utf8"));
|
|
@@ -21181,7 +21260,7 @@ function docsRefreshContext(root, range) {
|
|
|
21181
21260
|
return { stdout, stderr: "", exitCode: 0, cwd };
|
|
21182
21261
|
}
|
|
21183
21262
|
function releaseNotesContext(root, rangeOrTag) {
|
|
21184
|
-
const cwd =
|
|
21263
|
+
const cwd = path22.resolve(repoRoot(root));
|
|
21185
21264
|
if (!rangeOrTag) {
|
|
21186
21265
|
return { stdout: "", stderr: `ERROR: release tag or range required
|
|
21187
21266
|
`, exitCode: 1, cwd };
|
|
@@ -21219,7 +21298,7 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
21219
21298
|
`;
|
|
21220
21299
|
stdout += printSection("Existing Release Files");
|
|
21221
21300
|
for (const rel of ["CHANGELOG.md", "RELEASE_NOTES.md", ".github/releases.md"]) {
|
|
21222
|
-
if (existsSync7(
|
|
21301
|
+
if (existsSync7(path22.join(cwd, rel)))
|
|
21223
21302
|
stdout += rel + `
|
|
21224
21303
|
`;
|
|
21225
21304
|
}
|
|
@@ -21250,8 +21329,8 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
21250
21329
|
import { spawnSync as spawnSync15 } from "node:child_process";
|
|
21251
21330
|
|
|
21252
21331
|
// packages/workit-core/src/core/pr-create.ts
|
|
21253
|
-
import
|
|
21254
|
-
import
|
|
21332
|
+
import fs17 from "node:fs";
|
|
21333
|
+
import path23 from "node:path";
|
|
21255
21334
|
import { spawnSync as spawnSync14 } from "node:child_process";
|
|
21256
21335
|
import { pathToFileURL } from "node:url";
|
|
21257
21336
|
// packages/workit-core/src/forge/pr-body.ts
|
|
@@ -21263,13 +21342,13 @@ function parseGhIssue(value) {
|
|
|
21263
21342
|
// packages/workit-core/src/core/pr-create.ts
|
|
21264
21343
|
function whichOnPath(tool) {
|
|
21265
21344
|
const names = process.platform === "win32" ? [tool, `${tool}.exe`, `${tool}.cmd`] : [tool];
|
|
21266
|
-
for (const dir of (process.env.PATH ?? "").split(
|
|
21345
|
+
for (const dir of (process.env.PATH ?? "").split(path23.delimiter)) {
|
|
21267
21346
|
if (!dir)
|
|
21268
21347
|
continue;
|
|
21269
21348
|
for (const name of names) {
|
|
21270
|
-
const candidate =
|
|
21349
|
+
const candidate = path23.join(dir, name);
|
|
21271
21350
|
try {
|
|
21272
|
-
|
|
21351
|
+
fs17.accessSync(candidate, fs17.constants.X_OK);
|
|
21273
21352
|
return candidate;
|
|
21274
21353
|
} catch {}
|
|
21275
21354
|
}
|
|
@@ -21289,7 +21368,7 @@ var pushRemote = (cwd) => {
|
|
|
21289
21368
|
};
|
|
21290
21369
|
var safePushUrl = (remote) => {
|
|
21291
21370
|
const raw = remote.trim();
|
|
21292
|
-
if (
|
|
21371
|
+
if (path23.isAbsolute(raw))
|
|
21293
21372
|
return pathToFileURL(raw).href;
|
|
21294
21373
|
if (!raw.includes("://")) {
|
|
21295
21374
|
const scp = /^(?:([^@\s]+)@)?([^:]+):(.+)$/u.exec(raw);
|
|
@@ -21420,8 +21499,8 @@ var fetchGitLabIssueBody = async (ref, root, deps = {}) => {
|
|
|
21420
21499
|
};
|
|
21421
21500
|
|
|
21422
21501
|
// packages/workit-core/src/core/youtrack.ts
|
|
21423
|
-
import
|
|
21424
|
-
import
|
|
21502
|
+
import fs18 from "node:fs";
|
|
21503
|
+
import path24 from "node:path";
|
|
21425
21504
|
|
|
21426
21505
|
// packages/workit-core/src/core/templates.ts
|
|
21427
21506
|
var repoRoot2 = assetRoot();
|
|
@@ -21434,22 +21513,22 @@ var resolveWorkspaceRoot = (explicit) => explicit || process.cwd();
|
|
|
21434
21513
|
// packages/workit-core/src/core/youtrack.ts
|
|
21435
21514
|
var ISSUE_RE = /^[A-Z]+-\d+$/;
|
|
21436
21515
|
var TOKEN_PLACEHOLDER = "YOUR_TOKEN_HERE";
|
|
21437
|
-
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
21438
|
-
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ??
|
|
21516
|
+
var youTrackConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(configDir(), "youtrack.json");
|
|
21517
|
+
var youTrackReadOnlyConfigPath = () => process.env.WORKFLOW_YOUTRACK_CONFIG ?? path24.join(resolveConfigDir(), "youtrack.json");
|
|
21439
21518
|
var youTrackTokenModeOk = (p) => {
|
|
21440
21519
|
if (process.platform === "win32")
|
|
21441
21520
|
return true;
|
|
21442
|
-
const mode =
|
|
21521
|
+
const mode = fs18.statSync(p).mode & 511;
|
|
21443
21522
|
return mode === 384;
|
|
21444
21523
|
};
|
|
21445
21524
|
function readYouTrackConfig(required) {
|
|
21446
21525
|
const cfgPath = youTrackConfigPath();
|
|
21447
|
-
if (!
|
|
21526
|
+
if (!fs18.existsSync(cfgPath)) {
|
|
21448
21527
|
return required ? { error: "ERROR: missing youtrack.json", path: cfgPath } : { config: {}, path: cfgPath };
|
|
21449
21528
|
}
|
|
21450
21529
|
let parsed;
|
|
21451
21530
|
try {
|
|
21452
|
-
parsed = JSON.parse(
|
|
21531
|
+
parsed = JSON.parse(fs18.readFileSync(cfgPath, "utf8"));
|
|
21453
21532
|
} catch {
|
|
21454
21533
|
return { error: `${cfgPath} is not valid JSON`, path: cfgPath };
|
|
21455
21534
|
}
|
|
@@ -21460,11 +21539,11 @@ function readYouTrackConfig(required) {
|
|
|
21460
21539
|
}
|
|
21461
21540
|
var readYouTrackContextConfig = () => {
|
|
21462
21541
|
const cfgPath = youTrackReadOnlyConfigPath();
|
|
21463
|
-
if (!
|
|
21542
|
+
if (!fs18.existsSync(cfgPath))
|
|
21464
21543
|
return { data: {} };
|
|
21465
21544
|
let parsed;
|
|
21466
21545
|
try {
|
|
21467
|
-
parsed = JSON.parse(
|
|
21546
|
+
parsed = JSON.parse(fs18.readFileSync(cfgPath, "utf8"));
|
|
21468
21547
|
} catch {
|
|
21469
21548
|
return { error: "YouTrack configuration is unavailable" };
|
|
21470
21549
|
}
|
|
@@ -21503,12 +21582,12 @@ var youTrackToken = () => {
|
|
|
21503
21582
|
if ("error" in loaded)
|
|
21504
21583
|
return loaded;
|
|
21505
21584
|
const tokenFile = String(loaded.config.tokenFile ?? "");
|
|
21506
|
-
const tokenPath = tokenFile ?
|
|
21507
|
-
if (!tokenPath || !
|
|
21585
|
+
const tokenPath = tokenFile ? path24.isAbsolute(tokenFile) ? path24.resolve(tokenFile) : path24.resolve(process.cwd(), tokenFile) : "";
|
|
21586
|
+
if (!tokenPath || !fs18.existsSync(tokenPath))
|
|
21508
21587
|
return { error: "missing youtrack.token" };
|
|
21509
21588
|
if (!youTrackTokenModeOk(tokenPath))
|
|
21510
21589
|
return { error: "youtrack.token mode must be 0600" };
|
|
21511
|
-
const token =
|
|
21590
|
+
const token = fs18.readFileSync(tokenPath, "utf8").trim();
|
|
21512
21591
|
if (!token)
|
|
21513
21592
|
return { error: "empty token file" };
|
|
21514
21593
|
if (token === TOKEN_PLACEHOLDER || token.startsWith(TOKEN_PLACEHOLDER)) {
|
|
@@ -21554,7 +21633,7 @@ function youTrackTokenCreateUrl() {
|
|
|
21554
21633
|
const desc = String(defaults.description ?? "OpenCode workit — /wk-issue-update and /wk-meetings");
|
|
21555
21634
|
const scopes = Array.isArray(defaults.scopes) ? defaults.scopes : ["YouTrack"];
|
|
21556
21635
|
const base = String(config.baseUrl ?? "").replace(/\/+$/, "");
|
|
21557
|
-
const tokenFile = String(config.tokenFile ??
|
|
21636
|
+
const tokenFile = String(config.tokenFile ?? path24.join(path24.dirname(loaded.path), "youtrack.token"));
|
|
21558
21637
|
const tab = String(defaults.profileTab ?? "account-security");
|
|
21559
21638
|
const createUrl = base ? `${base}/users/me?${new URLSearchParams({ tab })}` : null;
|
|
21560
21639
|
const docsUrl = "https://www.jetbrains.com/help/youtrack/cloud/manage-permanent-token.html";
|
|
@@ -21563,7 +21642,7 @@ function youTrackTokenCreateUrl() {
|
|
|
21563
21642
|
tokenName: name,
|
|
21564
21643
|
tokenDescription: desc,
|
|
21565
21644
|
scopes,
|
|
21566
|
-
tokenFile:
|
|
21645
|
+
tokenFile: path24.resolve(tokenFile),
|
|
21567
21646
|
createUrl,
|
|
21568
21647
|
docsUrl,
|
|
21569
21648
|
prefillSupported: false,
|
|
@@ -21609,9 +21688,9 @@ function resolveYouTrackFromPaths(spec_path, plan_path, workspace_root) {
|
|
|
21609
21688
|
} catch {
|
|
21610
21689
|
continue;
|
|
21611
21690
|
}
|
|
21612
|
-
if (!
|
|
21691
|
+
if (!fs18.existsSync(full))
|
|
21613
21692
|
continue;
|
|
21614
|
-
const text =
|
|
21693
|
+
const text = fs18.readFileSync(full, "utf8");
|
|
21615
21694
|
const m = text.match(/^\*\*YouTrack:\*\*\s*`?([A-Z]+-\d+)`?/m);
|
|
21616
21695
|
if (m)
|
|
21617
21696
|
return m[1];
|
|
@@ -21903,15 +21982,15 @@ function resolveGitRevision(root, value) {
|
|
|
21903
21982
|
}
|
|
21904
21983
|
function resolveInside(root, candidate) {
|
|
21905
21984
|
const base = realpathSync5(root);
|
|
21906
|
-
const target =
|
|
21907
|
-
if (target !== base && !target.startsWith(base +
|
|
21985
|
+
const target = path25.resolve(base, candidate);
|
|
21986
|
+
if (target !== base && !target.startsWith(base + path25.sep)) {
|
|
21908
21987
|
throw new Error("path must stay inside repository root");
|
|
21909
21988
|
}
|
|
21910
21989
|
let ancestor = target;
|
|
21911
21990
|
while (!existsSync8(ancestor))
|
|
21912
|
-
ancestor =
|
|
21991
|
+
ancestor = path25.dirname(ancestor);
|
|
21913
21992
|
const canonicalAncestor = realpathSync5(ancestor);
|
|
21914
|
-
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base +
|
|
21993
|
+
if (canonicalAncestor !== base && !canonicalAncestor.startsWith(base + path25.sep)) {
|
|
21915
21994
|
throw new Error("path must stay inside repository root");
|
|
21916
21995
|
}
|
|
21917
21996
|
return target;
|
|
@@ -21955,7 +22034,7 @@ var capabilitiesFor = (descriptor, observed = {}) => descriptor.capabilities.map
|
|
|
21955
22034
|
};
|
|
21956
22035
|
});
|
|
21957
22036
|
// packages/workit-core/src/hooks/context.ts
|
|
21958
|
-
import
|
|
22037
|
+
import path26 from "node:path";
|
|
21959
22038
|
var MIGRATION_PENDING_NOTE = "workit migration pending — run `workit task status`";
|
|
21960
22039
|
var migrationPending = (result) => !result.ok && result.code === "needs_input" && (result.error ?? "").startsWith(MIGRATION_PENDING);
|
|
21961
22040
|
var boundTo = (entry, session) => entry.sessions.some((item) => item.host === session.host && item.handle === session.handle);
|
|
@@ -22040,7 +22119,7 @@ function entryCompactContext(store, entry, session, context) {
|
|
|
22040
22119
|
return null;
|
|
22041
22120
|
const freshness = { mode: "signal", current: () => recentSignal(store.root) };
|
|
22042
22121
|
const observed = task?.data.evidence.some(isObservedCheck) ?? false;
|
|
22043
|
-
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [
|
|
22122
|
+
const files = (task?.data.decisions ?? []).flatMap((decision) => decision.data.binding.contentRefs.flatMap((ref) => ref.kind === "file" ? [path26.resolve(store.root, ref.path)] : []));
|
|
22044
22123
|
const observedFiles = filesKey(files);
|
|
22045
22124
|
const compact = new WorkitCore(store, context).compactContext(entry?.id ?? null, freshness, origin && { origin: origin.origin, taskId: origin.entry.id });
|
|
22046
22125
|
if (!compact.ok || !compact.data)
|
|
@@ -22071,13 +22150,13 @@ var shellPolicy = (cwd, command, dialect = "posix") => {
|
|
|
22071
22150
|
return policy && !policy.ok ? { kind: "deny", reason: `branch_policy_denied: ${policy.error}`, unblock: null } : { kind: "none" };
|
|
22072
22151
|
};
|
|
22073
22152
|
// packages/workit-core/src/core/heavy-rules.ts
|
|
22074
|
-
import
|
|
22153
|
+
import fs19 from "node:fs";
|
|
22075
22154
|
import os6 from "node:os";
|
|
22076
|
-
import
|
|
22155
|
+
import path27 from "node:path";
|
|
22077
22156
|
var EMPTY = () => ({ deny: [], allow: [] });
|
|
22078
22157
|
var readText2 = (file) => {
|
|
22079
22158
|
try {
|
|
22080
|
-
return
|
|
22159
|
+
return fs19.readFileSync(file, "utf8");
|
|
22081
22160
|
} catch (error) {
|
|
22082
22161
|
if (error.code === "ENOENT")
|
|
22083
22162
|
return null;
|
|
@@ -22114,19 +22193,19 @@ function parseJsonc(text) {
|
|
|
22114
22193
|
return JSON.parse(out.replace(/,(\s*[}\]])/gu, "$1"));
|
|
22115
22194
|
}
|
|
22116
22195
|
function gitTop(cwd) {
|
|
22117
|
-
for (let dir =
|
|
22118
|
-
if (
|
|
22196
|
+
for (let dir = path27.resolve(cwd);; dir = path27.dirname(dir)) {
|
|
22197
|
+
if (fs19.existsSync(path27.join(dir, ".git")))
|
|
22119
22198
|
return dir;
|
|
22120
|
-
if (
|
|
22199
|
+
if (path27.dirname(dir) === dir)
|
|
22121
22200
|
return null;
|
|
22122
22201
|
}
|
|
22123
22202
|
}
|
|
22124
22203
|
var projectDirs = (cwd) => {
|
|
22125
22204
|
const top = gitTop(cwd);
|
|
22126
22205
|
const dirs = [];
|
|
22127
|
-
for (let dir =
|
|
22206
|
+
for (let dir = path27.resolve(cwd);; dir = path27.dirname(dir)) {
|
|
22128
22207
|
dirs.push(dir);
|
|
22129
|
-
if (!top || dir === top ||
|
|
22208
|
+
if (!top || dir === top || path27.dirname(dir) === dir)
|
|
22130
22209
|
return dirs;
|
|
22131
22210
|
}
|
|
22132
22211
|
};
|
|
@@ -22138,12 +22217,12 @@ var CLAUDE_MANAGED = {
|
|
|
22138
22217
|
};
|
|
22139
22218
|
function claudeSettingsFiles(cwd, env, platform = process.platform) {
|
|
22140
22219
|
const project = env.CLAUDE_PROJECT_DIR || gitTop(cwd) || cwd;
|
|
22141
|
-
const user = env.CLAUDE_CONFIG_DIR ||
|
|
22220
|
+
const user = env.CLAUDE_CONFIG_DIR || path27.join(homeOf(env), ".claude");
|
|
22142
22221
|
return [
|
|
22143
22222
|
...CLAUDE_MANAGED[platform] ? [CLAUDE_MANAGED[platform]] : [],
|
|
22144
|
-
|
|
22145
|
-
|
|
22146
|
-
|
|
22223
|
+
path27.join(user, "settings.json"),
|
|
22224
|
+
path27.join(project, ".claude", "settings.json"),
|
|
22225
|
+
path27.join(project, ".claude", "settings.local.json")
|
|
22147
22226
|
];
|
|
22148
22227
|
}
|
|
22149
22228
|
var bashPattern = (entry) => {
|
|
@@ -22233,10 +22312,10 @@ var opencodeConfig = (value, rules) => {
|
|
|
22233
22312
|
function opencodeRules(cwd, env = process.env) {
|
|
22234
22313
|
const rules = EMPTY();
|
|
22235
22314
|
try {
|
|
22236
|
-
const config = env.XDG_CONFIG_HOME ||
|
|
22315
|
+
const config = env.XDG_CONFIG_HOME || path27.join(homeOf(env), ".config");
|
|
22237
22316
|
const files = [
|
|
22238
|
-
...OPENCODE_NAMES.map((name) =>
|
|
22239
|
-
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [
|
|
22317
|
+
...OPENCODE_NAMES.map((name) => path27.join(config, "opencode", name)),
|
|
22318
|
+
...projectDirs(cwd).flatMap((dir) => OPENCODE_NAMES.flatMap((name) => [path27.join(dir, name), path27.join(dir, ".opencode", name)])),
|
|
22240
22319
|
...env.OPENCODE_CONFIG ? [env.OPENCODE_CONFIG] : []
|
|
22241
22320
|
];
|
|
22242
22321
|
for (const file of files) {
|
|
@@ -22280,19 +22359,19 @@ var codexRule = (body) => {
|
|
|
22280
22359
|
function codexRules(cwd, env = process.env) {
|
|
22281
22360
|
const rules = EMPTY();
|
|
22282
22361
|
try {
|
|
22283
|
-
const home = env.CODEX_HOME ||
|
|
22362
|
+
const home = env.CODEX_HOME || path27.join(homeOf(env), ".codex");
|
|
22284
22363
|
const top = gitTop(cwd) ?? cwd;
|
|
22285
|
-
for (const dir of [
|
|
22364
|
+
for (const dir of [path27.join(home, "rules"), path27.join(top, ".codex", "rules")]) {
|
|
22286
22365
|
let files;
|
|
22287
22366
|
try {
|
|
22288
|
-
files =
|
|
22367
|
+
files = fs19.readdirSync(dir).filter((name) => name.endsWith(".rules"));
|
|
22289
22368
|
} catch (error) {
|
|
22290
22369
|
if (error.code === "ENOENT")
|
|
22291
22370
|
continue;
|
|
22292
22371
|
return "unreadable";
|
|
22293
22372
|
}
|
|
22294
22373
|
for (const name of files) {
|
|
22295
|
-
const text = readText2(
|
|
22374
|
+
const text = readText2(path27.join(dir, name)) ?? "";
|
|
22296
22375
|
for (const part of text.split(/\bprefix_rule\s*\(/u).slice(1)) {
|
|
22297
22376
|
const rule = codexRule(part);
|
|
22298
22377
|
if (!rule)
|
|
@@ -22311,8 +22390,8 @@ function cursorRules(cwd, env = process.env) {
|
|
|
22311
22390
|
try {
|
|
22312
22391
|
const top = gitTop(cwd) ?? cwd;
|
|
22313
22392
|
for (const file of [
|
|
22314
|
-
|
|
22315
|
-
|
|
22393
|
+
path27.join(homeOf(env), ".cursor", "cli-config.json"),
|
|
22394
|
+
path27.join(top, ".cursor", "cli.json")
|
|
22316
22395
|
]) {
|
|
22317
22396
|
const text = readText2(file);
|
|
22318
22397
|
if (text === null)
|
|
@@ -22386,23 +22465,23 @@ function wrapAllowed(read, words, command, options = {}) {
|
|
|
22386
22465
|
}
|
|
22387
22466
|
|
|
22388
22467
|
// packages/workit-core/src/core/heavy.ts
|
|
22389
|
-
import
|
|
22468
|
+
import fs20 from "node:fs";
|
|
22390
22469
|
import os7 from "node:os";
|
|
22391
|
-
import
|
|
22470
|
+
import path28 from "node:path";
|
|
22392
22471
|
function stateDir(env, platform = process.platform) {
|
|
22393
22472
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
22394
22473
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
22395
22474
|
if (env.XDG_STATE_HOME)
|
|
22396
|
-
return
|
|
22475
|
+
return path28.join(env.XDG_STATE_HOME, "workit");
|
|
22397
22476
|
const home = env.HOME || os7.homedir();
|
|
22398
22477
|
if (platform === "darwin")
|
|
22399
|
-
return
|
|
22478
|
+
return path28.join(home, "Library", "Application Support", "workit");
|
|
22400
22479
|
if (platform === "win32")
|
|
22401
|
-
return
|
|
22402
|
-
return
|
|
22480
|
+
return path28.join(env.LOCALAPPDATA ?? path28.join(home, "AppData", "Local"), "workit");
|
|
22481
|
+
return path28.join(home, ".local", "state", "workit");
|
|
22403
22482
|
}
|
|
22404
22483
|
var HEAVY_COMMANDS_FILE = "heavy-commands.json";
|
|
22405
|
-
var heavyCommandsFile = (env) =>
|
|
22484
|
+
var heavyCommandsFile = (env) => path28.join(stateDir(env), HEAVY_COMMANDS_FILE);
|
|
22406
22485
|
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;
|
|
22407
22486
|
var INFO_FLAGS = new Set(["--version", "-v", "-V", "--help", "-h", "help", "version"]);
|
|
22408
22487
|
var WATCH_FLAG = /^(?:--watch(?:All)?(?:=.*)?|-w|--serve)$/u;
|
|
@@ -22665,7 +22744,7 @@ function parsePattern(pattern) {
|
|
|
22665
22744
|
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]));
|
|
22666
22745
|
var readJson = (file) => {
|
|
22667
22746
|
try {
|
|
22668
|
-
return JSON.parse(
|
|
22747
|
+
return JSON.parse(fs20.readFileSync(file, "utf8"));
|
|
22669
22748
|
} catch {
|
|
22670
22749
|
return;
|
|
22671
22750
|
}
|
|
@@ -22677,7 +22756,7 @@ function machinePatterns(env) {
|
|
|
22677
22756
|
return isRecord5(value) ? stringList(value.patterns) : [];
|
|
22678
22757
|
}
|
|
22679
22758
|
function repoPatterns(cwd) {
|
|
22680
|
-
return repoHeavyCommands(gitTop(cwd) ??
|
|
22759
|
+
return repoHeavyCommands(gitTop(cwd) ?? path28.resolve(cwd));
|
|
22681
22760
|
}
|
|
22682
22761
|
function heavyLines(lines, options) {
|
|
22683
22762
|
const found = [];
|
|
@@ -22755,12 +22834,12 @@ function heavyPlan(command, options) {
|
|
|
22755
22834
|
}
|
|
22756
22835
|
function workitOnPath2(env = process.env) {
|
|
22757
22836
|
const names = process.platform === "win32" ? ["workit.exe", "workit.cmd", "workit"] : ["workit"];
|
|
22758
|
-
for (const dir of (env.PATH ?? "").split(
|
|
22837
|
+
for (const dir of (env.PATH ?? "").split(path28.delimiter))
|
|
22759
22838
|
for (const name of names) {
|
|
22760
22839
|
if (!dir)
|
|
22761
22840
|
continue;
|
|
22762
22841
|
try {
|
|
22763
|
-
|
|
22842
|
+
fs20.accessSync(path28.join(dir, name), fs20.constants.X_OK);
|
|
22764
22843
|
return true;
|
|
22765
22844
|
} catch {}
|
|
22766
22845
|
}
|
|
@@ -22777,41 +22856,41 @@ function leaseRewrite(command) {
|
|
|
22777
22856
|
}
|
|
22778
22857
|
|
|
22779
22858
|
// packages/workit-core/src/core/heavy-words.ts
|
|
22780
|
-
import
|
|
22859
|
+
import fs21 from "node:fs";
|
|
22781
22860
|
import os8 from "node:os";
|
|
22782
|
-
import
|
|
22861
|
+
import path29 from "node:path";
|
|
22783
22862
|
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(" "));
|
|
22784
22863
|
var wordsOf = (command) => command.split(/[\s;&|()<>`'"]+/u).map((word) => (word.split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.(?:exe|cmd|bat)$/u, "")).filter(Boolean);
|
|
22785
22864
|
var stateDir2 = (env) => {
|
|
22786
22865
|
if (env.WORKFLOW_TOOLKIT_STATE)
|
|
22787
22866
|
return env.WORKFLOW_TOOLKIT_STATE;
|
|
22788
22867
|
if (env.XDG_STATE_HOME)
|
|
22789
|
-
return
|
|
22868
|
+
return path29.join(env.XDG_STATE_HOME, "workit");
|
|
22790
22869
|
const home = env.HOME || os8.homedir();
|
|
22791
22870
|
if (process.platform === "darwin")
|
|
22792
|
-
return
|
|
22871
|
+
return path29.join(home, "Library", "Application Support", "workit");
|
|
22793
22872
|
if (process.platform === "win32")
|
|
22794
|
-
return
|
|
22795
|
-
return
|
|
22873
|
+
return path29.join(env.LOCALAPPDATA ?? path29.join(home, "AppData", "Local"), "workit");
|
|
22874
|
+
return path29.join(home, ".local", "state", "workit");
|
|
22796
22875
|
};
|
|
22797
22876
|
var readJson2 = (file) => {
|
|
22798
22877
|
try {
|
|
22799
|
-
return JSON.parse(
|
|
22878
|
+
return JSON.parse(fs21.readFileSync(file, "utf8"));
|
|
22800
22879
|
} catch {
|
|
22801
22880
|
return;
|
|
22802
22881
|
}
|
|
22803
22882
|
};
|
|
22804
22883
|
var patternWords = (cwd, env) => {
|
|
22805
22884
|
const patterns = [];
|
|
22806
|
-
const machine = readJson2(
|
|
22885
|
+
const machine = readJson2(path29.join(stateDir2(env), "heavy-commands.json"));
|
|
22807
22886
|
if (Array.isArray(machine?.patterns))
|
|
22808
22887
|
patterns.push(...machine.patterns);
|
|
22809
|
-
for (let dir =
|
|
22810
|
-
if (
|
|
22888
|
+
for (let dir = path29.resolve(cwd);; dir = path29.dirname(dir)) {
|
|
22889
|
+
if (fs21.existsSync(path29.join(dir, ".git"))) {
|
|
22811
22890
|
patterns.push(...repoHeavyCommands(dir));
|
|
22812
22891
|
break;
|
|
22813
22892
|
}
|
|
22814
|
-
if (
|
|
22893
|
+
if (path29.dirname(dir) === dir)
|
|
22815
22894
|
break;
|
|
22816
22895
|
}
|
|
22817
22896
|
const words = new Set;
|
|
@@ -22872,14 +22951,14 @@ function heavyGate(cwd, command, options) {
|
|
|
22872
22951
|
// packages/workit-core/src/hooks/write-gate.ts
|
|
22873
22952
|
import { realpathSync as realpathSync6 } from "node:fs";
|
|
22874
22953
|
import os10 from "node:os";
|
|
22875
|
-
import
|
|
22954
|
+
import path31 from "node:path";
|
|
22876
22955
|
|
|
22877
22956
|
// packages/workit-core/src/core/live-session.ts
|
|
22878
22957
|
import { spawnSync as spawnSync17 } from "node:child_process";
|
|
22879
|
-
import { createHash as
|
|
22880
|
-
import
|
|
22958
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
22959
|
+
import fs22 from "node:fs";
|
|
22881
22960
|
import os9 from "node:os";
|
|
22882
|
-
import
|
|
22961
|
+
import path30 from "node:path";
|
|
22883
22962
|
var LIVE_SESSION_TTL_MS = 15 * 60000;
|
|
22884
22963
|
var HEARTBEAT_EVERY_MS = 30000;
|
|
22885
22964
|
var liveProbe = {
|
|
@@ -22900,9 +22979,9 @@ var processAlive = (pid) => {
|
|
|
22900
22979
|
var processInfo = (pid) => {
|
|
22901
22980
|
try {
|
|
22902
22981
|
if (liveProbe.platform === "linux") {
|
|
22903
|
-
const stat =
|
|
22982
|
+
const stat = fs22.readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
22904
22983
|
const ppid = Number(stat.slice(stat.lastIndexOf(")") + 2).split(" ")[1]);
|
|
22905
|
-
const command =
|
|
22984
|
+
const command = fs22.readFileSync(`/proc/${pid}/cmdline`, "utf8").replaceAll("\x00", " ");
|
|
22906
22985
|
return Number.isInteger(ppid) ? { ppid, command: command.trim() } : null;
|
|
22907
22986
|
}
|
|
22908
22987
|
if (liveProbe.platform === "win32")
|
|
@@ -22953,35 +23032,35 @@ var liveOwner = (input, transport, env = process.env) => {
|
|
|
22953
23032
|
};
|
|
22954
23033
|
};
|
|
22955
23034
|
var checkoutOf = (target) => {
|
|
22956
|
-
let dir =
|
|
22957
|
-
while (!
|
|
22958
|
-
dir =
|
|
22959
|
-
if (
|
|
22960
|
-
dir =
|
|
22961
|
-
const parts = dir.split(
|
|
23035
|
+
let dir = path30.resolve(target);
|
|
23036
|
+
while (!fs22.existsSync(dir) && path30.dirname(dir) !== dir)
|
|
23037
|
+
dir = path30.dirname(dir);
|
|
23038
|
+
if (fs22.existsSync(dir) && !fs22.statSync(dir).isDirectory())
|
|
23039
|
+
dir = path30.dirname(dir);
|
|
23040
|
+
const parts = dir.split(path30.sep);
|
|
22962
23041
|
const dotGit = parts.lastIndexOf(".git");
|
|
22963
23042
|
if (dotGit > 0)
|
|
22964
|
-
dir = parts.slice(0, dotGit).join(
|
|
23043
|
+
dir = parts.slice(0, dotGit).join(path30.sep) || path30.sep;
|
|
22965
23044
|
const location = resolveStore(dir);
|
|
22966
23045
|
if (location instanceof Error || !location.shared || !location.top)
|
|
22967
23046
|
return null;
|
|
22968
23047
|
let top = location.top;
|
|
22969
23048
|
try {
|
|
22970
|
-
top =
|
|
23049
|
+
top = fs22.realpathSync.native(top);
|
|
22971
23050
|
} catch {}
|
|
22972
23051
|
return top;
|
|
22973
23052
|
};
|
|
22974
|
-
var markerFile2 = (top) =>
|
|
23053
|
+
var markerFile2 = (top) => path30.join(resolveStateDir(), "live-sessions", `${createHash15("sha256").update(checkoutKey(top)).digest("hex").slice(0, 32)}.json`);
|
|
22975
23054
|
var checkoutKey = (top, platform = process.platform) => {
|
|
22976
|
-
let key =
|
|
23055
|
+
let key = path30.resolve(top);
|
|
22977
23056
|
try {
|
|
22978
|
-
key =
|
|
23057
|
+
key = fs22.realpathSync.native(key);
|
|
22979
23058
|
} catch {}
|
|
22980
23059
|
return platform === "win32" ? key.replaceAll("/", "\\").toLowerCase() : key;
|
|
22981
23060
|
};
|
|
22982
23061
|
var readMarker = (file) => {
|
|
22983
23062
|
try {
|
|
22984
|
-
const value = JSON.parse(
|
|
23063
|
+
const value = JSON.parse(fs22.readFileSync(file, "utf8"));
|
|
22985
23064
|
if (value?.version !== 1 || typeof value.session !== "string" || typeof value.host !== "string" || typeof value.heartbeatAt !== "string" || Number.isNaN(Date.parse(value.heartbeatAt)))
|
|
22986
23065
|
return null;
|
|
22987
23066
|
return {
|
|
@@ -23068,10 +23147,10 @@ var claimLiveSession = (target, owner, deps = {}) => {
|
|
|
23068
23147
|
checkout,
|
|
23069
23148
|
heartbeatAt: now.toISOString()
|
|
23070
23149
|
};
|
|
23071
|
-
|
|
23150
|
+
fs22.mkdirSync(path30.dirname(file), { recursive: true });
|
|
23072
23151
|
const temp = `${file}.${process.pid}.tmp`;
|
|
23073
|
-
|
|
23074
|
-
|
|
23152
|
+
fs22.writeFileSync(temp, JSON.stringify(marker));
|
|
23153
|
+
fs22.renameSync(temp, file);
|
|
23075
23154
|
} catch {}
|
|
23076
23155
|
};
|
|
23077
23156
|
|
|
@@ -23080,22 +23159,22 @@ var NONE3 = { kind: "none" };
|
|
|
23080
23159
|
var CASE_INSENSITIVE = process.platform === "darwin" || process.platform === "win32";
|
|
23081
23160
|
var canonical2 = (file) => {
|
|
23082
23161
|
let rest = "";
|
|
23083
|
-
for (let dir =
|
|
23162
|
+
for (let dir = path31.resolve(file);; dir = path31.dirname(dir)) {
|
|
23084
23163
|
try {
|
|
23085
|
-
return
|
|
23164
|
+
return path31.join(realpathSync6.native(dir), rest);
|
|
23086
23165
|
} catch {
|
|
23087
|
-
if (
|
|
23088
|
-
return
|
|
23089
|
-
rest = rest ?
|
|
23166
|
+
if (path31.dirname(dir) === dir)
|
|
23167
|
+
return path31.resolve(file);
|
|
23168
|
+
rest = rest ? path31.join(path31.basename(dir), rest) : path31.basename(dir);
|
|
23090
23169
|
}
|
|
23091
23170
|
}
|
|
23092
23171
|
};
|
|
23093
23172
|
var exempt = (cwd, root, file, plans) => {
|
|
23094
23173
|
const fold = (value) => CASE_INSENSITIVE ? value.toLowerCase() : value;
|
|
23095
|
-
const relative =
|
|
23096
|
-
if (relative.startsWith("..") ||
|
|
23174
|
+
const relative = path31.relative(fold(canonical2(root)), fold(canonical2(path31.resolve(cwd, file))));
|
|
23175
|
+
if (relative.startsWith("..") || path31.isAbsolute(relative))
|
|
23097
23176
|
return true;
|
|
23098
|
-
const posix = relative.split(
|
|
23177
|
+
const posix = relative.split(path31.sep).join("/");
|
|
23099
23178
|
const segments = posix.split("/");
|
|
23100
23179
|
return /\.mdx?$/i.test(posix) || segments[0] === "docs" || segments.includes("plans") || [...plans].some((plan) => fold(plan) === posix);
|
|
23101
23180
|
};
|
|
@@ -23216,7 +23295,7 @@ var shellWrites = (command, depth = 0) => {
|
|
|
23216
23295
|
return { writes: true, targets: unknown ? null : targets };
|
|
23217
23296
|
};
|
|
23218
23297
|
var cache2 = new Map;
|
|
23219
|
-
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(
|
|
23298
|
+
var planKeyOf = (root, plans) => [...plans].map((file) => fileSignature(path31.resolve(root, file)) ?? "-").join("\x00");
|
|
23220
23299
|
var gateFor = (cwd) => {
|
|
23221
23300
|
const store = new TaskStore(cwd);
|
|
23222
23301
|
const listed = store.listTaskIndex();
|
|
@@ -23295,7 +23374,7 @@ var gitMutationDirs = (cwd, command, dialect) => {
|
|
|
23295
23374
|
return [];
|
|
23296
23375
|
if (sub === "stash" && ["list", "show"].includes(rest[0] ?? ""))
|
|
23297
23376
|
return [];
|
|
23298
|
-
return [
|
|
23377
|
+
return [path31.resolve(cwd, invocation.dir ?? ".")];
|
|
23299
23378
|
});
|
|
23300
23379
|
};
|
|
23301
23380
|
var CD2 = new Set(["cd", "chdir", "set-location", "sl"]);
|
|
@@ -23306,7 +23385,7 @@ var cdInto = (dir, words) => {
|
|
|
23306
23385
|
const target = named === undefined ? undefined : homeExpanded(named);
|
|
23307
23386
|
if (dir === undefined || target === "-" || target && /^~|[$`*?]/.test(target))
|
|
23308
23387
|
return;
|
|
23309
|
-
return target === undefined ? os10.homedir() :
|
|
23388
|
+
return target === undefined ? os10.homedir() : path31.resolve(dir, target);
|
|
23310
23389
|
};
|
|
23311
23390
|
var quoteWord2 = (word) => /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replaceAll("'", "'\\''")}'`;
|
|
23312
23391
|
var homeExpanded = (file) => {
|
|
@@ -23320,7 +23399,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23320
23399
|
const groups = [];
|
|
23321
23400
|
const at = (file) => {
|
|
23322
23401
|
const home = homeExpanded(file);
|
|
23323
|
-
return
|
|
23402
|
+
return path31.isAbsolute(home) ? home : dir === undefined ? null : path31.resolve(dir, home);
|
|
23324
23403
|
};
|
|
23325
23404
|
for (const segment of segmentsOf(command, dialect)) {
|
|
23326
23405
|
if (segment.group === "open") {
|
|
@@ -23361,7 +23440,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23361
23440
|
const edits = editsOf(segment.words);
|
|
23362
23441
|
if (edits === null) {
|
|
23363
23442
|
if (dir !== undefined)
|
|
23364
|
-
targets.push(
|
|
23443
|
+
targets.push(path31.join(dir, DIR_TARGET));
|
|
23365
23444
|
} else
|
|
23366
23445
|
for (const file of edits) {
|
|
23367
23446
|
const resolved = at(file);
|
|
@@ -23369,7 +23448,7 @@ var segmentTargets = (cwd, command, dialect, depth = 0) => {
|
|
|
23369
23448
|
targets.push(resolved);
|
|
23370
23449
|
}
|
|
23371
23450
|
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), "")))
|
|
23372
|
-
targets.push(
|
|
23451
|
+
targets.push(path31.join(dir, DIR_TARGET));
|
|
23373
23452
|
}
|
|
23374
23453
|
return targets;
|
|
23375
23454
|
};
|
|
@@ -23404,7 +23483,7 @@ var liveDeny = ({ marker, checkout, ageMs, file }) => {
|
|
|
23404
23483
|
var guarded = (targets) => {
|
|
23405
23484
|
const seen = new Set;
|
|
23406
23485
|
return targets.filter((target) => {
|
|
23407
|
-
const dir =
|
|
23486
|
+
const dir = path31.dirname(target);
|
|
23408
23487
|
if (seen.has(dir))
|
|
23409
23488
|
return false;
|
|
23410
23489
|
seen.add(dir);
|
|
@@ -23425,7 +23504,7 @@ var claimAll = (owner, targets, deps) => {
|
|
|
23425
23504
|
for (const target of guarded(targets))
|
|
23426
23505
|
claimLiveSession(target, owner, deps);
|
|
23427
23506
|
};
|
|
23428
|
-
var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) =>
|
|
23507
|
+
var liveTargets = (cwd, paths) => paths?.length ? paths.map((file) => path31.resolve(cwd, file)) : [path31.join(cwd, DIR_TARGET)];
|
|
23429
23508
|
var issuedTarget = (cwd, targets) => {
|
|
23430
23509
|
const state = resolveStateDir();
|
|
23431
23510
|
const found = targets.find((target) => underIssued(state, cwd, homeExpanded(target), process.platform, canonical2));
|
|
@@ -23433,7 +23512,7 @@ var issuedTarget = (cwd, targets) => {
|
|
|
23433
23512
|
};
|
|
23434
23513
|
var underIssued = (state, cwd, target, platform = process.platform, real = (file) => file) => {
|
|
23435
23514
|
const win = platform === "win32";
|
|
23436
|
-
const p = win ?
|
|
23515
|
+
const p = win ? path31.win32 : path31.posix;
|
|
23437
23516
|
const fold = (value) => win || platform === "darwin" ? value.toLowerCase() : value;
|
|
23438
23517
|
const named = win ? target.replace(/^\/([a-zA-Z])(?=\/|$)/, "$1:") : target;
|
|
23439
23518
|
const relative = p.relative(fold(real(p.resolve(state))), fold(real(p.resolve(cwd, named))));
|
|
@@ -23482,7 +23561,7 @@ function shellGate(cwd, command, owner, dialect = "posix", deps) {
|
|
|
23482
23561
|
try {
|
|
23483
23562
|
targets = [
|
|
23484
23563
|
...segmentTargets(cwd, command, dialect),
|
|
23485
|
-
...gitMutationDirs(cwd, command, dialect).map((dir) =>
|
|
23564
|
+
...gitMutationDirs(cwd, command, dialect).map((dir) => path31.join(dir, DIR_TARGET))
|
|
23486
23565
|
];
|
|
23487
23566
|
} catch {
|
|
23488
23567
|
targets = [];
|
|
@@ -23922,8 +24001,110 @@ var WRITE_TOOLS = new Set([
|
|
|
23922
24001
|
"editfile",
|
|
23923
24002
|
"writefile"
|
|
23924
24003
|
]);
|
|
24004
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
24005
|
+
import fs23 from "node:fs";
|
|
24006
|
+
import path32 from "node:path";
|
|
24007
|
+
var readPlans = (store) => {
|
|
24008
|
+
const dir = path32.join(store, "fanouts");
|
|
24009
|
+
let names;
|
|
24010
|
+
try {
|
|
24011
|
+
names = fs23.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
24012
|
+
} catch {
|
|
24013
|
+
return [];
|
|
24014
|
+
}
|
|
24015
|
+
const plans = [];
|
|
24016
|
+
for (const name of names) {
|
|
24017
|
+
try {
|
|
24018
|
+
const raw = JSON.parse(fs23.readFileSync(path32.join(dir, name), "utf8"));
|
|
24019
|
+
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
24020
|
+
continue;
|
|
24021
|
+
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
24022
|
+
plans.push({
|
|
24023
|
+
name: raw.name,
|
|
24024
|
+
leads: texts([raw.leadSession, ...texts(raw.formerLeads)]),
|
|
24025
|
+
branches: texts(raw.slices.map((slice) => slice && typeof slice === "object" ? slice.branch : null))
|
|
24026
|
+
});
|
|
24027
|
+
} catch {}
|
|
24028
|
+
}
|
|
24029
|
+
return plans;
|
|
24030
|
+
};
|
|
24031
|
+
var leadOf2 = (input) => input.session.parentId ?? (input.session.agentId ? input.session.id : null) ?? (input.session.id.includes(":") ? input.session.id.split(":")[0] : null);
|
|
24032
|
+
var worksFor = (plan, input, branch) => {
|
|
24033
|
+
const session = input.session.id;
|
|
24034
|
+
if (plan.leads.includes(session) && !input.session.agentId)
|
|
24035
|
+
return false;
|
|
24036
|
+
const lead = leadOf2(input);
|
|
24037
|
+
if (lead && plan.leads.includes(lead))
|
|
24038
|
+
return true;
|
|
24039
|
+
if (plan.leads.some((each) => session.startsWith(`${each}-w-`)))
|
|
24040
|
+
return true;
|
|
24041
|
+
const current = branch();
|
|
24042
|
+
return current !== null && plan.branches.includes(current);
|
|
24043
|
+
};
|
|
24044
|
+
var standingFor = (input, store, rev) => {
|
|
24045
|
+
const orders = new Map;
|
|
24046
|
+
const ledger = readLedger(input.cwd);
|
|
24047
|
+
const rows = ledger.ok ? ledger.value.rows : [];
|
|
24048
|
+
let branch;
|
|
24049
|
+
const lazyBranch = () => branch === undefined ? branch = currentBranch(input.cwd) : branch;
|
|
24050
|
+
for (const plan of readPlans(store))
|
|
24051
|
+
if (worksFor(plan, input, lazyBranch))
|
|
24052
|
+
for (const row of activeStanding(rows, plan.name, plan.leads.length ? plan.leads : null))
|
|
24053
|
+
orders.set(row.id, row);
|
|
24054
|
+
return { rev, orders, rows };
|
|
24055
|
+
};
|
|
24056
|
+
var fanoutOf = (row) => typeof row.fanout === "string" ? row.fanout : "?";
|
|
24057
|
+
var changedSince = (now, ids) => {
|
|
24058
|
+
const known = new Set(ids);
|
|
24059
|
+
const added = [...now.orders.values()].filter((row) => !known.has(row.id));
|
|
24060
|
+
const byId = new Map(now.rows.map((row) => [row.id, row]));
|
|
24061
|
+
const dropped = ids.filter((id) => !now.orders.has(id)).map((id) => byId.get(id)).filter((row) => row !== undefined);
|
|
24062
|
+
if (!added.length && !dropped.length)
|
|
24063
|
+
return null;
|
|
24064
|
+
const fanouts = [...new Set([...added, ...dropped].map(fanoutOf))].join(", ");
|
|
24065
|
+
const lines = [
|
|
24066
|
+
`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.`,
|
|
24067
|
+
...added.map((row) => ` - new: ${String(row.what)}`),
|
|
24068
|
+
...dropped.map((row) => ` - no longer in force: ${String(row.what)}${row.stop ? " (the stop is lifted: continue your brief)" : ""}`)
|
|
24069
|
+
];
|
|
24070
|
+
if (added.some((row) => row.stop === true))
|
|
24071
|
+
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.");
|
|
24072
|
+
return lines.join(`
|
|
24073
|
+
`);
|
|
24074
|
+
};
|
|
24075
|
+
var sinceStart = new Map;
|
|
24076
|
+
var standingSinceStart = (input) => {
|
|
24077
|
+
try {
|
|
24078
|
+
const store = input.session.id ? gitStoreDir(input.cwd) : null;
|
|
24079
|
+
if (!store)
|
|
24080
|
+
return null;
|
|
24081
|
+
const rev = readStandingRev(store) ?? "";
|
|
24082
|
+
const file = standingSeenFile(store, input.session.id, input.session.agentId);
|
|
24083
|
+
const cached = sinceStart.get(file);
|
|
24084
|
+
if (cached?.rev === rev)
|
|
24085
|
+
return cached.text;
|
|
24086
|
+
let text = null;
|
|
24087
|
+
if (rev) {
|
|
24088
|
+
const now = standingFor(input, store, rev);
|
|
24089
|
+
const seen = readStandingSeen(file);
|
|
24090
|
+
let ids = seen.ids;
|
|
24091
|
+
if (seen.rev === null) {
|
|
24092
|
+
ids = cached ? [] : [...now.orders.keys()];
|
|
24093
|
+
writeStandingSeen(file, { rev, ids });
|
|
24094
|
+
}
|
|
24095
|
+
text = changedSince(now, ids);
|
|
24096
|
+
}
|
|
24097
|
+
sinceStart.set(file, { rev, text });
|
|
24098
|
+
if (sinceStart.size > 256)
|
|
24099
|
+
sinceStart.delete(sinceStart.keys().next().value);
|
|
24100
|
+
return text;
|
|
24101
|
+
} catch {
|
|
24102
|
+
return null;
|
|
24103
|
+
}
|
|
24104
|
+
};
|
|
23925
24105
|
// packages/workit-core/src/hooks/handle.ts
|
|
23926
24106
|
var offered = new Set;
|
|
24107
|
+
var PRE_TOOL = new Set(["shell.pre", "write.pre", "tool.pre"]);
|
|
23927
24108
|
// packages/workit-core/src/hooks/deadline.ts
|
|
23928
24109
|
var QUIET = new Set([
|
|
23929
24110
|
"stop",
|
|
@@ -24026,11 +24207,11 @@ var OPENCODE_DESCRIPTOR = {
|
|
|
24026
24207
|
]
|
|
24027
24208
|
};
|
|
24028
24209
|
// packages/workit-opencode/src/shared/init-apply.ts
|
|
24029
|
-
import
|
|
24210
|
+
import path37 from "node:path";
|
|
24030
24211
|
|
|
24031
24212
|
// packages/workit-core/src/core/gitignore.ts
|
|
24032
24213
|
import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
|
|
24033
|
-
import
|
|
24214
|
+
import path33 from "node:path";
|
|
24034
24215
|
var GITIGNORE_ENTRIES = [
|
|
24035
24216
|
"# workit: SDD working state (never commit)",
|
|
24036
24217
|
"docs/*/sdd/",
|
|
@@ -24050,7 +24231,7 @@ var GITIGNORE_ENTRIES = [
|
|
|
24050
24231
|
var ensureProjectGitignore = (workspaceRoot, confirmed) => {
|
|
24051
24232
|
if (!confirmed)
|
|
24052
24233
|
return { ok: false, error: "confirmed: true required" };
|
|
24053
|
-
const file =
|
|
24234
|
+
const file = path33.join(workspaceRoot, ".gitignore");
|
|
24054
24235
|
const existing = existsSync9(file) ? readFileSync6(file, "utf8") : "";
|
|
24055
24236
|
const existingLines = new Set(existing.split(`
|
|
24056
24237
|
`).map((l) => l.trim()).filter(Boolean));
|
|
@@ -24078,25 +24259,25 @@ var ensureProjectGitignore = (workspaceRoot, confirmed) => {
|
|
|
24078
24259
|
|
|
24079
24260
|
// packages/workit-core/src/core/hygiene.ts
|
|
24080
24261
|
import { existsSync as existsSync10, readFileSync as readFileSync7, readdirSync as readdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
24081
|
-
import
|
|
24262
|
+
import path34 from "node:path";
|
|
24082
24263
|
var repoRoot3 = assetRoot();
|
|
24083
|
-
var templatesDir = () =>
|
|
24264
|
+
var templatesDir = () => path34.join(repoRoot3, "templates", "hygiene");
|
|
24084
24265
|
var packageJson = (root) => {
|
|
24085
|
-
if (!existsSync10(
|
|
24266
|
+
if (!existsSync10(path34.join(root, "package.json")))
|
|
24086
24267
|
return null;
|
|
24087
24268
|
try {
|
|
24088
|
-
return JSON.parse(readFileSync7(
|
|
24269
|
+
return JSON.parse(readFileSync7(path34.join(root, "package.json"), "utf8"));
|
|
24089
24270
|
} catch {
|
|
24090
24271
|
return null;
|
|
24091
24272
|
}
|
|
24092
24273
|
};
|
|
24093
24274
|
var isOpenSource = (root) => {
|
|
24094
|
-
if (existsSync10(
|
|
24275
|
+
if (existsSync10(path34.join(root, "LICENSE")))
|
|
24095
24276
|
return true;
|
|
24096
24277
|
const pkg = packageJson(root);
|
|
24097
24278
|
if (pkg && !pkg.private)
|
|
24098
24279
|
return true;
|
|
24099
|
-
return
|
|
24280
|
+
return path34.basename(root) === "workflow-toolkit";
|
|
24100
24281
|
};
|
|
24101
24282
|
var licenseHolder = (root) => {
|
|
24102
24283
|
const pkg = packageJson(root);
|
|
@@ -24119,13 +24300,13 @@ var planHygieneFiles = (root, opts = {}) => {
|
|
|
24119
24300
|
files.push("LICENSE", "CONTRIBUTING.md");
|
|
24120
24301
|
const planned = [];
|
|
24121
24302
|
for (const file of files) {
|
|
24122
|
-
if (existsSync10(
|
|
24303
|
+
if (existsSync10(path34.join(root, file)))
|
|
24123
24304
|
continue;
|
|
24124
|
-
const tpl =
|
|
24305
|
+
const tpl = path34.join(templatesDir(), file);
|
|
24125
24306
|
if (!existsSync10(tpl))
|
|
24126
24307
|
continue;
|
|
24127
|
-
const content = readFileSync7(tpl, "utf8").replace(/<PROJECT>/g,
|
|
24128
|
-
planned.push({ path:
|
|
24308
|
+
const content = readFileSync7(tpl, "utf8").replace(/<PROJECT>/g, path34.basename(root)).replace(/<YEAR>/g, String(new Date().getFullYear())).replace(/<HOLDER>\s*/g, licenseHolder(root));
|
|
24309
|
+
planned.push({ path: path34.join(root, file), content });
|
|
24129
24310
|
}
|
|
24130
24311
|
return planned;
|
|
24131
24312
|
};
|
|
@@ -24135,19 +24316,19 @@ var ensureHygieneFiles = (root, opts) => {
|
|
|
24135
24316
|
const created = [];
|
|
24136
24317
|
for (const planned of planHygieneFiles(root, opts)) {
|
|
24137
24318
|
writeFileSync5(planned.path, planned.content, "utf8");
|
|
24138
|
-
created.push(
|
|
24319
|
+
created.push(path34.basename(planned.path));
|
|
24139
24320
|
}
|
|
24140
24321
|
return { ok: true, created };
|
|
24141
24322
|
};
|
|
24142
24323
|
|
|
24143
24324
|
// packages/workit-core/src/core/init.ts
|
|
24144
|
-
import
|
|
24145
|
-
import
|
|
24325
|
+
import fs24 from "node:fs";
|
|
24326
|
+
import path36 from "node:path";
|
|
24146
24327
|
import { spawnSync as spawnSync19 } from "node:child_process";
|
|
24147
24328
|
|
|
24148
24329
|
// packages/workit-core/src/core/workspace-branch-policy.ts
|
|
24149
24330
|
import { mkdirSync as mkdirSync4, readFileSync as readFileSync8, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
24150
|
-
import
|
|
24331
|
+
import path35 from "node:path";
|
|
24151
24332
|
import { isDeepStrictEqual } from "node:util";
|
|
24152
24333
|
var readFileSafe = (p) => {
|
|
24153
24334
|
try {
|
|
@@ -24158,7 +24339,7 @@ var readFileSafe = (p) => {
|
|
|
24158
24339
|
};
|
|
24159
24340
|
function applyWorkspaceBranchPolicy(opts) {
|
|
24160
24341
|
const { workspace_root, env = process.env } = opts;
|
|
24161
|
-
const dir =
|
|
24342
|
+
const dir = path35.join(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
24162
24343
|
const {
|
|
24163
24344
|
status,
|
|
24164
24345
|
path: wsPath,
|
|
@@ -24170,7 +24351,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
24170
24351
|
if (status === "malformed" || status === "invalid")
|
|
24171
24352
|
return { ok: false, error: workspacesError ?? `invalid workspaces.json: ${wsPath}` };
|
|
24172
24353
|
const detection = detectBranchPolicy(workspace_root);
|
|
24173
|
-
const name = String(env.WORKFLOW_BP_NAME ??
|
|
24354
|
+
const name = String(env.WORKFLOW_BP_NAME ?? path35.basename(workspace_root));
|
|
24174
24355
|
const integration = env.WORKFLOW_BP_INTEGRATION ?? detection.integration;
|
|
24175
24356
|
const policy = {
|
|
24176
24357
|
preset: detection.preset,
|
|
@@ -24219,7 +24400,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
24219
24400
|
ok: false,
|
|
24220
24401
|
error: `workspaces.json changed while applying the branch policy: ${wsPath}`
|
|
24221
24402
|
};
|
|
24222
|
-
mkdirSync4(
|
|
24403
|
+
mkdirSync4(path35.dirname(wsPath), { recursive: true });
|
|
24223
24404
|
const tmp = `${wsPath}.${process.pid}.tmp`;
|
|
24224
24405
|
try {
|
|
24225
24406
|
writeFileSync6(tmp, JSON.stringify({ ...document, workspaces: next }, null, 2) + `
|
|
@@ -24254,7 +24435,7 @@ function applyWorkspaceBranchPolicy(opts) {
|
|
|
24254
24435
|
var TOKEN_PLACEHOLDER2 = "YOUR_TOKEN_HERE";
|
|
24255
24436
|
var readJson3 = (p) => {
|
|
24256
24437
|
try {
|
|
24257
|
-
const parsed = JSON.parse(
|
|
24438
|
+
const parsed = JSON.parse(fs24.readFileSync(p, "utf8"));
|
|
24258
24439
|
return isConfigObject(parsed) ? parsed : null;
|
|
24259
24440
|
} catch {
|
|
24260
24441
|
return null;
|
|
@@ -24284,7 +24465,7 @@ var youtrackJsonContent = (dir) => {
|
|
|
24284
24465
|
const meetingIssue = process.env.WORKFLOW_YT_MEETING_ISSUE;
|
|
24285
24466
|
return {
|
|
24286
24467
|
baseUrl: process.env.WORKFLOW_YT_BASE_URL ?? "https://youtrack.example.com",
|
|
24287
|
-
tokenFile: process.env.WORKFLOW_YT_TOKEN_FILE ??
|
|
24468
|
+
tokenFile: process.env.WORKFLOW_YT_TOKEN_FILE ?? path36.join(dir, "youtrack.token"),
|
|
24288
24469
|
...meetingIssue ? {
|
|
24289
24470
|
meetingIssue,
|
|
24290
24471
|
meetingIssues: { general: { issue: meetingIssue, label: "General meetings" } }
|
|
@@ -24314,19 +24495,19 @@ var vcsJsonContent = () => {
|
|
|
24314
24495
|
};
|
|
24315
24496
|
function initApplyData(action, env = process.env) {
|
|
24316
24497
|
const dir = String(env.WORKFLOW_TOOLKIT_CONFIG ?? configDir());
|
|
24317
|
-
|
|
24498
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
24318
24499
|
switch (action) {
|
|
24319
24500
|
case "youtrack_json": {
|
|
24320
|
-
const out =
|
|
24321
|
-
|
|
24501
|
+
const out = path36.join(dir, "youtrack.json");
|
|
24502
|
+
fs24.writeFileSync(out, JSON.stringify(youtrackJsonContent(dir), null, 2) + `
|
|
24322
24503
|
`, "utf8");
|
|
24323
24504
|
return { action, ok: true, path: out };
|
|
24324
24505
|
}
|
|
24325
24506
|
case "youtrack_token_placeholder": {
|
|
24326
|
-
const p =
|
|
24507
|
+
const p = path36.join(dir, "youtrack.token");
|
|
24327
24508
|
const preserved = writeFileExclusive(p, TOKEN_PLACEHOLDER2 + `
|
|
24328
24509
|
`, 384) === "preserved";
|
|
24329
|
-
const abs =
|
|
24510
|
+
const abs = path36.resolve(p);
|
|
24330
24511
|
return {
|
|
24331
24512
|
action,
|
|
24332
24513
|
ok: true,
|
|
@@ -24338,14 +24519,14 @@ function initApplyData(action, env = process.env) {
|
|
|
24338
24519
|
};
|
|
24339
24520
|
}
|
|
24340
24521
|
case "youtrack_scaffold": {
|
|
24341
|
-
const jsonOut =
|
|
24342
|
-
const tokenOut =
|
|
24343
|
-
|
|
24522
|
+
const jsonOut = path36.join(dir, "youtrack.json");
|
|
24523
|
+
const tokenOut = path36.join(dir, "youtrack.token");
|
|
24524
|
+
fs24.writeFileSync(jsonOut, JSON.stringify(youtrackJsonContent(dir), null, 2) + `
|
|
24344
24525
|
`, "utf8");
|
|
24345
24526
|
const preserved = writeFileExclusive(tokenOut, TOKEN_PLACEHOLDER2 + `
|
|
24346
24527
|
`, 384) === "preserved";
|
|
24347
|
-
const configPath =
|
|
24348
|
-
const tokenPath =
|
|
24528
|
+
const configPath = path36.resolve(jsonOut);
|
|
24529
|
+
const tokenPath = path36.resolve(tokenOut);
|
|
24349
24530
|
const prev = process.env.WORKFLOW_YOUTRACK_CONFIG;
|
|
24350
24531
|
process.env.WORKFLOW_YOUTRACK_CONFIG = configPath;
|
|
24351
24532
|
let tokenCreate = {};
|
|
@@ -24397,10 +24578,10 @@ function initApplyData(action, env = process.env) {
|
|
|
24397
24578
|
}
|
|
24398
24579
|
}
|
|
24399
24580
|
case "vcs_scaffold": {
|
|
24400
|
-
const jsonOut =
|
|
24401
|
-
|
|
24581
|
+
const jsonOut = path36.join(dir, "vcs.json");
|
|
24582
|
+
fs24.writeFileSync(jsonOut, JSON.stringify(vcsJsonContent(), null, 2) + `
|
|
24402
24583
|
`, "utf8");
|
|
24403
|
-
const configPath =
|
|
24584
|
+
const configPath = path36.resolve(jsonOut);
|
|
24404
24585
|
const prev = process.env.WORKFLOW_VCS_CONFIG;
|
|
24405
24586
|
process.env.WORKFLOW_VCS_CONFIG = configPath;
|
|
24406
24587
|
try {
|
|
@@ -24519,7 +24700,7 @@ var executeInitApply = (args, directory, runtime) => {
|
|
|
24519
24700
|
protectedNames: args.branch_policy_protected
|
|
24520
24701
|
}, current);
|
|
24521
24702
|
writeConfig(next);
|
|
24522
|
-
return output(ok({ action: "config", path:
|
|
24703
|
+
return output(ok({ action: "config", path: path37.join(configDir(), "config.json"), ...next }));
|
|
24523
24704
|
}
|
|
24524
24705
|
const env = Object.fromEntries(Object.entries({
|
|
24525
24706
|
WORKFLOW_YT_BASE_URL: args.base_url,
|
|
@@ -24536,14 +24717,14 @@ var executeInitApply = (args, directory, runtime) => {
|
|
|
24536
24717
|
|
|
24537
24718
|
// packages/workit-opencode/src/shared/session.ts
|
|
24538
24719
|
import { realpathSync as realpathSync7 } from "node:fs";
|
|
24539
|
-
import
|
|
24720
|
+
import path38 from "node:path";
|
|
24540
24721
|
var sameWorkspace = (expected, observed) => {
|
|
24541
24722
|
if (typeof observed !== "string" || !observed)
|
|
24542
24723
|
return false;
|
|
24543
24724
|
try {
|
|
24544
24725
|
return realpathSync7(expected) === realpathSync7(observed);
|
|
24545
24726
|
} catch {
|
|
24546
|
-
return
|
|
24727
|
+
return path38.resolve(expected) === path38.resolve(observed);
|
|
24547
24728
|
}
|
|
24548
24729
|
};
|
|
24549
24730
|
|
|
@@ -24615,7 +24796,7 @@ var workitFamilyOf = (toolName) => {
|
|
|
24615
24796
|
|
|
24616
24797
|
// packages/workit-opencode/src/tools/context.ts
|
|
24617
24798
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
24618
|
-
import
|
|
24799
|
+
import path39 from "node:path";
|
|
24619
24800
|
var createContextTool = () => ({
|
|
24620
24801
|
description: "Read Git, pull request, YouTrack, issue, changelog, release, or affected-file context.",
|
|
24621
24802
|
execute: async (args, context) => {
|
|
@@ -24625,7 +24806,7 @@ var createContextTool = () => ({
|
|
|
24625
24806
|
let root;
|
|
24626
24807
|
try {
|
|
24627
24808
|
const cwd = parsed.data.cwd;
|
|
24628
|
-
root = realpathSync8(cwd ?
|
|
24809
|
+
root = realpathSync8(cwd ? path39.resolve(context.directory, cwd) : context.directory);
|
|
24629
24810
|
} catch {
|
|
24630
24811
|
return JSON.stringify(failure2("invalid_input", "context target directory cannot be resolved"), null, 2);
|
|
24631
24812
|
}
|
|
@@ -24655,20 +24836,20 @@ var workerCoordinatorFor = (task, worker) => {
|
|
|
24655
24836
|
};
|
|
24656
24837
|
|
|
24657
24838
|
// packages/workit-core/src/fanout.ts
|
|
24658
|
-
import { createHash as
|
|
24659
|
-
import
|
|
24660
|
-
import
|
|
24839
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
24840
|
+
import fs26 from "node:fs";
|
|
24841
|
+
import path42 from "node:path";
|
|
24661
24842
|
|
|
24662
24843
|
// packages/workit-core/src/stack.ts
|
|
24663
24844
|
import { spawnSync as spawnSync21 } from "node:child_process";
|
|
24664
|
-
import { createHash as
|
|
24665
|
-
import
|
|
24666
|
-
import
|
|
24845
|
+
import { createHash as createHash16, randomBytes as randomBytes4 } from "node:crypto";
|
|
24846
|
+
import fs25 from "node:fs";
|
|
24847
|
+
import path41 from "node:path";
|
|
24667
24848
|
|
|
24668
24849
|
// packages/workit-core/src/git/ops.ts
|
|
24669
24850
|
import { spawnSync as spawnSync20 } from "node:child_process";
|
|
24670
24851
|
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
24671
|
-
import
|
|
24852
|
+
import path40 from "node:path";
|
|
24672
24853
|
|
|
24673
24854
|
// packages/workit-core/src/forge/redact.ts
|
|
24674
24855
|
var KEY = String.raw`[A-Za-z0-9_.-]*?(?:token|secret|password|passwd|pwd|api[_-]?key|access[_-]?key|account[_-]?key|private[_-]?key|client[_-]?secret|credentials?|authorization|cookie|signature)[A-Za-z0-9_.-]*`;
|
|
@@ -24712,18 +24893,18 @@ function operationInProgress(cwd) {
|
|
|
24712
24893
|
if (!run.ok)
|
|
24713
24894
|
return null;
|
|
24714
24895
|
const found = run.stdout.split(`
|
|
24715
|
-
`).map((line) =>
|
|
24896
|
+
`).map((line) => path40.resolve(cwd, line.trim()));
|
|
24716
24897
|
const conflicted = () => git5(cwd, ["ls-files", "-u"]).stdout.trim() !== "";
|
|
24717
24898
|
for (const [index, [, operation]] of markers.entries()) {
|
|
24718
24899
|
const marker = found[index];
|
|
24719
24900
|
if (!marker || !existsSync11(marker))
|
|
24720
24901
|
continue;
|
|
24721
|
-
if (index === 1 && existsSync11(
|
|
24902
|
+
if (index === 1 && existsSync11(path40.join(marker, "applying")))
|
|
24722
24903
|
return { operation: "am", commitAllowed: false, branch: null };
|
|
24723
|
-
if (index === 0 && existsSync11(
|
|
24904
|
+
if (index === 0 && existsSync11(path40.join(marker, "amend")) && !conflicted()) {
|
|
24724
24905
|
let headName = "";
|
|
24725
24906
|
try {
|
|
24726
|
-
headName = readFileSync9(
|
|
24907
|
+
headName = readFileSync9(path40.join(marker, "head-name"), "utf8").trim();
|
|
24727
24908
|
} catch {}
|
|
24728
24909
|
const branch = headName.startsWith("refs/heads/") ? headName.slice("refs/heads/".length) : null;
|
|
24729
24910
|
return { operation, commitAllowed: branch !== null, branch };
|
|
@@ -24835,7 +25016,7 @@ function rebasingBranch2(dir) {
|
|
|
24835
25016
|
if (!found.ok)
|
|
24836
25017
|
continue;
|
|
24837
25018
|
try {
|
|
24838
|
-
return
|
|
25019
|
+
return fs25.readFileSync(found.stdout.trim(), "utf8").trim();
|
|
24839
25020
|
} catch {}
|
|
24840
25021
|
}
|
|
24841
25022
|
return null;
|
|
@@ -24843,14 +25024,14 @@ function rebasingBranch2(dir) {
|
|
|
24843
25024
|
function rebaseInProgress(dir) {
|
|
24844
25025
|
for (const name of ["rebase-merge", "rebase-apply"]) {
|
|
24845
25026
|
const found = gitRun3(dir, ["rev-parse", "--path-format=absolute", "--git-path", name]);
|
|
24846
|
-
if (found.ok &&
|
|
25027
|
+
if (found.ok && fs25.existsSync(found.stdout.trim()))
|
|
24847
25028
|
return true;
|
|
24848
25029
|
}
|
|
24849
25030
|
return false;
|
|
24850
25031
|
}
|
|
24851
25032
|
var scratchDir = (cwd) => {
|
|
24852
25033
|
const dir = stacksDir(cwd);
|
|
24853
|
-
return dir.ok ?
|
|
25034
|
+
return dir.ok ? path41.join(dir.data, "worktrees") : null;
|
|
24854
25035
|
};
|
|
24855
25036
|
function gitRestack(cwd, input) {
|
|
24856
25037
|
const owner = worktreeOf(cwd, input.branch);
|
|
@@ -24859,8 +25040,8 @@ function gitRestack(cwd, input) {
|
|
|
24859
25040
|
const scratch = scratchDir(cwd);
|
|
24860
25041
|
if (!scratch)
|
|
24861
25042
|
return { ok: false, conflict: false, worktree: cwd, error: "no store root" };
|
|
24862
|
-
|
|
24863
|
-
dir =
|
|
25043
|
+
fs25.mkdirSync(scratch, { recursive: true });
|
|
25044
|
+
dir = path41.join(scratch, `${input.branch.replace(/[^A-Za-z0-9._-]+/gu, "_").slice(0, 40)}-${randomBytes4(4).toString("hex")}`);
|
|
24864
25045
|
const added = gitRun3(cwd, ["worktree", "add", "-q", dir, input.branch], GIT_TIMEOUTS.worktree);
|
|
24865
25046
|
if (!added.ok)
|
|
24866
25047
|
return { ok: false, conflict: false, worktree: cwd, error: firstLine(added) };
|
|
@@ -24899,12 +25080,12 @@ function gitRestack(cwd, input) {
|
|
|
24899
25080
|
var firstLine = (run) => (`${run.stderr}
|
|
24900
25081
|
${run.stdout}`.split(`
|
|
24901
25082
|
`).find((line) => line.trim()) ?? "git failed").trim().slice(0, 300);
|
|
24902
|
-
var stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${
|
|
25083
|
+
var stackFileName = (name) => `${name.replace(/[^A-Za-z0-9._-]+/gu, "_").replace(/^[._]+/u, "").slice(0, 48).toLowerCase()}-${createHash16("sha256").update(name).digest("hex").slice(0, 12)}.json`;
|
|
24903
25084
|
function stacksDir(cwd) {
|
|
24904
25085
|
const root = storeRoot(cwd);
|
|
24905
25086
|
if (!root.ok)
|
|
24906
25087
|
return stackFail(root.code, root.error, root.unblock);
|
|
24907
|
-
return { ok: true, data:
|
|
25088
|
+
return { ok: true, data: path41.join(root.value.root, "stacks") };
|
|
24908
25089
|
}
|
|
24909
25090
|
var HEARTBEAT_STALE_MS = 2 * 60000;
|
|
24910
25091
|
|
|
@@ -25009,13 +25190,13 @@ function sliceHash(slice) {
|
|
|
25009
25190
|
issues: _issues,
|
|
25010
25191
|
...definition
|
|
25011
25192
|
} = slice;
|
|
25012
|
-
return
|
|
25193
|
+
return createHash17("sha256").update(JSON.stringify(definition)).digest("hex").slice(0, 16);
|
|
25013
25194
|
}
|
|
25014
25195
|
function fanoutsDir(cwd) {
|
|
25015
25196
|
const root = storeRoot(cwd);
|
|
25016
25197
|
if (!root.ok)
|
|
25017
25198
|
return fanoutFail(root.code, root.error, root.unblock);
|
|
25018
|
-
return { ok: true, data:
|
|
25199
|
+
return { ok: true, data: path42.join(root.value.root, "fanouts") };
|
|
25019
25200
|
}
|
|
25020
25201
|
function parseStored(raw) {
|
|
25021
25202
|
if (!isRecord7(raw) || typeof raw.name !== "string" || typeof raw.trunk !== "string")
|
|
@@ -25083,10 +25264,10 @@ function readFanout(cwd, name) {
|
|
|
25083
25264
|
const dir = fanoutsDir(cwd);
|
|
25084
25265
|
if (!dir.ok)
|
|
25085
25266
|
return dir;
|
|
25086
|
-
const file =
|
|
25267
|
+
const file = path42.join(dir.data, stackFileName(name));
|
|
25087
25268
|
let parsed = null;
|
|
25088
25269
|
try {
|
|
25089
|
-
parsed = parseStored(JSON.parse(
|
|
25270
|
+
parsed = parseStored(JSON.parse(fs26.readFileSync(file, "utf8")));
|
|
25090
25271
|
} catch (error) {
|
|
25091
25272
|
if (error.code === "ENOENT")
|
|
25092
25273
|
return { ok: true, data: null };
|
|
@@ -25100,7 +25281,7 @@ function listFanouts(cwd) {
|
|
|
25100
25281
|
return dir;
|
|
25101
25282
|
let names = [];
|
|
25102
25283
|
try {
|
|
25103
|
-
names =
|
|
25284
|
+
names = fs26.readdirSync(dir.data).filter((entry) => entry.endsWith(".json"));
|
|
25104
25285
|
} catch {
|
|
25105
25286
|
return { ok: true, data: [] };
|
|
25106
25287
|
}
|
|
@@ -25108,7 +25289,7 @@ function listFanouts(cwd) {
|
|
|
25108
25289
|
for (const entry of names) {
|
|
25109
25290
|
let parsed = null;
|
|
25110
25291
|
try {
|
|
25111
|
-
parsed = parseStored(JSON.parse(
|
|
25292
|
+
parsed = parseStored(JSON.parse(fs26.readFileSync(path42.join(dir.data, entry), "utf8")));
|
|
25112
25293
|
} catch {
|
|
25113
25294
|
parsed = null;
|
|
25114
25295
|
}
|
|
@@ -25689,7 +25870,18 @@ var injectAgentContext = (root, session, directChildren, system) => {
|
|
|
25689
25870
|
const verdict = session.parentID ? judgeVerdictText(root, session, workerContext) : null;
|
|
25690
25871
|
if (verdict && !hasMarker(system, "<workit-verdict-line>"))
|
|
25691
25872
|
system.push(textPart(`<workit-verdict-line>${verdict}</workit-verdict-line>`));
|
|
25873
|
+
const standing = session.parentID ? standingFor2(root, session) : null;
|
|
25874
|
+
if (standing && !hasMarker(system, "<workit-standing>"))
|
|
25875
|
+
system.push(textPart(`<workit-standing>${standing}</workit-standing>`));
|
|
25692
25876
|
};
|
|
25877
|
+
var standingFor2 = (root, session) => standingSinceStart({
|
|
25878
|
+
host: "opencode",
|
|
25879
|
+
cwd: session.directory ?? root,
|
|
25880
|
+
session: { id: session.id, agentId: null, agentType: null, parentId: session.parentID ?? null },
|
|
25881
|
+
permissionMode: null,
|
|
25882
|
+
transcriptPath: null,
|
|
25883
|
+
event: { kind: "context.turn" }
|
|
25884
|
+
});
|
|
25693
25885
|
var workerRole = (workerContext) => {
|
|
25694
25886
|
if (!workerContext)
|
|
25695
25887
|
return null;
|
|
@@ -25789,7 +25981,7 @@ var childTaskMissing = (store, input) => {
|
|
|
25789
25981
|
var childDenial = (identity) => `OpenCode child session has no validated Workit worker: as ${identity} it may only inspect the task summary (workit_task action "inspect") or record evidence or findings (workit_evidence/workit_finding action "record") on an existing task; for anything else the lead assigns it a worker with workit_worker before launching it`;
|
|
25790
25982
|
|
|
25791
25983
|
// packages/workit-opencode/src/v2/shell.ts
|
|
25792
|
-
import
|
|
25984
|
+
import path43 from "node:path";
|
|
25793
25985
|
var commandOf = (input) => {
|
|
25794
25986
|
if (input === null || typeof input !== "object")
|
|
25795
25987
|
return null;
|
|
@@ -25798,7 +25990,7 @@ var commandOf = (input) => {
|
|
|
25798
25990
|
};
|
|
25799
25991
|
var hookInput = (root, sessionID, id, shell) => ({
|
|
25800
25992
|
host: "opencode",
|
|
25801
|
-
cwd: shell.workdir ?
|
|
25993
|
+
cwd: shell.workdir ? path43.resolve(root, shell.workdir) : root,
|
|
25802
25994
|
session: { id: sessionID, agentId: null, agentType: null, parentId: null },
|
|
25803
25995
|
permissionMode: null,
|
|
25804
25996
|
transcriptPath: null,
|
|
@@ -26005,37 +26197,37 @@ var createStopControl = (root, port) => {
|
|
|
26005
26197
|
|
|
26006
26198
|
// packages/workit-opencode/src/v2/registry.ts
|
|
26007
26199
|
import { existsSync as existsSync13, readFileSync as readFileSync10 } from "node:fs";
|
|
26008
|
-
import
|
|
26200
|
+
import path45 from "node:path";
|
|
26009
26201
|
|
|
26010
26202
|
// packages/workit-opencode/src/shared/assets.ts
|
|
26011
26203
|
import { existsSync as existsSync12, realpathSync as realpathSync9 } from "node:fs";
|
|
26012
|
-
import
|
|
26204
|
+
import path44 from "node:path";
|
|
26013
26205
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
26014
26206
|
var moduleDir = () => {
|
|
26015
26207
|
try {
|
|
26016
|
-
return realpathSync9(
|
|
26208
|
+
return realpathSync9(path44.dirname(fileURLToPath2(import.meta.url)));
|
|
26017
26209
|
} catch {
|
|
26018
|
-
return
|
|
26210
|
+
return path44.dirname(fileURLToPath2(import.meta.url));
|
|
26019
26211
|
}
|
|
26020
26212
|
};
|
|
26021
26213
|
var packageRoot2 = () => {
|
|
26022
26214
|
const dir = moduleDir();
|
|
26023
26215
|
for (const candidate of [
|
|
26024
|
-
|
|
26025
|
-
|
|
26026
|
-
|
|
26216
|
+
path44.resolve(dir, ".."),
|
|
26217
|
+
path44.resolve(dir, "..", ".."),
|
|
26218
|
+
path44.resolve(dir, "..", "..", "..")
|
|
26027
26219
|
]) {
|
|
26028
|
-
if (existsSync12(
|
|
26220
|
+
if (existsSync12(path44.join(candidate, "package.json")))
|
|
26029
26221
|
return candidate;
|
|
26030
26222
|
}
|
|
26031
|
-
return
|
|
26223
|
+
return path44.resolve(dir, "..");
|
|
26032
26224
|
};
|
|
26033
26225
|
var skillsRoot = () => {
|
|
26034
26226
|
const root = packageRoot2();
|
|
26035
|
-
const canonical =
|
|
26036
|
-
if (existsSync12(
|
|
26227
|
+
const canonical = path44.resolve(root, "..", "workit-core", "skills");
|
|
26228
|
+
if (existsSync12(path44.join(root, "src")) && existsSync12(canonical))
|
|
26037
26229
|
return canonical;
|
|
26038
|
-
return
|
|
26230
|
+
return path44.join(root, "assets", "skills");
|
|
26039
26231
|
};
|
|
26040
26232
|
|
|
26041
26233
|
// packages/workit-opencode/src/v2/registry.ts
|
|
@@ -26062,11 +26254,11 @@ var registerSkills = async (ctx) => {
|
|
|
26062
26254
|
if (!existsSync13(skillsDir))
|
|
26063
26255
|
return new Set;
|
|
26064
26256
|
const listed = await ctx.skill.list().catch(() => ({ data: [] }));
|
|
26065
|
-
const own = (skill) => typeof skill.path === "string" &&
|
|
26257
|
+
const own = (skill) => typeof skill.path === "string" && path45.resolve(skill.path).startsWith(skillsDir + path45.sep);
|
|
26066
26258
|
const userSkills = new Set((listed?.data ?? []).filter((skill) => !own(skill)).map((skill) => skill.id));
|
|
26067
26259
|
const packaged = new Map;
|
|
26068
26260
|
for (const id of WORKIT_METHOD_SKILLS) {
|
|
26069
|
-
const file =
|
|
26261
|
+
const file = path45.join(skillsDir, id, "SKILL.md");
|
|
26070
26262
|
if (!userSkills.has(id) && existsSync13(file))
|
|
26071
26263
|
packaged.set(id, file);
|
|
26072
26264
|
}
|
|
@@ -26114,22 +26306,22 @@ var registerCommands = async (ctx, registeredSkills) => {
|
|
|
26114
26306
|
|
|
26115
26307
|
// packages/workit-opencode/src/stale-sources.ts
|
|
26116
26308
|
import { existsSync as existsSync14, readdirSync as readdirSync6 } from "node:fs";
|
|
26117
|
-
import
|
|
26309
|
+
import path46 from "node:path";
|
|
26118
26310
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
26119
26311
|
var typescriptFiles = (directory) => {
|
|
26120
26312
|
if (!existsSync14(directory))
|
|
26121
26313
|
return [];
|
|
26122
26314
|
return readdirSync6(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
26123
|
-
const file =
|
|
26315
|
+
const file = path46.join(directory, entry.name);
|
|
26124
26316
|
return entry.isDirectory() ? typescriptFiles(file) : entry.isFile() && file.endsWith(".ts") ? [file] : [];
|
|
26125
26317
|
});
|
|
26126
26318
|
};
|
|
26127
26319
|
var pluginSourceFiles = [
|
|
26128
26320
|
...new Set([
|
|
26129
26321
|
fileURLToPath3(import.meta.url),
|
|
26130
|
-
...typescriptFiles(
|
|
26131
|
-
|
|
26132
|
-
...typescriptFiles(
|
|
26322
|
+
...typescriptFiles(path46.join(packageRoot2(), "src")),
|
|
26323
|
+
path46.join(packageRoot2(), "..", "workit-core", "src", "core.ts"),
|
|
26324
|
+
...typescriptFiles(path46.join(packageRoot2(), "..", "workit-core", "src", "core"))
|
|
26133
26325
|
])
|
|
26134
26326
|
].filter((file) => existsSync14(file)).toSorted();
|
|
26135
26327
|
|