@krapht/ork 1.0.0-alpha.19 → 1.0.0-alpha.20

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.
Files changed (45) hide show
  1. package/dist/{__build_info__-dPf4cEGL.mjs → __build_info__-D6mXC4cD.mjs} +2 -2
  2. package/dist/argument-error-CihH46Le.mjs +27 -0
  3. package/dist/{attach-BQl8nQz2.mjs → attach-C1OnxyMh.mjs} +7 -5
  4. package/dist/{attach-DhZQ87Nz.mjs → attach-CEGbRg1D.mjs} +126 -69
  5. package/dist/bin.mjs +556 -119
  6. package/dist/{brief-BQbeoPMc.mjs → brief-DH66xmj8.mjs} +11 -6
  7. package/dist/{builtin-files-CWL3JEo-.mjs → builtin-files-Cf-NZDqM.mjs} +1 -1
  8. package/dist/{command-tree-B6uvMJq1.mjs → command-tree-CEkzWNy6.mjs} +1 -1
  9. package/dist/{completion-DKPuD_Rw.mjs → completion-DS0gCZRm.mjs} +19 -12
  10. package/dist/{context-Bw6R_EYq.mjs → context-CGPh12HV.mjs} +3 -3
  11. package/dist/{detached-BQlbmqR0.mjs → detached-Dakw5RZj.mjs} +3 -3
  12. package/dist/extra-arguments-BxQMXARO.mjs +13 -0
  13. package/dist/{find-B30-rd-u.mjs → find-BTikxc54.mjs} +1 -1
  14. package/dist/{flags-ByYBx-Xb.mjs → flags-C8yCq0j5.mjs} +7 -32
  15. package/dist/{follow-ups-Cxca1Jgg.mjs → follow-ups-CtlhHbwe.mjs} +87 -26
  16. package/dist/{format-C-nEZv-P.mjs → format-BB4E-T6x.mjs} +1 -1
  17. package/dist/{in-a-run-CZFzoT3R.mjs → in-a-run-CbnKjO7t.mjs} +2 -2
  18. package/dist/{install-CsqK1avz.mjs → install-CWcpX5g4.mjs} +1 -1
  19. package/dist/{limits-CXh052II.mjs → limits-VQqsBoQk.mjs} +1 -1
  20. package/dist/{mcp-B4wME9C4.mjs → mcp-wGfkMCVF.mjs} +6 -6
  21. package/dist/{once-BKn3pOtg.mjs → once-BHxSdZz_.mjs} +43 -7
  22. package/dist/{pause-B1grR1cl.mjs → pause-C_Wxh-KM.mjs} +6 -3
  23. package/dist/{print-Bd8MWVJk.mjs → print-DNYzq4Rr.mjs} +1 -1
  24. package/dist/{project-records-BOEVs69i.mjs → project-records-XY3ku95x.mjs} +4 -1
  25. package/dist/{relay-CeNiq3GT.mjs → relay-BA6tsnpc.mjs} +1 -1
  26. package/dist/{run-D6yU2rLf.mjs → run-Bvvg-fiF.mjs} +61 -19
  27. package/dist/{run-C0C54UiU.mjs → run-DBUAq-Uu.mjs} +29 -20
  28. package/dist/{send-DqgF58hb.mjs → send-nrKtak5F.mjs} +2 -2
  29. package/dist/{src-Ciy7i3se.mjs → src-8cOPOgrT.mjs} +155 -32
  30. package/dist/{src-n-u4TGev.mjs → src-CmEvHdju.mjs} +28 -28
  31. package/dist/{src-D2qpd-G7.mjs → src-D4JSymhK.mjs} +11 -2
  32. package/dist/{src-DP02RP9O.mjs → src-I_RyKu6_.mjs} +2 -2
  33. package/dist/{store-2KXzMCEN.mjs → store-CDpk8Wtz.mjs} +1 -1
  34. package/dist/ui/assets/app--FijEXiJ.css +1 -0
  35. package/dist/ui/assets/{app-ICEKpy_C.js → app-BowhjEAe.js} +12 -12
  36. package/dist/ui/assets/{index-BGaix5wh.js → index-CrMa2oHB.js} +2 -2
  37. package/dist/ui/index.html +1 -1
  38. package/dist/{ui-CAvygxTb.mjs → ui-DY3Dnpho.mjs} +4 -4
  39. package/dist/{usage-BFBco5OS.mjs → usage-1VwSg_Qt.mjs} +4 -4
  40. package/dist/{validate-UrmC5AG1.mjs → validate-BxayjjkV.mjs} +3 -3
  41. package/dist/{watch-DTxkgB8R.mjs → watch-CT0EtLPZ.mjs} +5 -5
  42. package/dist/{workflows-8GV-SeRm.mjs → workflows-DHHi-APg.mjs} +2 -2
  43. package/dist/{worktrees-CUdUvZlO.mjs → worktrees-CZvbHzbN.mjs} +4 -4
  44. package/package.json +1 -1
  45. package/dist/ui/assets/app-C5vO1M-l.css +0 -1
@@ -1,4 +1,4 @@
1
- import { nn as git, rn as gitOk } from "./src-Ciy7i3se.mjs";
1
+ import { in as gitOk, rn as git } from "./src-8cOPOgrT.mjs";
2
2
  import path from "node:path";
3
3
  import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { createHash, randomUUID } from "node:crypto";
@@ -10,14 +10,27 @@ import { tmpdir } from "node:os";
10
10
  * written through a temporary index so the real one is untouched, with `HEAD`
11
11
  * and the repository's common git folder, where passes are kept for every
12
12
  * worktree. The key is the files, not the commit: a commit or a no-op rebase
13
- * keeps it.
13
+ * keeps it. With pathspecs (`--on`), only the files they match count.
14
14
  */
15
15
  /**
16
+ * Git rejected the pathspecs, or they match no file: a usage error, never a
17
+ * silent hit.
18
+ */
19
+ var OncePathspecError = class extends Error {
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = "OncePathspecError";
23
+ }
24
+ };
25
+ /** The part of the key a pass is matched on: the files, else the tree. */
26
+ const filesOf = (key) => key.files ?? key.tree;
27
+ /**
16
28
  * 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.
29
+ * repository, and with `OncePathspecError` when git rejects `on` or it matches
30
+ * no file. Starts from a copy of the real index, so git hashes only the files
31
+ * whose stat changed.
19
32
  */
