@brainervirus/workit-pi 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/worker.js +596 -7
- package/dist/workit.js +464 -245
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -8476,8 +8476,38 @@ var TIER_HOSTS = new Set([
|
|
|
8476
8476
|
]);
|
|
8477
8477
|
|
|
8478
8478
|
// packages/workit-core/src/git/rev.ts
|
|
8479
|
+
import { spawnSync } from "node:child_process";
|
|
8479
8480
|
var MAX_BUFFER = 256 * 1024 * 1024;
|
|
8481
|
+
var GIT_TIMEOUTS = { local: 20000, worktree: 120000, network: 15000 };
|
|
8482
|
+
var git = (cwd, args, options = {}) => {
|
|
8483
|
+
const result = spawnSync("git", args, {
|
|
8484
|
+
cwd,
|
|
8485
|
+
encoding: "utf8",
|
|
8486
|
+
env: options.env ?? process.env,
|
|
8487
|
+
input: options.input,
|
|
8488
|
+
maxBuffer: MAX_BUFFER,
|
|
8489
|
+
timeout: options.timeoutMs ?? GIT_TIMEOUTS.local,
|
|
8490
|
+
killSignal: "SIGKILL",
|
|
8491
|
+
windowsHide: true
|
|
8492
|
+
});
|
|
8493
|
+
const error = result.error;
|
|
8494
|
+
return {
|
|
8495
|
+
ok: result.status === 0,
|
|
8496
|
+
stdout: result.stdout ?? "",
|
|
8497
|
+
stderr: result.stderr ?? "",
|
|
8498
|
+
timedOut: error?.code === "ETIMEDOUT"
|
|
8499
|
+
};
|
|
8500
|
+
};
|
|
8501
|
+
var line = (run) => {
|
|
8502
|
+
if (!run.ok)
|
|
8503
|
+
return null;
|
|
8504
|
+
const value = run.stdout.trim();
|
|
8505
|
+
return value ? value : null;
|
|
8506
|
+
};
|
|
8480
8507
|
var MAX_UNTRACKED_BYTES = 5 * 1024 * 1024;
|
|
8508
|
+
function currentBranch(cwd) {
|
|
8509
|
+
return line(git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
|
|
8510
|
+
}
|
|
8481
8511
|
|
|
8482
8512
|
// packages/workit-core/src/core/release-tracks.ts
|
|
8483
8513
|
var KNOWN_FIELDS = new Set([
|
|
@@ -8540,6 +8570,160 @@ var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
|
8540
8570
|
var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8541
8571
|
var homePattern = new RegExp(`${escapeRegExp(os.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
8542
8572
|
|
|
8573
|
+
// packages/workit-core/src/store/paths.ts
|
|
8574
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
8575
|
+
import fs from "node:fs";
|
|
8576
|
+
import path2 from "node:path";
|
|
8577
|
+
var NOT_A_REPO = /not a git repository \(or any (of the parent directories|parent up to)/u;
|
|
8578
|
+
var gitRun = (cwd, args) => {
|
|
8579
|
+
const run = spawnSync2("git", args, {
|
|
8580
|
+
cwd,
|
|
8581
|
+
encoding: "utf8",
|
|
8582
|
+
timeout: 20000,
|
|
8583
|
+
killSignal: "SIGKILL",
|
|
8584
|
+
windowsHide: true,
|
|
8585
|
+
env: {
|
|
8586
|
+
...process.env,
|
|
8587
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
8588
|
+
GIT_OPTIONAL_LOCKS: "0",
|
|
8589
|
+
LC_ALL: "C",
|
|
8590
|
+
LANGUAGE: "C"
|
|
8591
|
+
}
|
|
8592
|
+
});
|
|
8593
|
+
const error = run.error;
|
|
8594
|
+
return {
|
|
8595
|
+
ok: run.status === 0,
|
|
8596
|
+
stdout: run.stdout ?? "",
|
|
8597
|
+
stderr: error ? String(error.message) : run.stderr ?? "",
|
|
8598
|
+
missing: error?.code === "ENOENT"
|
|
8599
|
+
};
|
|
8600
|
+
};
|
|
8601
|
+
var real = (file) => {
|
|
8602
|
+
try {
|
|
8603
|
+
return fs.realpathSync.native(file);
|
|
8604
|
+
} catch {
|
|
8605
|
+
return file;
|
|
8606
|
+
}
|
|
8607
|
+
};
|
|
8608
|
+
var DISCOVERY_ENV = [
|
|
8609
|
+
"GIT_DIR",
|
|
8610
|
+
"GIT_COMMON_DIR",
|
|
8611
|
+
"GIT_WORK_TREE",
|
|
8612
|
+
"GIT_CEILING_DIRECTORIES",
|
|
8613
|
+
"GIT_DISCOVERY_ACROSS_FILESYSTEM"
|
|
8614
|
+
];
|
|
8615
|
+
var isGitDir = (dir) => {
|
|
8616
|
+
try {
|
|
8617
|
+
return fs.statSync(path2.join(dir, "HEAD")).isFile() && fs.statSync(path2.join(dir, "objects")).isDirectory() && fs.statSync(path2.join(dir, "refs")).isDirectory();
|
|
8618
|
+
} catch {
|
|
8619
|
+
return false;
|
|
8620
|
+
}
|
|
8621
|
+
};
|
|
8622
|
+
var reftableRefs = (common) => {
|
|
8623
|
+
try {
|
|
8624
|
+
return /^\s*refstorage\s*=\s*reftable\s*$/imu.test(fs.readFileSync(path2.join(common, "config"), "utf8"));
|
|
8625
|
+
} catch {
|
|
8626
|
+
return false;
|
|
8627
|
+
}
|
|
8628
|
+
};
|
|
8629
|
+
function fastGit(root) {
|
|
8630
|
+
if (DISCOVERY_ENV.some((name) => process.env[name]))
|
|
8631
|
+
return null;
|
|
8632
|
+
let dir = real(root);
|
|
8633
|
+
let device = null;
|
|
8634
|
+
for (;; ) {
|
|
8635
|
+
let stat;
|
|
8636
|
+
try {
|
|
8637
|
+
stat = fs.statSync(dir);
|
|
8638
|
+
} catch {
|
|
8639
|
+
return null;
|
|
8640
|
+
}
|
|
8641
|
+
if (device !== null && stat.dev !== device)
|
|
8642
|
+
return { kind: "none" };
|
|
8643
|
+
device = stat.dev;
|
|
8644
|
+
const dotGit = path2.join(dir, ".git");
|
|
8645
|
+
let entry = null;
|
|
8646
|
+
try {
|
|
8647
|
+
entry = fs.statSync(dotGit);
|
|
8648
|
+
} catch {}
|
|
8649
|
+
let gitDir = null;
|
|
8650
|
+
let top = null;
|
|
8651
|
+
if (entry) {
|
|
8652
|
+
top = dir;
|
|
8653
|
+
if (entry.isDirectory())
|
|
8654
|
+
gitDir = dotGit;
|
|
8655
|
+
else if (entry.isFile()) {
|
|
8656
|
+
let text = "";
|
|
8657
|
+
try {
|
|
8658
|
+
text = fs.readFileSync(dotGit, "utf8");
|
|
8659
|
+
} catch {
|
|
8660
|
+
return null;
|
|
8661
|
+
}
|
|
8662
|
+
const match = /^gitdir: (.+)$/mu.exec(text);
|
|
8663
|
+
if (!match)
|
|
8664
|
+
return null;
|
|
8665
|
+
gitDir = path2.resolve(dir, match[1].trim());
|
|
8666
|
+
} else
|
|
8667
|
+
return null;
|
|
8668
|
+
if (!fs.existsSync(path2.join(gitDir, "HEAD")))
|
|
8669
|
+
return null;
|
|
8670
|
+
} else if (isGitDir(dir))
|
|
8671
|
+
gitDir = dir;
|
|
8672
|
+
if (gitDir) {
|
|
8673
|
+
let common = gitDir;
|
|
8674
|
+
try {
|
|
8675
|
+
common = path2.resolve(gitDir, fs.readFileSync(path2.join(gitDir, "commondir"), "utf8").trim());
|
|
8676
|
+
} catch {}
|
|
8677
|
+
if (!fs.existsSync(path2.join(common, "objects")))
|
|
8678
|
+
return null;
|
|
8679
|
+
return {
|
|
8680
|
+
kind: "repo",
|
|
8681
|
+
common: real(common),
|
|
8682
|
+
gitDir: real(gitDir),
|
|
8683
|
+
top: top === null ? null : real(top),
|
|
8684
|
+
reftable: reftableRefs(common)
|
|
8685
|
+
};
|
|
8686
|
+
}
|
|
8687
|
+
const parent = path2.dirname(dir);
|
|
8688
|
+
if (parent === dir)
|
|
8689
|
+
return { kind: "none" };
|
|
8690
|
+
dir = parent;
|
|
8691
|
+
}
|
|
8692
|
+
}
|
|
8693
|
+
function resolveStore(root) {
|
|
8694
|
+
root = path2.resolve(root);
|
|
8695
|
+
let directory = false;
|
|
8696
|
+
try {
|
|
8697
|
+
directory = fs.statSync(root).isDirectory();
|
|
8698
|
+
} catch {}
|
|
8699
|
+
if (!directory)
|
|
8700
|
+
return { dir: path2.join(root, ".workit"), shared: false, top: null };
|
|
8701
|
+
const fast = fastGit(root);
|
|
8702
|
+
if (fast?.kind === "none")
|
|
8703
|
+
return { dir: path2.join(root, ".workit"), shared: false, top: null };
|
|
8704
|
+
if (fast?.kind === "repo")
|
|
8705
|
+
return {
|
|
8706
|
+
dir: path2.join(fast.common, "workit"),
|
|
8707
|
+
shared: true,
|
|
8708
|
+
top: fast.top,
|
|
8709
|
+
git: { gitDir: fast.gitDir, top: fast.top, reftable: fast.reftable }
|
|
8710
|
+
};
|
|
8711
|
+
const run = gitRun(root, ["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
8712
|
+
const common = run.stdout.trim();
|
|
8713
|
+
if (run.ok && common) {
|
|
8714
|
+
const top = gitRun(root, ["rev-parse", "--path-format=absolute", "--show-toplevel"]);
|
|
8715
|
+
return {
|
|
8716
|
+
dir: path2.join(real(path2.resolve(root, common)), "workit"),
|
|
8717
|
+
shared: true,
|
|
8718
|
+
top: top.ok && top.stdout.trim() ? real(top.stdout.trim()) : null
|
|
8719
|
+
};
|
|
8720
|
+
}
|
|
8721
|
+
if (run.missing || !run.ok && NOT_A_REPO.test(run.stderr))
|
|
8722
|
+
return { dir: path2.join(root, ".workit"), shared: false, top: null };
|
|
8723
|
+
return new Error(`cannot locate the workit store: git rev-parse failed (${run.stderr.trim().split(`
|
|
8724
|
+
`)[0] || "no output"}); fix the repository (git status should work here)`);
|
|
8725
|
+
}
|
|
8726
|
+
|
|
8543
8727
|
// packages/workit-core/src/host-session.ts
|
|
8544
8728
|
var OWN_CHILD_SHELL = new Set(["opencode", "pi"]);
|
|
8545
8729
|
var SESSION_UNSAFE = /[^A-Za-z0-9_.:@/+-]/g;
|
|
@@ -8551,20 +8735,20 @@ function childSessionId(lead, child) {
|
|
|
8551
8735
|
|
|
8552
8736
|
// packages/workit-core/src/core/package-root.ts
|
|
8553
8737
|
import { existsSync } from "node:fs";
|
|
8554
|
-
import
|
|
8738
|
+
import path3 from "node:path";
|
|
8555
8739
|
import { fileURLToPath } from "node:url";
|
|
8556
8740
|
var packageRoot = () => {
|
|
8557
|
-
let dir =
|
|
8741
|
+
let dir = path3.dirname(fileURLToPath(import.meta.url));
|
|
8558
8742
|
while (true) {
|
|
8559
|
-
const parent =
|
|
8560
|
-
if (existsSync(
|
|
8743
|
+
const parent = path3.dirname(dir);
|
|
8744
|
+
if (existsSync(path3.join(dir, "package.json")) || parent === dir)
|
|
8561
8745
|
return dir;
|
|
8562
8746
|
dir = parent;
|
|
8563
8747
|
}
|
|
8564
8748
|
};
|
|
8565
8749
|
var assetRoot = () => {
|
|
8566
8750
|
const root = packageRoot();
|
|
8567
|
-
const assets =
|
|
8751
|
+
const assets = path3.join(root, "assets");
|
|
8568
8752
|
return existsSync(assets) ? assets : root;
|
|
8569
8753
|
};
|
|
8570
8754
|
|
|
@@ -8617,6 +8801,57 @@ var STALE_TEMPORARY_MS = 60 * 60000;
|
|
|
8617
8801
|
var origins = new Map;
|
|
8618
8802
|
var heldInProcess = new Map;
|
|
8619
8803
|
// packages/workit-core/src/ledger.ts
|
|
8804
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
8805
|
+
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
8806
|
+
import fs3 from "node:fs";
|
|
8807
|
+
import path5 from "node:path";
|
|
8808
|
+
|
|
8809
|
+
// packages/workit-core/src/hooks/standing-signal.ts
|
|
8810
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
8811
|
+
import fs2 from "node:fs";
|
|
8812
|
+
import path4 from "node:path";
|
|
8813
|
+
var gitStoreDir = (cwd) => {
|
|
8814
|
+
try {
|
|
8815
|
+
for (let dir = path4.resolve(cwd);; dir = path4.dirname(dir)) {
|
|
8816
|
+
const dotGit = path4.join(dir, ".git");
|
|
8817
|
+
if (fs2.existsSync(dotGit)) {
|
|
8818
|
+
let gitDir = dotGit;
|
|
8819
|
+
if (fs2.statSync(dotGit).isFile()) {
|
|
8820
|
+
const target = /^gitdir:\s*(.+)$/mu.exec(fs2.readFileSync(dotGit, "utf8"))?.[1]?.trim();
|
|
8821
|
+
if (!target)
|
|
8822
|
+
return null;
|
|
8823
|
+
gitDir = path4.resolve(dir, target);
|
|
8824
|
+
const common = path4.join(gitDir, "commondir");
|
|
8825
|
+
if (fs2.existsSync(common))
|
|
8826
|
+
gitDir = path4.resolve(gitDir, fs2.readFileSync(common, "utf8").trim());
|
|
8827
|
+
}
|
|
8828
|
+
return path4.join(gitDir, "workit");
|
|
8829
|
+
}
|
|
8830
|
+
if (path4.dirname(dir) === dir)
|
|
8831
|
+
return null;
|
|
8832
|
+
}
|
|
8833
|
+
} catch {
|
|
8834
|
+
return null;
|
|
8835
|
+
}
|
|
8836
|
+
};
|
|
8837
|
+
var standingRevFile = (store) => path4.join(store, "standing", "rev");
|
|
8838
|
+
var standingSeenFile = (store, session, agentId) => path4.join(store, "standing", "seen", `${createHash2("sha256").update(`${session}\x00${agentId ?? ""}`).digest("hex").slice(0, 32)}.json`);
|
|
8839
|
+
var readStandingRev = (store) => {
|
|
8840
|
+
try {
|
|
8841
|
+
return fs2.readFileSync(standingRevFile(store), "utf8").trim() || null;
|
|
8842
|
+
} catch {
|
|
8843
|
+
return null;
|
|
8844
|
+
}
|
|
8845
|
+
};
|
|
8846
|
+
var writeStandingSeen = (file, seen) => {
|
|
8847
|
+
try {
|
|
8848
|
+
fs2.mkdirSync(path4.dirname(file), { recursive: true });
|
|
8849
|
+
fs2.writeFileSync(file, JSON.stringify(seen));
|
|
8850
|
+
} catch {}
|
|
8851
|
+
};
|
|
8852
|
+
|
|
8853
|
+
// packages/workit-core/src/ledger.ts
|
|
8854
|
+
var LEDGER_VERSION = 1;
|
|
8620
8855
|
var PASSING = new Set(["verified", "tests-verified", "type-check-only"]);
|
|
8621
8856
|
var FAILING = new Set(["failed", "blocked"]);
|
|
8622
8857
|
var STRONG_RESULTS = new Set(["verified", "tests-verified"]);
|
|
@@ -8626,6 +8861,50 @@ var PR_ROW_TYPES = new Set([
|
|
|
8626
8861
|
"pr.merged",
|
|
8627
8862
|
"pr.linked"
|
|
8628
8863
|
]);
|
|
8864
|
+
var err = (code, error, unblock) => ({
|
|
8865
|
+
ok: false,
|
|
8866
|
+
code,
|
|
8867
|
+
error,
|
|
8868
|
+
...unblock ? { unblock } : {}
|
|
8869
|
+
});
|
|
8870
|
+
var gitRun2 = (cwd, args, timeoutMs = GIT_TIMEOUTS.local) => {
|
|
8871
|
+
const run = spawnSync3("git", args, {
|
|
8872
|
+
cwd,
|
|
8873
|
+
encoding: "utf8",
|
|
8874
|
+
timeout: timeoutMs,
|
|
8875
|
+
killSignal: "SIGKILL",
|
|
8876
|
+
windowsHide: true,
|
|
8877
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
8878
|
+
env: {
|
|
8879
|
+
...process.env,
|
|
8880
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
8881
|
+
GIT_OPTIONAL_LOCKS: "0",
|
|
8882
|
+
LC_ALL: "C",
|
|
8883
|
+
LANGUAGE: "C"
|
|
8884
|
+
}
|
|
8885
|
+
});
|
|
8886
|
+
return {
|
|
8887
|
+
ok: run.status === 0,
|
|
8888
|
+
stdout: run.stdout ?? "",
|
|
8889
|
+
stderr: run.error ? String(run.error.message) : run.stderr ?? ""
|
|
8890
|
+
};
|
|
8891
|
+
};
|
|
8892
|
+
var git2 = (cwd, args) => {
|
|
8893
|
+
const run = gitRun2(cwd, args);
|
|
8894
|
+
const value = run.ok ? run.stdout.trim() : "";
|
|
8895
|
+
return value ? value : null;
|
|
8896
|
+
};
|
|
8897
|
+
var safeRef = (value) => value.length > 0 && !value.startsWith("-");
|
|
8898
|
+
function storeRoot(cwd) {
|
|
8899
|
+
const location = resolveStore(path5.resolve(cwd));
|
|
8900
|
+
if (location instanceof Error)
|
|
8901
|
+
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");
|
|
8902
|
+
return { ok: true, value: { root: location.dir, shared: location.shared } };
|
|
8903
|
+
}
|
|
8904
|
+
function ledgerPath(cwd) {
|
|
8905
|
+
const root = storeRoot(cwd);
|
|
8906
|
+
return root.ok ? { ok: true, value: path5.join(root.value.root, "ledger", "ledger.jsonl") } : root;
|
|
8907
|
+
}
|
|
8629
8908
|
var NETWORK_FS_TYPES = new Set([
|
|
8630
8909
|
26985,
|
|
8631
8910
|
20859,
|
|
@@ -8638,9 +8917,219 @@ var NETWORK_FS_TYPES = new Set([
|
|
|
8638
8917
|
1196443219,
|
|
8639
8918
|
198183888
|
|
8640
8919
|
]);
|
|
8920
|
+
var sha2562 = (text) => createHash3("sha256").update(text).digest("hex");
|
|
8921
|
+
var chainHash = (prevHash, body) => sha2562(`${prevHash ?? ""}
|
|
8922
|
+
${body}`);
|
|
8641
8923
|
var TAIL_BYTES = 64 * 1024;
|
|
8924
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8925
|
+
var str2 = (value) => typeof value === "string" ? value : null;
|
|
8926
|
+
var normalizeActor = (value) => {
|
|
8927
|
+
const actor = isRecord(value) ? value : {};
|
|
8928
|
+
return {
|
|
8929
|
+
host: str2(actor.host) ?? "unknown",
|
|
8930
|
+
session: str2(actor.session),
|
|
8931
|
+
agentId: str2(actor.agentId)
|
|
8932
|
+
};
|
|
8933
|
+
};
|
|
8934
|
+
function supersedeAllowed(by, target, onBranch = (row) => (by.branch ?? null) === (row.branch ?? null)) {
|
|
8935
|
+
if (by.type !== target.type)
|
|
8936
|
+
return `a ${by.type} row cannot supersede a ${target.type} row`;
|
|
8937
|
+
if (!by.actor.session || by.actor.session !== target.actor.session)
|
|
8938
|
+
return "only the session that wrote a row can supersede it";
|
|
8939
|
+
if (!onBranch(target))
|
|
8940
|
+
return `the row is on another branch (${String(target.branch ?? "none")}); a row supersedes only one on its own branch`;
|
|
8941
|
+
if (by.type === "verdict" && (by.kind ?? "review") !== (target.kind ?? "review"))
|
|
8942
|
+
return `a ${String(by.kind ?? "review")} verdict cannot supersede a ${String(target.kind ?? "review")} verdict; record it with --kind ${String(target.kind ?? "review")}`;
|
|
8943
|
+
if (by.type === "verdict" && by.self === true && target.self !== true)
|
|
8944
|
+
return "a self verdict cannot replace an independent verdict";
|
|
8945
|
+
return null;
|
|
8946
|
+
}
|
|
8947
|
+
function readLedger(cwd, options = {}) {
|
|
8948
|
+
const file = ledgerPath(cwd);
|
|
8949
|
+
if (!file.ok)
|
|
8950
|
+
return file;
|
|
8951
|
+
let text = "";
|
|
8952
|
+
let stat = null;
|
|
8953
|
+
try {
|
|
8954
|
+
stat = fs3.statSync(file.value);
|
|
8955
|
+
text = fs3.readFileSync(file.value, "utf8");
|
|
8956
|
+
} catch (error) {
|
|
8957
|
+
if (error.code === "ENOENT")
|
|
8958
|
+
return {
|
|
8959
|
+
ok: true,
|
|
8960
|
+
value: {
|
|
8961
|
+
path: file.value,
|
|
8962
|
+
rows: [],
|
|
8963
|
+
skipped: 0,
|
|
8964
|
+
integrity: options.integrity ? { chained: 0, legacy: 0, unverified: [] } : null
|
|
8965
|
+
}
|
|
8966
|
+
};
|
|
8967
|
+
return err("unavailable", `cannot read ${file.value}: ${error.message}`);
|
|
8968
|
+
}
|
|
8969
|
+
const rows = [];
|
|
8970
|
+
let skipped = 0;
|
|
8971
|
+
const integrity = { chained: 0, legacy: 0, unverified: [] };
|
|
8972
|
+
const earlier = new Set([null]);
|
|
8973
|
+
let chainStarted = false;
|
|
8974
|
+
const ids = new Set;
|
|
8975
|
+
for (const raw of text.split(`
|
|
8976
|
+
`)) {
|
|
8977
|
+
const trimmed = raw.trim();
|
|
8978
|
+
if (!trimmed)
|
|
8979
|
+
continue;
|
|
8980
|
+
const linked = (prevHash) => earlier.has(prevHash);
|
|
8981
|
+
if (options.integrity)
|
|
8982
|
+
earlier.add(sha2562(trimmed));
|
|
8983
|
+
let parsed;
|
|
8984
|
+
try {
|
|
8985
|
+
parsed = JSON.parse(trimmed);
|
|
8986
|
+
} catch {
|
|
8987
|
+
skipped += 1;
|
|
8988
|
+
continue;
|
|
8989
|
+
}
|
|
8990
|
+
if (!isRecord(parsed) || !str2(parsed.id) || !str2(parsed.type) || !str2(parsed.at)) {
|
|
8991
|
+
skipped += 1;
|
|
8992
|
+
continue;
|
|
8993
|
+
}
|
|
8994
|
+
let rowIntegrity = options.integrity ? "verified" : undefined;
|
|
8995
|
+
let reason = null;
|
|
8996
|
+
if (!options.integrity) {} else if (typeof parsed.rowHash === "string") {
|
|
8997
|
+
chainStarted = true;
|
|
8998
|
+
const { rowHash, ...body } = parsed;
|
|
8999
|
+
const prevHash = str2(parsed.prevHash);
|
|
9000
|
+
if (chainHash(prevHash, JSON.stringify(body)) !== rowHash)
|
|
9001
|
+
reason = "hash_mismatch";
|
|
9002
|
+
else if (!linked(prevHash))
|
|
9003
|
+
reason = "broken_link";
|
|
9004
|
+
} else if (chainStarted)
|
|
9005
|
+
reason = "unsigned";
|
|
9006
|
+
else
|
|
9007
|
+
rowIntegrity = "legacy";
|
|
9008
|
+
if (options.integrity && !reason && ids.has(parsed.id))
|
|
9009
|
+
reason = "duplicate_id";
|
|
9010
|
+
if (options.integrity)
|
|
9011
|
+
ids.add(parsed.id);
|
|
9012
|
+
if (reason)
|
|
9013
|
+
rowIntegrity = "unverified";
|
|
9014
|
+
const pr = typeof parsed.pr === "number" && Number.isInteger(parsed.pr) ? parsed.pr : undefined;
|
|
9015
|
+
const row = {
|
|
9016
|
+
...parsed,
|
|
9017
|
+
v: typeof parsed.v === "number" ? parsed.v : LEDGER_VERSION,
|
|
9018
|
+
id: parsed.id,
|
|
9019
|
+
at: parsed.at,
|
|
9020
|
+
type: parsed.type,
|
|
9021
|
+
actor: normalizeActor(parsed.actor),
|
|
9022
|
+
branch: str2(parsed.branch),
|
|
9023
|
+
head: str2(parsed.head),
|
|
9024
|
+
base: str2(parsed.base),
|
|
9025
|
+
baseSha: str2(parsed.baseSha),
|
|
9026
|
+
patchId: str2(parsed.patchId),
|
|
9027
|
+
diffHash: str2(parsed.diffHash),
|
|
9028
|
+
tree: str2(parsed.tree),
|
|
9029
|
+
dirty: typeof parsed.dirty === "boolean" ? parsed.dirty : null,
|
|
9030
|
+
...pr === undefined ? {} : { pr },
|
|
9031
|
+
...str2(parsed.supersedes) ? { supersedes: parsed.supersedes } : {},
|
|
9032
|
+
seq: rows.length + 1,
|
|
9033
|
+
superseded: false,
|
|
9034
|
+
supersedeIgnored: false,
|
|
9035
|
+
...rowIntegrity ? { integrity: rowIntegrity } : {},
|
|
9036
|
+
...reason ? { integrityReason: reason } : {}
|
|
9037
|
+
};
|
|
9038
|
+
rows.push(row);
|
|
9039
|
+
if (!options.integrity)
|
|
9040
|
+
continue;
|
|
9041
|
+
if (rowIntegrity === "verified")
|
|
9042
|
+
integrity.chained += 1;
|
|
9043
|
+
else if (rowIntegrity === "legacy")
|
|
9044
|
+
integrity.legacy += 1;
|
|
9045
|
+
else if (reason)
|
|
9046
|
+
integrity.unverified.push({
|
|
9047
|
+
seq: row.seq,
|
|
9048
|
+
id: row.id,
|
|
9049
|
+
type: row.type,
|
|
9050
|
+
branch: row.branch,
|
|
9051
|
+
reason
|
|
9052
|
+
});
|
|
9053
|
+
}
|
|
9054
|
+
const scopes = new Map;
|
|
9055
|
+
const scopeOf = (branch) => {
|
|
9056
|
+
let scope = scopes.get(branch);
|
|
9057
|
+
if (!scope)
|
|
9058
|
+
scopes.set(branch, scope = branchScope(cwd, branch));
|
|
9059
|
+
return scope;
|
|
9060
|
+
};
|
|
9061
|
+
const byId = new Map;
|
|
9062
|
+
for (const row of rows) {
|
|
9063
|
+
const target = row.supersedes ? byId.get(row.supersedes) : undefined;
|
|
9064
|
+
if (target && row.integrity !== "unverified" && supersedeAllowed(row, target, renameAwareBranch(scopeOf, row.branch)) === null)
|
|
9065
|
+
target.superseded = true;
|
|
9066
|
+
else if (row.supersedes)
|
|
9067
|
+
row.supersedeIgnored = true;
|
|
9068
|
+
if (!byId.has(row.id))
|
|
9069
|
+
byId.set(row.id, row);
|
|
9070
|
+
}
|
|
9071
|
+
if (options.integrity && stat && Buffer.byteLength(text) === stat.size)
|
|
9072
|
+
tamperCache.set(file.value, {
|
|
9073
|
+
size: stat.size,
|
|
9074
|
+
stamp: fileStamp(stat),
|
|
9075
|
+
breaks: integrity.unverified.filter((row) => TAMPER_REASONS.has(row.reason))
|
|
9076
|
+
});
|
|
9077
|
+
return {
|
|
9078
|
+
ok: true,
|
|
9079
|
+
value: { path: file.value, rows, skipped, integrity: options.integrity ? integrity : null }
|
|
9080
|
+
};
|
|
9081
|
+
}
|
|
8642
9082
|
var TAMPER_REASONS = new Set(["hash_mismatch", "broken_link"]);
|
|
8643
9083
|
var tamperCache = new Map;
|
|
9084
|
+
var fileStamp = (stat) => `${stat.ino}:${stat.mtimeMs}:${stat.ctimeMs}`;
|
|
9085
|
+
var RENAMED = /^branch: renamed refs\/heads\/(.+) to refs\/heads\/(.+)$/iu;
|
|
9086
|
+
function branchScope(cwd, branch) {
|
|
9087
|
+
const renamedAt = new Map;
|
|
9088
|
+
let since = Number.NEGATIVE_INFINITY;
|
|
9089
|
+
if (safeRef(branch)) {
|
|
9090
|
+
const log = git2(cwd, [
|
|
9091
|
+
"log",
|
|
9092
|
+
"-g",
|
|
9093
|
+
"--date=unix",
|
|
9094
|
+
"--format=%gd%x09%gs",
|
|
9095
|
+
`refs/heads/${branch}`,
|
|
9096
|
+
"--"
|
|
9097
|
+
]);
|
|
9098
|
+
for (const line of (log ?? "").split(`
|
|
9099
|
+
`)) {
|
|
9100
|
+
const [selector = "", subject = ""] = line.split("\t");
|
|
9101
|
+
const seconds = Number(/@\{(\d+)\}$/u.exec(selector)?.[1]);
|
|
9102
|
+
if (!Number.isFinite(seconds))
|
|
9103
|
+
continue;
|
|
9104
|
+
since = seconds * 1000;
|
|
9105
|
+
const match = RENAMED.exec(subject);
|
|
9106
|
+
if (!match || match[1] === branch)
|
|
9107
|
+
continue;
|
|
9108
|
+
const until = (seconds + 1) * 1000;
|
|
9109
|
+
renamedAt.set(match[1], Math.max(renamedAt.get(match[1]) ?? 0, until));
|
|
9110
|
+
}
|
|
9111
|
+
}
|
|
9112
|
+
return (row) => {
|
|
9113
|
+
if (row.branch === branch)
|
|
9114
|
+
return true;
|
|
9115
|
+
const until = row.branch === null ? undefined : renamedAt.get(row.branch);
|
|
9116
|
+
if (until === undefined)
|
|
9117
|
+
return false;
|
|
9118
|
+
const at = Date.parse(row.at);
|
|
9119
|
+
return at >= since && at <= until;
|
|
9120
|
+
};
|
|
9121
|
+
}
|
|
9122
|
+
var renameAwareBranch = (scopeOf, branch) => {
|
|
9123
|
+
return (target) => {
|
|
9124
|
+
const own = typeof branch === "string" ? branch : null;
|
|
9125
|
+
const theirs = typeof target.branch === "string" ? target.branch : null;
|
|
9126
|
+
if (own === theirs)
|
|
9127
|
+
return true;
|
|
9128
|
+
if (own === null || theirs === null || typeof target.at !== "string")
|
|
9129
|
+
return false;
|
|
9130
|
+
return scopeOf(own)({ branch: theirs, at: target.at });
|
|
9131
|
+
};
|
|
9132
|
+
};
|
|
8644
9133
|
var TRUST_REASONS = new Set([
|
|
8645
9134
|
"unsigned",
|
|
8646
9135
|
"hash_mismatch",
|
|
@@ -8656,6 +9145,28 @@ var SHELL_VOUCHED_HOSTS = new Set([
|
|
|
8656
9145
|
"codex_cli",
|
|
8657
9146
|
"codex_desktop"
|
|
8658
9147
|
]);
|
|
9148
|
+
var fromLead = (row, leads) => leads === null || row.actor.session !== null && leads.includes(row.actor.session);
|
|
9149
|
+
function activeStanding(rows, fanout, leads = null) {
|
|
9150
|
+
const active = [];
|
|
9151
|
+
for (const row of rows) {
|
|
9152
|
+
if (row.fanout !== fanout || !fromLead(row, leads))
|
|
9153
|
+
continue;
|
|
9154
|
+
if (row.type === "standing" && typeof row.what === "string" && row.what.trim()) {
|
|
9155
|
+
if (!row.superseded)
|
|
9156
|
+
active.push(row);
|
|
9157
|
+
} else if (row.type === "standing.cleared") {
|
|
9158
|
+
const target = str2(row.target);
|
|
9159
|
+
if (target === null)
|
|
9160
|
+
active.length = 0;
|
|
9161
|
+
else {
|
|
9162
|
+
const index = active.findIndex((order) => order.id === target);
|
|
9163
|
+
if (index >= 0)
|
|
9164
|
+
active.splice(index, 1);
|
|
9165
|
+
}
|
|
9166
|
+
}
|
|
9167
|
+
}
|
|
9168
|
+
return active;
|
|
9169
|
+
}
|
|
8659
9170
|
var OBSERVED_ONLY = new Set([
|
|
8660
9171
|
"check",
|
|
8661
9172
|
"merge.unverified",
|
|
@@ -8850,12 +9361,82 @@ var contextReadSchema = object({
|
|
|
8850
9361
|
planPath: string2().optional(),
|
|
8851
9362
|
cwd: string2().min(1).optional()
|
|
8852
9363
|
}).strict();
|
|
9364
|
+
// packages/workit-core/src/hooks/standing.ts
|
|
9365
|
+
import fs4 from "node:fs";
|
|
9366
|
+
import path6 from "node:path";
|
|
9367
|
+
var readPlans = (store) => {
|
|
9368
|
+
const dir = path6.join(store, "fanouts");
|
|
9369
|
+
let names;
|
|
9370
|
+
try {
|
|
9371
|
+
names = fs4.readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
9372
|
+
} catch {
|
|
9373
|
+
return [];
|
|
9374
|
+
}
|
|
9375
|
+
const plans = [];
|
|
9376
|
+
for (const name of names) {
|
|
9377
|
+
try {
|
|
9378
|
+
const raw = JSON.parse(fs4.readFileSync(path6.join(dir, name), "utf8"));
|
|
9379
|
+
if (typeof raw.name !== "string" || !Array.isArray(raw.slices))
|
|
9380
|
+
continue;
|
|
9381
|
+
const texts = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string" && item !== "") : [];
|
|
9382
|
+
plans.push({
|
|
9383
|
+
name: raw.name,
|
|
9384
|
+
leads: texts([raw.leadSession, ...texts(raw.formerLeads)]),
|
|
9385
|
+
branches: texts(raw.slices.map((slice) => slice && typeof slice === "object" ? slice.branch : null))
|
|
9386
|
+
});
|
|
9387
|
+
} catch {}
|
|
9388
|
+
}
|
|
9389
|
+
return plans;
|
|
9390
|
+
};
|
|
9391
|
+
var leadOf = (input) => input.session.parentId ?? (input.session.agentId ? input.session.id : null) ?? (input.session.id.includes(":") ? input.session.id.split(":")[0] : null);
|
|
9392
|
+
var worksFor = (plan, input, branch) => {
|
|
9393
|
+
const session = input.session.id;
|
|
9394
|
+
if (plan.leads.includes(session) && !input.session.agentId)
|
|
9395
|
+
return false;
|
|
9396
|
+
const lead = leadOf(input);
|
|
9397
|
+
if (lead && plan.leads.includes(lead))
|
|
9398
|
+
return true;
|
|
9399
|
+
if (plan.leads.some((each) => session.startsWith(`${each}-w-`)))
|
|
9400
|
+
return true;
|
|
9401
|
+
const current = branch();
|
|
9402
|
+
return current !== null && plan.branches.includes(current);
|
|
9403
|
+
};
|
|
9404
|
+
var standingFor = (input, store, rev) => {
|
|
9405
|
+
const orders = new Map;
|
|
9406
|
+
const ledger = readLedger(input.cwd);
|
|
9407
|
+
const rows = ledger.ok ? ledger.value.rows : [];
|
|
9408
|
+
let branch;
|
|
9409
|
+
const lazyBranch = () => branch === undefined ? branch = currentBranch(input.cwd) : branch;
|
|
9410
|
+
for (const plan of readPlans(store))
|
|
9411
|
+
if (worksFor(plan, input, lazyBranch))
|
|
9412
|
+
for (const row of activeStanding(rows, plan.name, plan.leads.length ? plan.leads : null))
|
|
9413
|
+
orders.set(row.id, row);
|
|
9414
|
+
return { rev, orders, rows };
|
|
9415
|
+
};
|
|
9416
|
+
var located = (input) => {
|
|
9417
|
+
const store = input.session.id ? gitStoreDir(input.cwd) : null;
|
|
9418
|
+
const rev = store ? readStandingRev(store) : null;
|
|
9419
|
+
if (!store || rev === null)
|
|
9420
|
+
return null;
|
|
9421
|
+
return { store, rev, file: standingSeenFile(store, input.session.id, input.session.agentId) };
|
|
9422
|
+
};
|
|
9423
|
+
var seedStanding = (input) => {
|
|
9424
|
+
try {
|
|
9425
|
+
const where = located(input);
|
|
9426
|
+
if (!where)
|
|
9427
|
+
return;
|
|
9428
|
+
const now = standingFor(input, where.store, where.rev);
|
|
9429
|
+
writeStandingSeen(where.file, { rev: where.rev, ids: [...now.orders.keys()] });
|
|
9430
|
+
} catch {}
|
|
9431
|
+
};
|
|
9432
|
+
var sinceStart = new Map;
|
|
9433
|
+
|
|
8853
9434
|
// packages/workit-pi/src/worker-protocol.ts
|
|
8854
9435
|
var MAX_WORKER_LINE_BYTES = 64 * 1024;
|
|
8855
9436
|
var MAX_WORKER_STDERR_BYTES = 64 * 1024;
|
|
8856
|
-
var
|
|
9437
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
8857
9438
|
var parseEvent = (value) => {
|
|
8858
|
-
if (!
|
|
9439
|
+
if (!isRecord2(value) || typeof value.type !== "string")
|
|
8859
9440
|
return null;
|
|
8860
9441
|
if (value.type === "workit_worker_ready") {
|
|
8861
9442
|
if (typeof value.workerId !== "string" || typeof value.sessionId !== "string")
|
|
@@ -9013,6 +9594,14 @@ function launchWorker(assignment, options) {
|
|
|
9013
9594
|
WORKIT_PI_WORKER_ROLE: assignment.role,
|
|
9014
9595
|
WORKIT_PI_WORKER_SCOPE: JSON.stringify(assignment.scope)
|
|
9015
9596
|
};
|
|
9597
|
+
seedStanding({
|
|
9598
|
+
host: "pi",
|
|
9599
|
+
cwd: spec.cwd,
|
|
9600
|
+
session: { id: env.WORKIT_SESSION_ID, agentId: null, agentType: null, parentId: null },
|
|
9601
|
+
permissionMode: null,
|
|
9602
|
+
transcriptPath: null,
|
|
9603
|
+
event: { kind: "session.start", source: "startup" }
|
|
9604
|
+
});
|
|
9016
9605
|
try {
|
|
9017
9606
|
const spawn = options.spawn ?? ((command, args, spawnOptions) => nodeSpawn(command, args, spawnOptions));
|
|
9018
9607
|
handle.spec = { ...spec, env };
|