@krapht/ork 1.0.0-alpha.11 → 1.0.0-alpha.13
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/{__build_info__-CIchF6nr.mjs → __build_info__-Da73_nBs.mjs} +4 -3
- package/dist/attach-E6NNyA3T.mjs +89 -0
- package/dist/bin.mjs +213 -1230
- package/dist/{decide-B6PnKeqo.mjs → builtin-files-n6o6oWpB.mjs} +3 -51
- package/dist/{chips-BA7SrrH5.mjs → chips-CyeB_rhR.mjs} +1 -1
- package/dist/{clean-Di-KT7Mf.mjs → clean-Bh4KZgzc.mjs} +1 -1
- package/dist/{completion-C5D0sEs5.mjs → completion-SNNNxnv9.mjs} +7 -6
- package/dist/{context-BaNshWr9.mjs → context-DHudLA5e.mjs} +6 -6
- package/dist/decide-DuIHACvH.mjs +50 -0
- package/dist/{find-BicBbGMg.mjs → find-CjsNYAAf.mjs} +1 -1
- package/dist/{format-lWhN-jYR.mjs → format-C60TFpRe.mjs} +5 -85
- package/dist/{help-groups-BwYoAWsh.mjs → help-groups-CyfPWlST.mjs} +8 -0
- package/dist/{in-a-run-CgkVouyG.mjs → in-a-run-BYjTXaST.mjs} +4 -2
- package/dist/{limits-jZQp9ZJC.mjs → limits-C5QKZNLT.mjs} +2 -2
- package/dist/{list-CEaJ07jd.mjs → list-BUb5Uc3H.mjs} +1 -1
- package/dist/{mcp-DYgVA9f5.mjs → mcp-bcctR-wc.mjs} +6 -6
- package/dist/once-DPQu5Q3H.mjs +76 -0
- package/dist/{output-CM95njYt.mjs → output-CnRzrbUM.mjs} +3 -1
- package/dist/{pause-D6PuSlNl.mjs → pause-BPvlDIvz.mjs} +4 -4
- package/dist/{relay-DNx7be9k.mjs → relay-C8W0t_zc.mjs} +2 -2
- package/dist/{remove-CpMb4NDl.mjs → remove-BkFWGVYo.mjs} +3 -3
- package/dist/run-CQIfq918.mjs +192 -0
- package/dist/{send-CLs_fyg7.mjs → send-CaZlGG5a.mjs} +3 -3
- package/dist/{src-D6_xjm-x.mjs → src-BeR6f70A.mjs} +595 -228
- package/dist/{src-B6KvTm7B.mjs → src-CGJGL1sZ.mjs} +7 -6
- package/dist/{src-BnZgZGrf.mjs → src-CqRqsb2t.mjs} +44 -7
- package/dist/{src-9iGkjnsy.mjs → src-D93tHZ5B.mjs} +110 -35
- package/dist/store-CM3cERGl.mjs +1365 -0
- package/dist/ui/THIRD_PARTY_LICENSES.txt +18 -0
- package/dist/ui/assets/app-DYRC0V4p.js +111 -0
- package/dist/ui/assets/{index-By_8KKG6.js → index-CWwm8HTG.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/dist/{ui-CIci4UBW.mjs → ui-D2Ydofq0.mjs} +4 -4
- package/dist/{usage-GceBGMjU.mjs → usage-6WIowblz.mjs} +6 -6
- package/dist/verdict-CIy8tAyX.mjs +84 -0
- package/dist/{watch-BmoybMQg.mjs → watch-uOU_WeBI.mjs} +7 -7
- package/dist/{workflows-DZvW3i1e.mjs → workflows-7tQdMnrA.mjs} +3 -3
- package/dist/{worktrees-Be51E2rB.mjs → worktrees-ZCII298F.mjs} +5 -5
- package/package.json +1 -1
- package/dist/ui/assets/app-CxURph7a.js +0 -75
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Rt as git, zt as gitOk } from "./src-BeR6f70A.mjs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
// ../core/src/once/key.ts
|
|
7
|
+
/**
|
|
8
|
+
* @file The key of a check run once (`ork once`, `verify: { once: true }`): the
|
|
9
|
+
* working tree's files as a git tree (tracked and untracked, not ignored),
|
|
10
|
+
* written through a temporary index so the real one is untouched, with `HEAD`
|
|
11
|
+
* and the repository's common git folder, where passes are kept for every
|
|
12
|
+
* worktree. The key is the files, not the commit: a commit or a no-op rebase
|
|
13
|
+
* keeps it.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The key of the files in the worktree at `cwd`. Rejects outside a git
|
|
17
|
+
* repository. Starts from a copy of the real index, so git hashes only the
|
|
18
|
+
* files whose stat changed.
|
|
19
|
+
*/
|
|
20
|
+
const treeKeyOf = async (cwd) => {
|
|
21
|
+
const [commonDir = "", index = ""] = (await gitOk(cwd, [
|
|
22
|
+
"rev-parse",
|
|
23
|
+
"--git-common-dir",
|
|
24
|
+
"--git-path",
|
|
25
|
+
"index"
|
|
26
|
+
])).split("\n").map((line) => path.resolve(cwd, line.trim()));
|
|
27
|
+
const scratch = mkdtempSync(path.join(tmpdir(), "ork-once-"));
|
|
28
|
+
const env = { GIT_INDEX_FILE: path.join(scratch, "index") };
|
|
29
|
+
try {
|
|
30
|
+
if (existsSync(index)) copyFileSync(index, env.GIT_INDEX_FILE);
|
|
31
|
+
await gitOk(cwd, ["add", "-A"], env);
|
|
32
|
+
const tree = (await gitOk(cwd, ["write-tree"], env)).trim();
|
|
33
|
+
const head = await git(cwd, [
|
|
34
|
+
"rev-parse",
|
|
35
|
+
"--verify",
|
|
36
|
+
"-q",
|
|
37
|
+
"HEAD"
|
|
38
|
+
]);
|
|
39
|
+
return {
|
|
40
|
+
tree,
|
|
41
|
+
head: head.code === 0 ? head.stdout.trim() : null,
|
|
42
|
+
commonDir
|
|
43
|
+
};
|
|
44
|
+
} finally {
|
|
45
|
+
rmSync(scratch, {
|
|
46
|
+
recursive: true,
|
|
47
|
+
force: true
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
// ../core/src/once/store.ts
|
|
52
|
+
/**
|
|
53
|
+
* @file The passes of checks run once, kept in `<git-common-dir>/ork-once/`,
|
|
54
|
+
* outside every worktree and shared by all of them. A pass is one JSON file
|
|
55
|
+
* per check name, files and Node version; it holds the tree, `HEAD`, the time
|
|
56
|
+
* and who ran it, nothing else. Only a passing run writes one (Ork's process
|
|
57
|
+
* or the check's own, never an agent's edit). Pruned past 7 days or 500
|
|
58
|
+
* entries.
|
|
59
|
+
*/
|
|
60
|
+
const ONCE_MAX_AGE_MS = 6048e5;
|
|
61
|
+
/** The folder of passes for a repository's common git folder. */
|
|
62
|
+
const onceDirOf = (commonDir) => path.join(commonDir, "ork-once");
|
|
63
|
+
const fileOf = (dir, name, tree, node) => path.join(dir, `${createHash("sha256").update(JSON.stringify([
|
|
64
|
+
name,
|
|
65
|
+
tree,
|
|
66
|
+
node
|
|
67
|
+
])).digest("hex")}.json`);
|
|
68
|
+
const read = (file) => {
|
|
69
|
+
try {
|
|
70
|
+
const value = JSON.parse(readFileSync(file, "utf8"));
|
|
71
|
+
if (typeof value !== "object" || value === null || !("name" in value && "tree" in value && "head" in value && "node" in value && "at" in value && "who" in value)) return null;
|
|
72
|
+
const { name, tree, head, node, at, who } = value;
|
|
73
|
+
return typeof name === "string" && typeof tree === "string" && (typeof head === "string" || head === null) && typeof node === "string" && typeof at === "string" && typeof who === "string" ? {
|
|
74
|
+
name,
|
|
75
|
+
tree,
|
|
76
|
+
head,
|
|
77
|
+
node,
|
|
78
|
+
at,
|
|
79
|
+
who
|
|
80
|
+
} : null;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
/** The pass of `name` on these files, or `null`. */
|
|
86
|
+
const findPass = ({ key, name, withHead = false, node = process.version }) => {
|
|
87
|
+
const pass = read(fileOf(onceDirOf(key.commonDir), name, key.tree, node));
|
|
88
|
+
if (pass === null || pass.tree !== key.tree || pass.node !== node) return null;
|
|
89
|
+
return withHead && pass.head !== key.head ? null : pass;
|
|
90
|
+
};
|
|
91
|
+
/** Records a pass under `name` and each covered name, then prunes. */
|
|
92
|
+
const recordPass = ({ key, name, covers = [], who, node = process.version, at = /* @__PURE__ */ new Date() }) => {
|
|
93
|
+
const dir = onceDirOf(key.commonDir);
|
|
94
|
+
mkdirSync(dir, { recursive: true });
|
|
95
|
+
const pass = {
|
|
96
|
+
name,
|
|
97
|
+
tree: key.tree,
|
|
98
|
+
head: key.head,
|
|
99
|
+
node,
|
|
100
|
+
at: at.toISOString(),
|
|
101
|
+
who
|
|
102
|
+
};
|
|
103
|
+
for (const each of [name, ...covers]) {
|
|
104
|
+
const temp = path.join(dir, `.${randomUUID()}.tmp`);
|
|
105
|
+
writeFileSync(temp, `${JSON.stringify({
|
|
106
|
+
...pass,
|
|
107
|
+
name: each
|
|
108
|
+
})}\n`);
|
|
109
|
+
renameSync(temp, fileOf(dir, each, pass.tree, node));
|
|
110
|
+
}
|
|
111
|
+
prunePasses(key.commonDir, { now: at });
|
|
112
|
+
return pass;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Removes passes older than `maxAgeMs` or past the newest `maxEntries`, and
|
|
116
|
+
* files that don't read as a pass. Returns how many it removed.
|
|
117
|
+
*/
|
|
118
|
+
const prunePasses = (commonDir, { now = /* @__PURE__ */ new Date(), maxAgeMs = ONCE_MAX_AGE_MS, maxEntries = 500 } = {}) => {
|
|
119
|
+
const dir = onceDirOf(commonDir);
|
|
120
|
+
let names;
|
|
121
|
+
try {
|
|
122
|
+
names = readdirSync(dir).filter((name) => name.endsWith(".json"));
|
|
123
|
+
} catch {
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
const kept = [];
|
|
127
|
+
const stale = [];
|
|
128
|
+
for (const name of names) {
|
|
129
|
+
const file = path.join(dir, name);
|
|
130
|
+
const at = Date.parse(read(file)?.at ?? "");
|
|
131
|
+
if (Number.isNaN(at) || now.getTime() - at > maxAgeMs) stale.push(file);
|
|
132
|
+
else kept.push({
|
|
133
|
+
file,
|
|
134
|
+
at
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
kept.sort((a, b) => b.at - a.at);
|
|
138
|
+
stale.push(...kept.slice(maxEntries).map((entry) => entry.file));
|
|
139
|
+
for (const file of stale) rmSync(file, { force: true });
|
|
140
|
+
return stale.length;
|
|
141
|
+
};
|
|
142
|
+
// ../core/src/once/run.ts
|
|
143
|
+
/**
|
|
144
|
+
* @file Runs a check once per set of files, for `ork once` and for
|
|
145
|
+
* `verify:`/tool commands with `once: true`: skip it when the same check
|
|
146
|
+
* already passed on identical files, else run it and record a pass when it
|
|
147
|
+
* exits 0 and the files didn't change while it ran. `force` and
|
|
148
|
+
* `ORK_ONCE=off` run it anyway; outside a git repository it always runs.
|
|
149
|
+
*/
|
|
150
|
+
/** `null` outside a git repository: nothing to key the files by. */
|
|
151
|
+
const keyOf = (cwd) => treeKeyOf(cwd).catch(() => null);
|
|
152
|
+
/** Runs `run` unless the check already passed on these files. */
|
|
153
|
+
const runOnce = async ({ cwd, name, covers = [], withHead = false, force = false, who = "you", run, env = process.env, node = process.version }) => {
|
|
154
|
+
if (env["ORK_ONCE"] === "off") return {
|
|
155
|
+
skipped: false,
|
|
156
|
+
code: await run()
|
|
157
|
+
};
|
|
158
|
+
const before = await keyOf(cwd);
|
|
159
|
+
const earlier = before === null || force ? null : findPass({
|
|
160
|
+
key: before,
|
|
161
|
+
name,
|
|
162
|
+
withHead,
|
|
163
|
+
node
|
|
164
|
+
});
|
|
165
|
+
if (earlier !== null) return {
|
|
166
|
+
skipped: true,
|
|
167
|
+
pass: earlier,
|
|
168
|
+
code: 0
|
|
169
|
+
};
|
|
170
|
+
const code = await run();
|
|
171
|
+
if (code !== 0 || before === null) return {
|
|
172
|
+
skipped: false,
|
|
173
|
+
code
|
|
174
|
+
};
|
|
175
|
+
const after = await keyOf(cwd);
|
|
176
|
+
if (after?.tree !== before.tree || after.head !== before.head) return {
|
|
177
|
+
skipped: false,
|
|
178
|
+
code
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
skipped: false,
|
|
182
|
+
pass: recordPass({
|
|
183
|
+
key: before,
|
|
184
|
+
name,
|
|
185
|
+
covers,
|
|
186
|
+
who,
|
|
187
|
+
node
|
|
188
|
+
}),
|
|
189
|
+
code
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
export { runOnce as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { u as inheritedScrubber } from "./src-
|
|
1
|
+
import { Cn as socketPath, Dt as scriptContactsOf, Tn as wakeRun, _t as liveStatus, w as openStore } from "./src-BeR6f70A.mjs";
|
|
2
|
+
import { s as writeErr } from "./output-CnRzrbUM.mjs";
|
|
3
|
+
import { u as inheritedScrubber } from "./src-D93tHZ5B.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
// ../core/src/remote/send.ts
|
|
6
6
|
/**
|