20
- const treeKeyOf = async (cwd) => {
33
+ const treeKeyOf = async (cwd, { on = [] } = {}) => {
21
34
  const [commonDir = "", index = ""] = (await gitOk(cwd, [
22
35
  "rev-parse",
23
36
  "--git-common-dir",
@@ -36,11 +49,28 @@ const treeKeyOf = async (cwd) => {
36
49
  "-q",
37
50
  "HEAD"
38
51
  ]);
39
- return {
52
+ const key = {
40
53
  tree,
41
54
  head: head.code === 0 ? head.stdout.trim() : null,
42
55
  commonDir
43
56
  };
57
+ if (on.length === 0) return key;
58
+ const listed = await git(cwd, [
59
+ "ls-files",
60
+ "-s",
61
+ "-z",
62
+ "--full-name",
63
+ "--",
64
+ ...on
65
+ ], env);
66
+ if (listed.code !== 0) throw new OncePathspecError(`git rejected the pathspecs ${on.join(" ")}: ${listed.stderr.trim()}`);
67
+ if (listed.stdout === "") throw new OncePathspecError(`the pathspecs ${on.join(" ")} match no file: check them, or drop --on to key every file`);
68
+ const files = createHash("sha256").update(listed.stdout).digest("hex");
69
+ return {
70
+ ...key,
71
+ files,
72
+ on: [...on]
73
+ };
44
74
  } finally {
45
75
  rmSync(scratch, {
46
76
  recursive: true,
@@ -60,10 +90,16 @@ const treeKeyOf = async (cwd) => {
60
90
  const ONCE_MAX_AGE_MS = 6048e5;
61
91
  /** The folder of passes for a repository's common git folder. */
62
92
  const onceDirOf = (commonDir) => path.join(commonDir, "ork-once");
63
- const fileOf = (dir, name, tree, node) => path.join(dir, `${createHash("sha256").update(JSON.stringify([
93
+ /** Without pathspecs the name key is unchanged, so earlier passes still hit. */
94
+ const fileOf = (dir, name, key, node) => path.join(dir, `${createHash("sha256").update(JSON.stringify(key.on === void 0 || key.on.length === 0 ? [
64
95
  name,
65
- tree,
96
+ key.tree,
66
97
  node
98
+ ] : [
99
+ name,
100
+ filesOf(key),
101
+ node,
102
+ key.on
67
103
  ])).digest("hex")}.json`);
68
104
  const read = (file) => {
69
105
  try {
@@ -84,8 +120,8 @@ const read = (file) => {
84
120
  };
85
121
  /** The pass of `name` on these files, or `null`. */
86
122
  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;
123
+ const pass = read(fileOf(onceDirOf(key.commonDir), name, key, node));
124
+ if (pass === null || pass.tree !== filesOf(key) || pass.node !== node) return null;
89
125
  return withHead && pass.head !== key.head ? null : pass;
90
126
  };
91
127
  /** Records a pass under `name` and each covered name, then prunes. */
@@ -94,7 +130,7 @@ const recordPass = ({ key, name, covers = [], who, node = process.version, at =
94
130
  mkdirSync(dir, { recursive: true });
95
131
  const pass = {
96
132
  name,
97
- tree: key.tree,
133
+ tree: filesOf(key),
98
134
  head: key.head,
99
135
  node,
100
136
  at: at.toISOString(),
@@ -106,7 +142,7 @@ const recordPass = ({ key, name, covers = [], who, node = process.version, at =
106
142
  ...pass,
107
143
  name: each
108
144
  })}\n`);
109
- renameSync(temp, fileOf(dir, each, pass.tree, node));
145
+ renameSync(temp, fileOf(dir, each, key, node));
110
146
  }
111
147
  prunePasses(key.commonDir, { now: at });
112
148
  return pass;
@@ -147,15 +183,21 @@ const prunePasses = (commonDir, { now = /* @__PURE__ */ new Date(), maxAgeMs = O
147
183
  * exits 0 and the files didn't change while it ran. `force` and
148
184
  * `ORK_ONCE=off` run it anyway; outside a git repository it always runs.
149
185
  */
150
- /** `null` outside a git repository: nothing to key the files by. */
151
- const keyOf = (cwd) => treeKeyOf(cwd).catch(() => null);
186
+ /**
187
+ * `null` outside a git repository: nothing to key the files by. Rejected
188
+ * pathspecs reject, so a bad `--on` is an error, never a run without a key.
189
+ */
190
+ const keyOf = (cwd, on) => treeKeyOf(cwd, { on }).catch((error) => {
191
+ if (error instanceof OncePathspecError) throw error;
192
+ return null;
193
+ });
152
194
  /** 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 }) => {
195
+ const runOnce = async ({ cwd, name, covers = [], withHead = false, on = [], force = false, who = "you", run, env = process.env, node = process.version }) => {
154
196
  if (env["ORK_ONCE"] === "off") return {
155
197
  skipped: false,
156
198
  code: await run()
157
199
  };
158
- const before = await keyOf(cwd);
200
+ const before = await keyOf(cwd, on);
159
201
  const earlier = before === null || force ? null : findPass({
160
202
  key: before,
161
203
  name,
@@ -172,8 +214,8 @@ const runOnce = async ({ cwd, name, covers = [], withHead = false, force = false
172
214
  skipped: false,
173
215
  code
174
216
  };
175
- const after = await keyOf(cwd);
176
- if (after?.tree !== before.tree || after.head !== before.head) return {
217
+ const after = await keyOf(cwd, on).catch(() => null);
218
+ if (after === null || filesOf(after) !== filesOf(before) || after.head !== before.head) return {
177
219
  skipped: false,
178
220
  code
179
221
  };
@@ -189,4 +231,4 @@ const runOnce = async ({ cwd, name, covers = [], withHead = false, force = false
189
231
  code
190
232
  };
191
233
  };
192
- export { runOnce as t };
234
+ export { OncePathspecError as n, runOnce as t };
@@ -1,13 +1,13 @@
1
- import { $n as createSignals, B as appendRecorder, Cr as startControl, En as endLinksOf, Et as startRun, Fi as DRIVER_IDS, Gn as gitRulesOf, J as parseInputPairs, K as createReplay, Kn as loadProject, Kr as runDirOf, Nn as liveStatus, Ot as userMessageText, Pi as AGENT_DRIVERS, R as openStore, Rn as templateOf, Tt as walkSummary, Ur as placeFiles, V as createRecorder, Xn as findFollowUp, Y as resolveInputs, Yr as inside, _n as checkFollowUpsDue, bi as isClaudeNode, br as parseTemplate, bt as planNodeSession, ci as beforeOf, cn as sessionDriver, ct as adoptedCalls, dt as DETACHED_ENV, er as endOf, h as resolveBase, hn as createFollowUps, hr as createFeedback, ji as readyDriver, mt as NOT_STARTED, n as resumedOptions, nn as git, pr as runGh, q as replayLoopAnswers, qn as machineRulesOf, rt as createRelay, st as createCalls, t as createWorkspace, tn as inspectProject, wi as retiredDriverHint, xn as deliverFollowUp, xr as renderTemplate, z as storePath } from "./src-Ciy7i3se.mjs";
2
- import { _ as clearOutputFiles, a as builtinExecutors, b as runScrubber, d as maskedEnv, f as maskedNamesOfRun, i as onPath, l as clearStateFiles, m as sessionEnv, n as missingProgramMessage, r as missingPrograms, t as envProblems, v as namedMcpEntries, y as resultOf } from "./src-DP02RP9O.mjs";
3
- import { n as newRunId } from "./find-B30-rd-u.mjs";
4
- import { h as nodeSession, n as ORK_VERSION } from "./__build_info__-dPf4cEGL.mjs";
1
+ import { B as appendRecorder, Dn as endLinksOf, Dt as startRun, Et as walkSummary, Fi as AGENT_DRIVERS, Ii as DRIVER_IDS, J as parseInputPairs, Jn as machineRulesOf, K as createReplay, Kn as gitRulesOf, Mi as readyDriver, Pn as liveStatus, R as openStore, Sn as deliverFollowUp, Sr as renderTemplate, Ti as retiredDriverHint, V as createRecorder, Wr as placeFiles, Xr as inside, Y as resolveInputs, Zn as findFollowUp, ct as createCalls, er as createSignals, ft as DETACHED_ENV, gn as createFollowUps, gr as createFeedback, h as resolveBase, ht as NOT_STARTED, kt as userMessageText, li as beforeOf, ln as sessionDriver, lt as adoptedCalls, mr as runGh, n as resumedOptions, nn as inspectProject, q as replayLoopAnswers, qn as loadProject, qr as runDirOf, rn as git, rt as createRelay, t as createWorkspace, tr as endOf, vn as checkFollowUpsDue, wr as startControl, xi as isClaudeNode, xr as parseTemplate, xt as planNodeSession, z as storePath, zn as templateOf } from "./src-8cOPOgrT.mjs";
2
+ import { _ as clearOutputFiles, a as builtinExecutors, b as runScrubber, d as maskedEnv, f as maskedNamesOfRun, i as onPath, l as clearStateFiles, m as sessionEnv, n as missingProgramMessage, r as missingPrograms, t as envProblems, v as namedMcpEntries, y as resultOf } from "./src-I_RyKu6_.mjs";
3
+ import { n as newRunId } from "./find-BTikxc54.mjs";
4
+ import { h as nodeSession, n as ORK_VERSION } from "./__build_info__-D6mXC4cD.mjs";
5
5
  import { c as write, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
6
- import { c as callsShown, l as createTerminalHuman, o as formatEvent, s as formatRunEvent, t as attachRun } from "./attach-DhZQ87Nz.mjs";
7
- import { a as refusedBuiltin, s as workflowArg, t as WORKFLOW_DIR } from "./workflows-8GV-SeRm.mjs";
8
- import { a as formatReport, c as checksHere, d as runReadyDriver, f as unfitLines, i as walkLoaded, l as chooseReadyDriver, o as warningLines, s as budgetWarningLines, t as loadWorkflow, u as overrideRefusal } from "./validate-UrmC5AG1.mjs";
6
+ import { d as formatEvent, f as formatRunEvent, m as createTerminalHuman, p as callsShown, t as attachRun } from "./attach-CEGbRg1D.mjs";
7
+ import { a as refusedBuiltin, s as workflowArg, t as WORKFLOW_DIR } from "./workflows-DHHi-APg.mjs";
8
+ import { a as formatReport, c as checksHere, d as runReadyDriver, f as unfitLines, i as walkLoaded, l as chooseReadyDriver, o as warningLines, s as budgetWarningLines, t as loadWorkflow, u as overrideRefusal } from "./validate-BxayjjkV.mjs";
9
9
  import { a as createView, o as styler } from "./verdict-CMvPCpWC.mjs";
10
- import { i as runLimits, r as limitsRefusal, t as chatNotice } from "./limits-CXh052II.mjs";
10
+ import { i as runLimits, r as limitsRefusal, t as chatNotice } from "./limits-VQqsBoQk.mjs";
11
11
  import path from "node:path";
12
12
  import { existsSync, linkSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
13
13
  import { createHash, randomUUID } from "node:crypto";
@@ -25,14 +25,19 @@ const put = (rows, f, run, at) => {
25
25
  return next;
26
26
  };
27
27
  /**
28
- * Whether another, live run has taken `f`: it is not free to take again. A run
29
- * the store does not know counts as live while the mark is recent, so a run
30
- * that fails its preflight frees its follow-ups when the window ends.
28
+ * Why `f` is held by the run that took it, as the end of `taken by run <id>,
29
+ * <note>`; `undefined` when it is free. A run the store does not know counts as
30
+ * live while the mark is recent, so a run that fails its preflight frees its
31
+ * follow-ups when the window ends.
31
32
  */
32
- const heldByLive = (f, run, isLive, now) => {
33
- if (f.takenBy === void 0 || f.takenBy === run) return false;
34
- return isLive(f.takenBy) ?? now - Date.parse(f.updatedAt) < 12e4;
33
+ const heldNote = (f, isLive, now) => {
34
+ if (f.takenBy === void 0) return void 0;
35
+ const live = isLive(f.takenBy);
36
+ if (live !== void 0) return live ? "still running" : void 0;
37
+ return now - Date.parse(f.updatedAt) < 12e4 ? "not started yet; free in under 2 minutes" : void 0;
35
38
  };
39
+ /** Whether another run holds `f`: it is not free to take again. */
40
+ const heldByLive = (f, run, isLive, now) => f.takenBy !== run && heldNote(f, isLive, now) !== void 0;
36
41
  /**
37
42
  * The project's due `agent` follow-ups no live run has taken (`ids`), and those
38
43
  * a live run holds (`held`), so a second `--follow-ups due` doesn't take them
@@ -54,13 +59,17 @@ const availableDue = (rows, project, isLive, run = "", now = () => (/* @__PURE__
54
59
  const takeFollowUps = (rows, taking, now = () => (/* @__PURE__ */ new Date()).toISOString()) => {
55
60
  const taken = [];
56
61
  const refused = [];
62
+ const at = Date.parse(now());
57
63
  for (const id of taking.ids) {
58
64
  const f = rows.followUp(taking.project, id);
59
65
  if (f === void 0) refused.push(`${id}: there is no such follow-up`);
60
66
  else if (f.for !== "agent") refused.push(`${id}: it is for ${f.for}`);
61
67
  else if (f.status === "done" || f.status === "dropped") refused.push(`${id}: it is ${f.status}`);
62
- else if (heldByLive(f, taking.run, taking.isLive, Date.parse(now()))) refused.push(`${id}: taken by run ${f.takenBy}, still running`);
63
- else taken.push(put(rows, f, taking.run, now()));
68
+ else {
69
+ const note = f.takenBy === taking.run ? void 0 : heldNote(f, taking.isLive, at);
70
+ if (note === void 0) taken.push(put(rows, f, taking.run, now()));
71
+ else refused.push(`${id}: taken by run ${f.takenBy}, ${note}`);
72
+ }
64
73
  }
65
74
  return {
66
75
  taken,
@@ -1246,7 +1255,7 @@ const isDriver = (value) => AGENT_DRIVERS.some((d) => d.id === value);
1246
1255
  /** Why `--driver` refuses a value: a retired id names its replacement. */
1247
1256
  const badDriver = (value) => `--${retiredDriverHint(value) ?? `driver must be one of ${AGENT_DRIVERS.map((d) => d.id).join(", ")}, got \`${value}\``}`;
1248
1257
  /** Loads the drivers only when a run starts, so other commands stay fast. */
1249
- const loadRuntime = async (driver, runs) => (await import("./src-D2qpd-G7.mjs")).createRuntime(driver, sessionEnv(process.env), runs);
1258
+ const loadRuntime = async (driver, runs) => (await import("./src-D4JSymhK.mjs")).createRuntime(driver, sessionEnv(process.env), runs);
1250
1259
  /**
1251
1260
  * Ctrl-C asks the run to stop, and so does a terminal closing or a polite kill,
1252
1261
  * so that the run ends tidily and leaves no result unscrubbed.
@@ -1368,14 +1377,14 @@ const run = defineCommand({
1368
1377
  process.exitCode = 1;
1369
1378
  return;
1370
1379
  }
1371
- const { prepareFollowUps: prepare, followUpsFlagFine: flagFine } = await import("./brief-BQbeoPMc.mjs");
1380
+ const { prepareFollowUps: prepare, followUpsFlagFine: flagFine } = await import("./brief-DH66xmj8.mjs");
1372
1381
  const cwd = process.cwd();
1373
1382
  if (refusedBuiltin([args.workflow], cwd) || !flagFine(rawArgs)) return;
1374
1383
  const target = workflowArg(args.workflow, cwd);
1375
1384
  const store = openStore();
1376
1385
  if (args.detach) {
1377
1386
  try {
1378
- const { startDetached } = await import("./detached-BQlbmqR0.mjs");
1387
+ const { startDetached } = await import("./detached-Dakw5RZj.mjs");
1379
1388
  await startDetached(store, {
1380
1389
  rawArgs,
1381
1390
  cwd,
@@ -1440,4 +1449,4 @@ const run = defineCommand({
1440
1449
  }
1441
1450
  }
1442
1451
  });
1443
- export { machineSlotLedger as _, onInterrupt as a, runWorkflowFile as c, followUpsRule as d, refreshDue as f, sweepLocks as g, machineLocksDir as h, loadRuntime as i, briefOf as l, resumeChat as m, flagValues as n, run as o, runIsLive as p, isDriver as r, terminalHuman as s, badDriver as t, checkTakeable as u, availableDue as v, takeFollowUps as y };
1452
+ export { machineSlotLedger as _, onInterrupt as a, takeFollowUps as b, runWorkflowFile as c, followUpsRule as d, refreshDue as f, sweepLocks as g, machineLocksDir as h, loadRuntime as i, briefOf as l, resumeChat as m, flagValues as n, run as o, runIsLive as p, isDriver as r, terminalHuman as s, badDriver as t, checkTakeable as u, availableDue as v, heldNote as y };
@@ -1,5 +1,5 @@
1
- import { R as openStore, et as TOO_LONG, nt as sendFromScript, tt as scriptRefusal } from "./src-Ciy7i3se.mjs";
2
- import { u as inheritedScrubber } from "./src-DP02RP9O.mjs";
1
+ import { R as openStore, et as TOO_LONG, nt as sendFromScript, tt as scriptRefusal } from "./src-8cOPOgrT.mjs";
2
+ import { u as inheritedScrubber } from "./src-I_RyKu6_.mjs";
3
3
  import { l as writeErr } from "./output-B1kwo0YU.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  // src/commands/send.ts
@@ -5003,7 +5003,8 @@ const feedbackActions = (item, fixRun) => {
5003
5003
  accept: check,
5004
5004
  lesson: check,
5005
5005
  apply: check,
5006
- publish: check
5006
+ publish: check,
5007
+ resolve: check
5007
5008
  };
5008
5009
  }
5009
5010
  const settled = item.status === "resolved" || item.status === "published";
@@ -5018,11 +5019,13 @@ const feedbackActions = (item, fixRun) => {
5018
5019
  let publish = ALLOWED;
5019
5020
  if (!isOrk) publish = no("only feedback about Ork is shared", `${short} is about this ${item.target}, not Ork itself: only feedback about Ork is shared, and the rest stays on your machine.`);
5020
5021
  else if (item.status === "published") publish = already(short, item.status);
5022
+ const resolve = settled ? already(short, item.status) : ALLOWED;
5021
5023
  return {
5022
5024
  accept,
5023
5025
  lesson,
5024
5026
  apply,
5025
- publish
5027
+ publish,
5028
+ resolve
5026
5029
  };
5027
5030
  };
5028
5031
  /** The running `ork:feedback-apply` run proposing a fix for `item`, if any. */
@@ -16278,7 +16281,7 @@ const answerDecision = async (store, id, choice, home, by = "decide", note) => {
16278
16281
  * Calls `onEvent` for each event of `root` and of the runs it called, once
16279
16282
  * each. A called run's stored events come right after the `call.started` that
16280
16283
  * started it; live events as they arrive. Ends when the root ends or `signal`
16281
- * aborts.
16284
+ * aborts; with `follow: false`, once the stored events are read.
16282
16285
  */
16283
16286
  const followRunTree = async (store, root, onEvent, options = {}) => {
16284
16287
  /** Every run followed, with its call path, in the order found. */
@@ -16286,6 +16289,7 @@ const followRunTree = async (store, root, onEvent, options = {}) => {
16286
16289
  /** Each run's last event seen, for the catch-up once the root ends. */
16287
16290
  const seqs = /* @__PURE__ */ new Map();
16288
16291
  const followers = [];
16292
+ const live = options.follow ?? true;
16289
16293
  /** Ends the called runs' following once the root's has ended. */
16290
16294
  const halt = new AbortController();
16291
16295
  const signal = options.signal === void 0 ? halt.signal : AbortSignal.any([options.signal, halt.signal]);
@@ -16303,7 +16307,7 @@ const followRunTree = async (store, root, onEvent, options = {}) => {
16303
16307
  paths.set(run, path);
16304
16308
  followers.push(followEvents(store, run, handle(run, path), {
16305
16309
  ...options,
16306
- follow: true,
16310
+ follow: live,
16307
16311
  after: seqs.get(run) ?? 0,
16308
16312
  signal
16309
16313
  }));
@@ -16314,7 +16318,7 @@ const followRunTree = async (store, root, onEvent, options = {}) => {
16314
16318
  };
16315
16319
  const end = await followEvents(store, root, handle(root, []), {
16316
16320
  ...options,
16317
- follow: true
16321
+ follow: live
16318
16322
  });
16319
16323
  halt.abort();
16320
16324
  await settle();
@@ -16333,6 +16337,95 @@ const followRunTree = async (store, root, onEvent, options = {}) => {
16333
16337
  })
16334
16338
  };
16335
16339
  };
16340
+ // ../core/src/remote/follow-runs.ts
16341
+ /**
16342
+ * @file Following many runs at once (`ork logs -f --all`, `ork decide
16343
+ * --follow`): each live top-level run through `followRunTree`, so a called
16344
+ * run is reached through its caller and seen once, and a run that starts
16345
+ * later found by polling the run list, since no socket announces a new run.
16346
+ */
16347
+ /**
16348
+ * Calls `onEvent` for each event of the live runs in `scope` and of the runs
16349
+ * they call, once each: stored events first, then live ones. Roots are the live
16350
+ * runs with no `parent`, and a called run whose caller is not followed (out of
16351
+ * scope, or ended while it runs on). A root's end does not end the watch.
16352
+ */
16353
+ const followRuns = async (store, scope, onEvent, options = {}) => {
16354
+ /** Each followed tree's runs, by its root, while it is followed. */
16355
+ const trees = /* @__PURE__ */ new Map();
16356
+ const followers = /* @__PURE__ */ new Set();
16357
+ /** Each run's last event passed on: a run followed again starts after it. */
16358
+ const seqs = /* @__PURE__ */ new Map();
16359
+ const workflows = /* @__PURE__ */ new Map();
16360
+ const failure = {};
16361
+ /** Ends every follower once one has failed. */
16362
+ const halt = new AbortController();
16363
+ const signal = options.signal === void 0 ? halt.signal : AbortSignal.any([options.signal, halt.signal]);
16364
+ const { project } = scope;
16365
+ const filter = project === void 0 || project === "all" ? {} : { project };
16366
+ /** What each tree takes: `untilIdle` is the watch's, not a tree's. */
16367
+ const { untilIdle, ...poll } = options;
16368
+ const followed = (run) => [...trees.values()].some((runs) => runs.has(run));
16369
+ const workflowOf = (run) => {
16370
+ const known = workflows.get(run);
16371
+ if (known !== void 0) return known;
16372
+ const name = store.lookup(run).find((r) => r.id === run)?.workflow ?? "";
16373
+ workflows.set(run, name);
16374
+ return name;
16375
+ };
16376
+ const inScope = (run) => (scope.run === void 0 || run.id === scope.run) && (scope.workflow === void 0 || run.workflow === scope.workflow);
16377
+ const adopt = (root) => {
16378
+ const runs = /* @__PURE__ */ new Set([root]);
16379
+ trees.set(root, runs);
16380
+ const following = followRunTree(store, root, (event) => {
16381
+ runs.add(event.run);
16382
+ if (event.stored.seq <= (seqs.get(event.run) ?? 0)) return;
16383
+ seqs.set(event.run, event.stored.seq);
16384
+ onEvent({
16385
+ ...event,
16386
+ workflow: workflowOf(event.run)
16387
+ });
16388
+ }, {
16389
+ ...poll,
16390
+ signal
16391
+ }).catch((error) => {
16392
+ failure.error ??= error;
16393
+ halt.abort();
16394
+ }).finally(() => {
16395
+ trees.delete(root);
16396
+ followers.delete(following);
16397
+ });
16398
+ followers.add(following);
16399
+ };
16400
+ /** Starts a tree for each live run in scope that no tree reaches. */
16401
+ const discover = () => {
16402
+ const live = store.runs(filter).filter((run) => liveStatus(run) === "running" && inScope(run));
16403
+ for (const run of live) workflows.set(run.id, run.workflow);
16404
+ const unseen = live.filter((run) => !followed(run.id));
16405
+ const pending = new Set(unseen.map((run) => run.id));
16406
+ for (const run of unseen) {
16407
+ const { parent } = run;
16408
+ const orphan = parent === void 0 || !followed(parent) && !pending.has(parent);
16409
+ if (scope.run !== void 0 || orphan) adopt(run.id);
16410
+ }
16411
+ };
16412
+ const settle = async () => {
16413
+ await Promise.all(followers);
16414
+ if ("error" in failure) throw failure.error;
16415
+ };
16416
+ for (;;) {
16417
+ if (signal.aborted) break;
16418
+ discover();
16419
+ if (untilIdle === true && trees.size === 0) return "idle";
16420
+ try {
16421
+ await setTimeout$1(options.intervalMs ?? 1e3, void 0, { signal });
16422
+ } catch {
16423
+ break;
16424
+ }
16425
+ }
16426
+ await settle();
16427
+ return "aborted";
16428
+ };
16336
16429
  // ../core/src/remote/relay.ts
16337
16430
  /**
16338
16431
  * @file A run's side of the relay (RFC-003): its nodes' links, read from the
@@ -17342,7 +17435,11 @@ const feedbackQueries = (db) => {
17342
17435
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
17343
17436
  const insertItem = db.prepare(`INSERT INTO feedback_items (fingerprint, status, updated_at)
17344
17437
  VALUES (?, 'new', ?) ON CONFLICT (fingerprint) DO NOTHING`);
17345
- const shown = db.prepare(`${ITEMS} WHERE r.status != 'dismissed' GROUP BY r.fingerprint ORDER BY last_seen DESC`);
17438
+ const shown = db.prepare(`${ITEMS} WHERE r.status NOT IN ('dismissed', 'resolved') GROUP BY r.fingerprint ORDER BY last_seen DESC`);
17439
+ const reopen = db.prepare(`UPDATE feedback_items SET status = 'new', updated_at = ?
17440
+ WHERE fingerprint = (
17441
+ SELECT COALESCE(merged_into, fingerprint) FROM feedback_items WHERE fingerprint = ?
17442
+ ) AND status = 'resolved' AND updated_at < ?`);
17346
17443
  const every = db.prepare(`${ITEMS} GROUP BY r.fingerprint ORDER BY last_seen DESC`);
17347
17444
  const byPrefix = db.prepare(`${ITEMS} WHERE r.fingerprint IN (
17348
17445
  SELECT COALESCE(merged_into, fingerprint) FROM feedback_items
@@ -17367,6 +17464,7 @@ const feedbackQueries = (db) => {
17367
17464
  const { origin } = feedback;
17368
17465
  insert.run(runId, seq, at, node ?? null, feedback.source, feedback.kind, feedback.target, feedback.severity, maskSecrets(feedback.title), maskSecrets(feedback.body), JSON.stringify(feedback.evidence.map((e) => maskSecrets(e))), feedback.code ?? null, feedback.fingerprint, origin.workflow ?? null, origin.workflowHash ?? null, origin.nodeType ?? null, origin.model ?? null, origin.driver ?? null, origin.version ?? null, 1);
17369
17466
  insertItem.run(feedback.fingerprint, at);
17467
+ reopen.run(at, feedback.fingerprint, at);
17370
17468
  };
17371
17469
  return {
17372
17470
  insertFeedback: insertRecord,
@@ -18321,14 +18419,62 @@ const takeWatchLock = (store, pid = process.pid) => {
18321
18419
  }
18322
18420
  };
18323
18421
  };
18422
+ // ../core/src/triggers/check-reads.ts
18423
+ /**
18424
+ * @file What a trigger's check runs beyond its own words, for the hash a person
18425
+ * accepts: the `.mcp.json` its server comes from, and the project's files its
18426
+ * command, interpreter or server program names (`--config=./x.json` names
18427
+ * `./x.json`). What those files read in turn, a program outside the project
18428
+ * and a path built from an env variable are not in it. Only files inside the
18429
+ * project are read, and what goes into the hash is the text of `.mcp.json`
18430
+ * and a digest of each named file's bytes, never anything else.
18431
+ */
18432
+ /** A file's text; `undefined` only when it isn't there. Anything else throws. */
18433
+ const readText = (file) => {
18434
+ try {
18435
+ return readFileSync(file, "utf8");
18436
+ } catch (error) {
18437
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
18438
+ throw error;
18439
+ }
18440
+ };
18441
+ const isFile = (file) => statSync(file, { throwIfNoEntry: false })?.isFile() === true;
18442
+ /**
18443
+ * What a word names, if it is a file in the project: the word and a digest of
18444
+ * the file's bytes, not its text, so a compiled program that differs only in
18445
+ * bytes that aren't UTF-8 still changes the hash. A file outside the project, a
18446
+ * missing one and a word that is no file add nothing.
18447
+ */
18448
+ const fileRead = (root, from, word) => {
18449
+ const file = path.resolve(from, word.replace(/^-{1,2}[^=\s]+=/u, ""));
18450
+ return word !== "" && inside(root, file) && isFile(file) ? [`${word}\0${createHash("sha256").update(readFileSync(file)).digest("hex")}`] : [];
18451
+ };
18452
+ /** The in-repo files a stdio server's program and arguments name. */
18453
+ const serverReads = (root, server) => {
18454
+ const read = serversIn(root);
18455
+ const entry = read.ok ? read.value[server] : void 0;
18456
+ if (typeof entry !== "object" || entry === null) return [];
18457
+ const command = Reflect.get(entry, "command");
18458
+ const args = Reflect.get(entry, "args");
18459
+ return [command, ...Array.isArray(args) ? args : []].flatMap((word) => typeof word === "string" ? fileRead(root, root, word) : []);
18460
+ };
18461
+ /** The texts a check's hash covers beyond its own words. */
18462
+ const checkReads = (root, check) => {
18463
+ if (check === void 0) return [];
18464
+ if (check.type === "mcp.call") return [readText(path.join(root, ".mcp.json")) ?? "", ...serverReads(root, check.server)];
18465
+ const from = path.resolve(root, check.cwd ?? ".");
18466
+ return [check.command, check.interpreter].join(" ").split(/\s+/u).flatMap((word) => fileRead(root, from, word));
18467
+ };
18324
18468
  // ../core/src/triggers/trust.ts
18325
18469
  /**
18326
18470
  * @file What a person accepts (RFC-011): a trigger, the workflow it starts,
18327
18471
  * what its check runs beyond its own words, and the folder it was accepted
18328
18472
  * in. A branch can change any of them and so what runs here with nobody
18329
18473
  * there, so a change to one turns the trigger off until someone accepts it
18330
- * again. It can't cover all a run reads: skills, agents, scripts and called
18331
- * workflows aren't in it.
18474
+ * again. That includes the project's files a check's command or an MCP
18475
+ * check's server program names. It can't cover all a run reads: skills,
18476
+ * agents, what a script or server program itself reads, programs outside the
18477
+ * project and called workflows aren't in it.
18332
18478
  */
18333
18479
  const sorted = (value) => {
18334
18480
  if (Array.isArray(value)) return value.map((item) => sorted(item));
@@ -18354,29 +18500,6 @@ const triggerHash = (trigger, workflowText, root = "", reads = []) => {
18354
18500
  * Read fresh each time, so a file changed by a pull turns its trigger off
18355
18501
  * rather than running as it was.
18356
18502
  */
18357
- /** A file's text; `undefined` only when it isn't there. Anything else throws. */
18358
- const readText = (file) => {
18359
- try {
18360
- return readFileSync(file, "utf8");
18361
- } catch (error) {
18362
- if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
18363
- throw error;
18364
- }
18365
- };
18366
- const isFile = (file) => statSync(file, { throwIfNoEntry: false })?.isFile() === true;
18367
- /**
18368
- * What a check runs beyond its own words, for what a person accepts: the
18369
- * `.mcp.json` its server comes from, or the project's files its command names.
18370
- */
18371
- const checkReads = (root, check) => {
18372
- if (check === void 0) return [];
18373
- if (check.type === "mcp.call") return [readText(path.join(root, ".mcp.json")) ?? ""];
18374
- const from = path.resolve(root, check.cwd ?? ".");
18375
- return [check.command, check.interpreter].join(" ").split(/\s+/u).flatMap((word) => {
18376
- const file = path.resolve(from, word);
18377
- return word !== "" && inside(root, file) && isFile(file) ? [`${word}\0${readFileSync(file, "utf8")}`] : [];
18378
- });
18379
- };
18380
18503
  /** Where a project's workflow of this name is. */
18381
18504
  const workflowFileOf = (place, name) => path.join(placeFiles(place).workflows, `${name}.ork.yaml`);
18382
18505
  const readTriggers = (file, place, home, registered) => {
@@ -19830,4 +19953,4 @@ const createWorkspace = (options) => {
19830
19953
  close
19831
19954
  };
19832
19955
  };
19833
- export { driverQueues as $, createSignals as $n, guardedBase as $r, stepActs as $t, triggerStanding as A, driverChecks as Ai, requestPause as An, applySteps as Ar, runScope as At, appendRecorder as B, stillTheSameProcess as Bn, hasInRepoFiles as Br, programFound as Bt, detectInstaller as C, NodeIdSchema as Ci, liveSessionOf as Cn, startControl as Cr, checkWorkflowText as Ct, lateTriggers as D, TOOL_PREFIX as Di, linkNodes as Dn, maskReplacer as Dr, MESSAGE_LIMIT as Dt, parseVersion as E, INTEGRATIONS as Ei, endLinksOf as En, MASK as Er, startRun as Et, watchingPid as F, DRIVER_IDS as Fi, pausedOf as Fn, createAgent as Fr, stoppedEnd as Ft, listOrkWorktrees as G, gitRulesOf as Gn, projectsHome as Gr, followUpListTable as Gt, applyPrune as H, nestItems as Hn, newProjectId as Hr, LIST_TABLES as Ht, activeTree as I, firstLine as Ii, runStatus as In, deleteAgent as Ir, declaredProblem as It, parseInputPairs as J, changeFollowUp as Jn, workflowDirOf as Jr, worktreeListTable as Jt, createReplay as K, loadProject as Kn, runDirOf as Kr, runListTable as Kt, isNodeEvent as L, EXPERIMENTS as Li, slotWaitsOf as Ln, AGENT_SOURCES as Lr, slotClock as Lt, readProjectTriggers as M, AGENT_TOOL_LAYOUTS as Mi, tellLiveRun as Mn, linkTools as Mr, lockWaitLine as Mt, workflowTextHash as N, ORK_LAYOUT as Ni, liveStatus as Nn, toolLinks as Nr, endedWith as Nt, triggersReport as O, integrationFor as Oi, unlinkNodes as On, maskSecrets as Or, userMessageText as Ot, takeWatchLock as P, AGENT_DRIVERS as Pi, lockWaitsOf as Pn, toolsInUse as Pr, failedWith as Pt, sessionRefusals as Q, isGithubIssueUrl as Qn, estimateTokens as Qr, planClean as Qt, openStore as R, experimentsOn as Ri, templateOf$1 as Rn, catalogAgent as Rr, slotWaitLine as Rt, runningScript as S, DriverSchema as Si, followUpProblem as Sn, readCondition as Sr, reportSchemaFor as St, isNewer as T, timeoutMs as Ti, addressOf as Tn, TOOL_INPUT_KEYS as Tr, walkSummary as Tt, planPrune as U, countedTokens as Un, placeFiles as Ur, decisionListTable as Ut, createRecorder as V, isItem as Vn, inRepoPlace as Vr, startAt as Vt, createdWorktrees as W, PROJECT_FILE as Wn, placeFor as Wr, feedbackListTable as Wt, budgetWarnings as X, findFollowUp as Xn, projectRootOf as Xr, cleanStep as Xt, resolveInputs as Y, dueCause as Yn, inside as Yr, applyClean as Yt, driverRefusals as Z, followUpActions as Zn, LESSON_CAP_TOKENS as Zr, keyOf as Zt, usageReport as _, expandEdge as _i, checkFollowUpsDue as _n, feedbackActions as _r, planReason as _t, planRemove as a, newWorkflowText as ai, envReadsOf as an, previewPost as ar, answerDecision as at, releaseNotes as b, isClaudeNode as bi, startFollowUpChecks as bn, parseTemplate as br, planNodeSession as bt, repoRoot as c, beforeOf as ci, sessionDriver as cn, FEEDBACK_KINDS as cr, adoptedCalls as ct, mergeStateOf as d, parseWorkflow as di, MCP_FILE as dn, DISCUSSIONS as dr, DETACHED_ENV as dt, plainPathInside as ei, stepPrunes as en, endOf as er, TOO_LONG as et, planLine as f, serializeWorkflow as fi, mcpNotText as fn, planPost as fr, detachRun as ft, USAGE_DIMENSIONS as g, CheckReportSchema as gi, postFollowUpMessage as gn, normalizeTitle as gr, limitsReport as gt, resolveBase as h, WorkflowSchema as hi, createFollowUps as hn, createFeedback as hr, limitsNow as ht, lostWork as i, applyEdits as ii, clearGitLocalEnv as in, endFor as ir, followRunTree as it, declaredTriggers as j, readyDriver as ji, requestStop as jn, planMoveInto as jr, calledWorkflows as jt, createWatcher as k, PREFERRED_DRIVER as ki, requestContinue as kn, planAgentMigration as kr, heldTimeout as kt, isDetached as l, programsRunBy as li, nodeSays as ln, FEEDBACK_SEVERITIES as lr, detachResume as lt, stateParts as m, EdgeInputSchema as mi, FOLLOW_UP_KINDS as mn, sendPost as mr, NOT_STARTED as mt, resumedOptions as n, skillsIn as ni, git as nn, END_DETAIL_LIMIT as nr, sendFromScript as nt, projectHead as o, readDocument as oi, modelDriver as on, checkNote as or, pendingDecisions as ot, removeRefusal as p, markValue as pi, serversIn as pn, runGh as pr, followEvents as pt, replayLoopAnswers as q, machineRulesOf as qn, shownPath as qr, usageListTable as qt, applyRemove as r, WorkflowEditSchema as ri, gitOk as rn, END_KINDS as rr, createRelay as rt, readWorktrees as s, renameNodeTypes as si, namingNoDriver as sn, recordNote as sr, createCalls as st, createWorkspace as t, writePlainFile as ti, inspectProject as tn, outcomeEnd as tr, scriptRefusal as tt, labelOf as u, renderJsonSchema as ui, declaredOutputOf as un, FEEDBACK_TARGETS as ur, resumable as ut, capsHere as v, settingsOf as vi, markDue as vn, openFixRun as vr, explainWorkflowText as vt, compareVersions as w, retiredDriverHint as wi, DEFAULT_FOLLOW_UPS_RULE as wn, socketRoom as wr, walkChecks as wt, runningRunIds as x, isToolNode as xi, deliverFollowUp as xn, renderTemplate as xr, parseReport as xt, planUpgrade as y, NodeSchema as yi, recordPublished as yn, evaluate as yr, explainSession as yt, storePath as z, knownExperiments as zi, processAlive as zn, loadAgents as zr, lowerChild as zt };
19956
+ export { driverQueues as $, isGithubIssueUrl as $n, estimateTokens as $r, planClean as $t, triggerStanding as A, PREFERRED_DRIVER as Ai, requestContinue as An, planAgentMigration as Ar, heldTimeout as At, appendRecorder as B, knownExperiments as Bi, processAlive as Bn, loadAgents as Br, lowerChild as Bt, detectInstaller as C, DriverSchema as Ci, followUpProblem as Cn, readCondition as Cr, reportSchemaFor as Ct, lateTriggers as D, INTEGRATIONS as Di, endLinksOf as Dn, MASK as Dr, startRun as Dt, parseVersion as E, timeoutMs as Ei, addressOf as En, TOOL_INPUT_KEYS as Er, walkSummary as Et, watchingPid as F, AGENT_DRIVERS as Fi, lockWaitsOf as Fn, toolsInUse as Fr, failedWith as Ft, listOrkWorktrees as G, PROJECT_FILE as Gn, placeFor as Gr, feedbackListTable as Gt, applyPrune as H, isItem as Hn, inRepoPlace as Hr, startAt as Ht, activeTree as I, DRIVER_IDS as Ii, pausedOf as In, createAgent as Ir, stoppedEnd as It, parseInputPairs as J, machineRulesOf as Jn, shownPath as Jr, usageListTable as Jt, createReplay as K, gitRulesOf as Kn, projectsHome as Kr, followUpListTable as Kt, isNodeEvent as L, firstLine as Li, runStatus as Ln, deleteAgent as Lr, declaredProblem as Lt, readProjectTriggers as M, readyDriver as Mi, requestStop as Mn, planMoveInto as Mr, calledWorkflows as Mt, workflowTextHash as N, AGENT_TOOL_LAYOUTS as Ni, tellLiveRun as Nn, linkTools as Nr, lockWaitLine as Nt, triggersReport as O, TOOL_PREFIX as Oi, linkNodes as On, maskReplacer as Or, MESSAGE_LIMIT as Ot, takeWatchLock as P, ORK_LAYOUT as Pi, liveStatus as Pn, toolLinks as Pr, endedWith as Pt, sessionRefusals as Q, followUpActions as Qn, LESSON_CAP_TOKENS as Qr, keyOf as Qt, openStore as R, EXPERIMENTS as Ri, slotWaitsOf as Rn, AGENT_SOURCES as Rr, slotClock as Rt, runningScript as S, isToolNode as Si, deliverFollowUp as Sn, renderTemplate as Sr, parseReport as St, isNewer as T, retiredDriverHint as Ti, DEFAULT_FOLLOW_UPS_RULE as Tn, socketRoom as Tr, walkChecks as Tt, planPrune as U, nestItems as Un, newProjectId as Ur, LIST_TABLES as Ut, createRecorder as V, stillTheSameProcess as Vn, hasInRepoFiles as Vr, programFound as Vt, createdWorktrees as W, countedTokens as Wn, placeFiles as Wr, decisionListTable as Wt, budgetWarnings as X, dueCause as Xn, inside as Xr, applyClean as Xt, resolveInputs as Y, changeFollowUp as Yn, workflowDirOf as Yr, worktreeListTable as Yt, driverRefusals as Z, findFollowUp as Zn, projectRootOf as Zr, cleanStep as Zt, usageReport as _, CheckReportSchema as _i, postFollowUpMessage as _n, normalizeTitle as _r, limitsReport as _t, planRemove as a, applyEdits as ai, clearGitLocalEnv as an, endFor as ar, followRunTree as at, releaseNotes as b, NodeSchema as bi, recordPublished as bn, evaluate as br, explainSession as bt, repoRoot as c, renameNodeTypes as ci, namingNoDriver as cn, recordNote as cr, createCalls as ct, mergeStateOf as d, renderJsonSchema as di, declaredOutputOf as dn, FEEDBACK_TARGETS as dr, resumable as dt, guardedBase as ei, stepActs as en, createSignals as er, TOO_LONG as et, planLine as f, parseWorkflow as fi, MCP_FILE as fn, DISCUSSIONS as fr, DETACHED_ENV as ft, USAGE_DIMENSIONS as g, WorkflowSchema as gi, createFollowUps as gn, createFeedback as gr, limitsNow as gt, resolveBase as h, EdgeInputSchema as hi, FOLLOW_UP_KINDS as hn, sendPost as hr, NOT_STARTED as ht, lostWork as i, WorkflowEditSchema as ii, gitOk as in, END_KINDS as ir, followRuns as it, declaredTriggers as j, driverChecks as ji, requestPause as jn, applySteps as jr, runScope as jt, createWatcher as k, integrationFor as ki, unlinkNodes as kn, maskSecrets as kr, userMessageText as kt, isDetached as l, beforeOf as li, sessionDriver as ln, FEEDBACK_KINDS as lr, adoptedCalls as lt, stateParts as m, markValue as mi, serversIn as mn, runGh as mr, followEvents as mt, resumedOptions as n, writePlainFile as ni, inspectProject as nn, outcomeEnd as nr, sendFromScript as nt, projectHead as o, newWorkflowText as oi, envReadsOf as on, previewPost as or, answerDecision as ot, removeRefusal as p, serializeWorkflow as pi, mcpNotText as pn, planPost as pr, detachRun as pt, replayLoopAnswers as q, loadProject as qn, runDirOf as qr, runListTable as qt, applyRemove as r, skillsIn as ri, git as rn, END_DETAIL_LIMIT as rr, createRelay as rt, readWorktrees as s, readDocument as si, modelDriver as sn, checkNote as sr, pendingDecisions as st, createWorkspace as t, plainPathInside as ti, stepPrunes as tn, endOf as tr, scriptRefusal as tt, labelOf as u, programsRunBy as ui, nodeSays as un, FEEDBACK_SEVERITIES as ur, detachResume as ut, capsHere as v, expandEdge as vi, checkFollowUpsDue as vn, feedbackActions as vr, planReason as vt, compareVersions as w, NodeIdSchema as wi, liveSessionOf as wn, startControl as wr, checkWorkflowText as wt, runningRunIds as x, isClaudeNode as xi, startFollowUpChecks as xn, parseTemplate as xr, planNodeSession as xt, planUpgrade as y, settingsOf as yi, markDue as yn, openFixRun as yr, explainWorkflowText as yt, storePath as z, experimentsOn as zi, templateOf$1 as zn, catalogAgent as zr, slotWaitLine as zt };