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

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 (48) hide show
  1. package/dist/{__build_info__-C1Nm0hlJ.mjs → __build_info__-dPf4cEGL.mjs} +3 -134
  2. package/dist/{attach-EP374oMP.mjs → attach-BQl8nQz2.mjs} +5 -5
  3. package/dist/{attach-RQx__RzH.mjs → attach-DhZQ87Nz.mjs} +49 -224
  4. package/dist/bin.mjs +204 -154
  5. package/dist/{brief-Bs3cMQU0.mjs → brief-BQbeoPMc.mjs} +19 -9
  6. package/dist/{builtin-files-yYaNTQRU.mjs → builtin-files-CWL3JEo-.mjs} +1 -1
  7. package/dist/{command-tree-BkSYWmYJ.mjs → command-tree-B6uvMJq1.mjs} +1 -1
  8. package/dist/{completion-DIXWlnAl.mjs → completion-DKPuD_Rw.mjs} +47 -14
  9. package/dist/{context-Dq-VM_sq.mjs → context-Bw6R_EYq.mjs} +3 -3
  10. package/dist/detached-BQlbmqR0.mjs +38 -0
  11. package/dist/{find-k489laBa.mjs → find-B30-rd-u.mjs} +1 -1
  12. package/dist/flags-ByYBx-Xb.mjs +170 -0
  13. package/dist/{follow-ups-DD8NTPe6.mjs → follow-ups-Cxca1Jgg.mjs} +24 -18
  14. package/dist/{format-DQc9A_ei.mjs → format-C-nEZv-P.mjs} +27 -11
  15. package/dist/{help-groups-hB6kY34d.mjs → help-groups-BpRgBSTh.mjs} +13 -7
  16. package/dist/{in-a-run-D_9GlAlS.mjs → in-a-run-CZFzoT3R.mjs} +2 -2
  17. package/dist/{install-PVlV2QPq.mjs → install-CsqK1avz.mjs} +2 -183
  18. package/dist/{limits-CHqBO7wb.mjs → limits-CXh052II.mjs} +1 -1
  19. package/dist/{mcp-D38Ajb0b.mjs → mcp-B4wME9C4.mjs} +6 -6
  20. package/dist/{once-DuUzpzL2.mjs → once-BKn3pOtg.mjs} +3 -3
  21. package/dist/outputs-text-CNTJ7Qq_.mjs +19 -0
  22. package/dist/{pause-Bx3ePGrn.mjs → pause-B1grR1cl.mjs} +3 -3
  23. package/dist/{print-n2qetUHc.mjs → print-Bd8MWVJk.mjs} +1 -1
  24. package/dist/{project-records-Cune1l6I.mjs → project-records-BOEVs69i.mjs} +1 -1
  25. package/dist/{parse-BzWpMN-a.mjs → refusals-DQQX3AIb.mjs} +10 -1
  26. package/dist/{relay-D7RN4m68.mjs → relay-CeNiq3GT.mjs} +1 -1
  27. package/dist/{run-OOWQIKMJ.mjs → run-C0C54UiU.mjs} +116 -137
  28. package/dist/{run-BfxdsQJk.mjs → run-D6yU2rLf.mjs} +1 -1
  29. package/dist/{send-CKth_vgn.mjs → send-DqgF58hb.mjs} +2 -2
  30. package/dist/{src-DLsFsmOD.mjs → src-Ciy7i3se.mjs} +882 -71
  31. package/dist/{src-BHod38UQ.mjs → src-D2qpd-G7.mjs} +394 -247
  32. package/dist/{src-DmmrX2_C.mjs → src-DP02RP9O.mjs} +227 -180
  33. package/dist/{src-DOjTY2ET.mjs → src-n-u4TGev.mjs} +186 -43
  34. package/dist/{store-DACH768X.mjs → store-2KXzMCEN.mjs} +1 -1
  35. package/dist/ui/assets/app-C5vO1M-l.css +1 -0
  36. package/dist/ui/assets/{app-CN3acQ-1.js → app-ICEKpy_C.js} +21 -20
  37. package/dist/ui/assets/{index-B2uGxA4W.js → index-BGaix5wh.js} +2 -2
  38. package/dist/ui/index.html +1 -1
  39. package/dist/{ui-CJ-BX12n.mjs → ui-CAvygxTb.mjs} +53 -24
  40. package/dist/{usage-DxZ6JGd4.mjs → usage-BFBco5OS.mjs} +7 -7
  41. package/dist/{validate-BS0nCccW.mjs → validate-UrmC5AG1.mjs} +5 -5
  42. package/dist/{watch-Dp7IB4FR.mjs → watch-DTxkgB8R.mjs} +5 -5
  43. package/dist/{workflows-Djo1edlK.mjs → workflows-8GV-SeRm.mjs} +28 -4
  44. package/dist/{worktrees-Drof_Nyx.mjs → worktrees-CUdUvZlO.mjs} +9 -6
  45. package/package.json +1 -1
  46. package/dist/flags-B4ZZWspN.mjs +0 -125
  47. package/dist/post-2CaJz_mV.mjs +0 -46
  48. package/dist/ui/assets/app-9Q-62Ywz.css +0 -1
@@ -1,86 +1,70 @@
1
- import { $r as beforeOf, $t as git, An as liveStatus, Br as inside, Cn as endLinksOf, Ct as startRun, Ei as DRIVER_IDS, Fn as templateOf, G as parseInputPairs, Gn as createSignals, Hn as gitRulesOf, K as resolveInputs, Kn as endOf, L as openStore, Lr as runDirOf, Pr as placeFiles, Qt as inspectProject, R as storePath, Si as readyDriver, St as walkSummary, Ti as AGENT_DRIVERS, Tt as userMessageText, U as createReplay, Un as loadProject, W as replayLoopAnswers, Wn as machineRulesOf, _n as takeFollowUps, _t as planNodeSession, an as sessionDriver, at as adoptedCalls, ct as DETACHED_ENV, di as isClaudeNode, dr as parseTemplate, dt as NOT_STARTED, et as createRelay, fn as createFollowUps, fr as renderTemplate, hi as retiredDriverHint, hr as socketPath, it as createCalls, lt as detachRun, m as resolveBase, mr as serveRun, n as resumedOptions, nr as runGh, or as createFeedback, pn as checkFollowUpsDue, t as createWorkspace, vn as deliverFollowUp, vr as maskReplacer } from "./src-DLsFsmOD.mjs";
2
- import { c as callsShown, d as createDecisionQueue, l as createTerminalHuman, o as formatEvent, s as formatRunEvent, t as attachRun } from "./attach-RQx__RzH.mjs";
3
- import { h as nodeSession, n as ORK_VERSION, v as findFollowUp } from "./__build_info__-C1Nm0hlJ.mjs";
4
- import { n as newRunId } from "./find-k489laBa.mjs";
5
- import { c as write, i as detachHint, l as writeErr, s as style } from "./output-B1kwo0YU.mjs";
6
- import { _ as clearOutputFiles, a as builtinExecutors, d as maskedEnv, f as maskedNamesOfRun, i as onPath, l as clearStateFiles, m as sessionEnv, n as missingProgramMessage, p as runScrubber, r as missingPrograms, t as envProblems, v as namedMcpEntries, y as resultOf } from "./src-DmmrX2_C.mjs";
7
- import { i as refusedBuiltin, o as workflowArg } from "./workflows-Djo1edlK.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-BS0nCccW.mjs";
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";
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";
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-CHqBO7wb.mjs";
10
+ import { i as runLimits, r as limitsRefusal, t as chatNotice } from "./limits-CXh052II.mjs";
11
11
  import path from "node:path";
12
- import { appendFileSync, existsSync, linkSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
12
+ import { existsSync, linkSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
13
13
  import { createHash, randomUUID } from "node:crypto";
14
14
  import { homedir } from "node:os";
15
15
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
16
16
  import { defineCommand } from "citty";
17
- // ../core/src/control/control.ts
18
- const startControl = async (options) => {
19
- const { store, runId } = options;
20
- const waiting = /* @__PURE__ */ new Map();
21
- let stopped = false;
22
- const check = () => {
23
- for (const [id, resolve] of waiting) {
24
- const decision = store.decision(id);
25
- if (decision !== void 0 && decision.status !== "open") {
26
- waiting.delete(id);
27
- resolve(decision);
28
- }
29
- }
30
- for (const command of store.takeCommands(runId)) if (command.kind === "message") options.onMessage(command.node, command.body);
31
- else if (command.kind === "relay") options.onRelay?.(command.node, command.from, command.body);
32
- else if (command.kind === "script") options.onScript?.(command.node, command.from, command.body);
33
- else if (command.kind === "notice") options.onNotice?.(command.node, command.body);
34
- else if (command.kind === "stop" && command.node === void 0) {
35
- if (stopped) continue;
36
- stopped = true;
37
- options.emit({
38
- type: "run.command",
39
- command: "stop"
40
- });
41
- options.onStop();
42
- } else if (!stopped) {
43
- if (options.onControl?.(command.kind, command.node) ?? false) options.emit({
44
- type: "run.command",
45
- command: command.kind,
46
- ...command.node === void 0 ? {} : { node: command.node }
47
- });
48
- }
17
+ // ../core/src/follow-ups/take.ts
18
+ const put = (rows, f, run, at) => {
19
+ const next = {
20
+ ...f,
21
+ takenBy: run,
22
+ updatedAt: at
49
23
  };
50
- const timer = setInterval(check, options.intervalMs ?? 1e3);
51
- let socket;
52
- try {
53
- socket = await serveRun({
54
- path: socketPath(runId, options.home),
55
- onWake: check,
56
- backlog: (after) => store.events(runId, after)
57
- });
58
- } catch {}
24
+ rows.putFollowUp(next);
25
+ return next;
26
+ };
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.
31
+ */
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;
35
+ };
36
+ /**
37
+ * The project's due `agent` follow-ups no live run has taken (`ids`), and those
38
+ * a live run holds (`held`), so a second `--follow-ups due` doesn't take them
39
+ * twice.
40
+ */
41
+ const availableDue = (rows, project, isLive, run = "", now = () => (/* @__PURE__ */ new Date()).toISOString()) => {
42
+ const at = Date.parse(now());
43
+ const due = rows.followUps(project).filter((f) => f.for === "agent" && f.status === "due");
59
44
  return {
60
- human: createDecisionQueue({
61
- store,
62
- runId,
63
- emit: options.emit,
64
- waitFor: (id, signal) => {
65
- const { promise, resolve, reject } = Promise.withResolvers();
66
- waiting.set(id, resolve);
67
- signal.addEventListener("abort", () => {
68
- waiting.delete(id);
69
- reject(/* @__PURE__ */ new Error("settled"));
70
- }, { once: true });
71
- check();
72
- return promise;
73
- },
74
- ...options.local === void 0 ? {} : { local: options.local }
75
- }),
76
- publish: (stored) => {
77
- socket?.publish(stored);
78
- },
79
- check,
80
- close: async () => {
81
- clearInterval(timer);
82
- await socket?.close();
83
- }
45
+ ids: due.filter((f) => !heldByLive(f, run, isLive, at)).map((f) => f.id),
46
+ held: due.filter((f) => heldByLive(f, run, isLive, at))
47
+ };
48
+ };
49
+ /**
50
+ * `ork run start --follow-ups <ids>`: the open `agent` follow-ups among `ids`
51
+ * become `run`'s brief; why each other id wasn't taken. One a live run took is
52
+ * refused; one a finished, failed or crashed run took can be taken again.
53
+ */
54
+ const takeFollowUps = (rows, taking, now = () => (/* @__PURE__ */ new Date()).toISOString()) => {
55
+ const taken = [];
56
+ const refused = [];
57
+ for (const id of taking.ids) {
58
+ const f = rows.followUp(taking.project, id);
59
+ if (f === void 0) refused.push(`${id}: there is no such follow-up`);
60
+ else if (f.for !== "agent") refused.push(`${id}: it is for ${f.for}`);
61
+ 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()));
64
+ }
65
+ return {
66
+ taken,
67
+ refused
84
68
  };
85
69
  };
86
70
  /** `ORK_HEAVY_SLOTS` as a count; anything but a positive integer is the default. */
@@ -288,31 +272,6 @@ const sweepLocks = (dir) => {
288
272
  slots: 1
289
273
  }).sweep());
290
274
  };
291
- // ../core/src/store/recorder.ts
292
- /**
293
- * @file Records a run as it happens: each event appended to the store and
294
- * copied to the run's `events.jsonl`, both with secrets masked, before
295
- * anything else sees it; and adds to a finished run (`ork chat`).
296
- */
297
- const EVENTS_FILE = "events.jsonl";
298
- /**
299
- * Appends to a run already in the store, e.g. `ork chat` resuming a finished
300
- * node's session; `runDir` gets the JSONL copy.
301
- */
302
- const appendRecorder = (store, runId, runDir) => {
303
- mkdirSync(runDir, { recursive: true });
304
- const file = path.join(runDir, EVENTS_FILE);
305
- return (event) => {
306
- const stored = store.append(runId, event);
307
- appendFileSync(file, `${JSON.stringify(stored, maskReplacer)}\n`);
308
- return stored;
309
- };
310
- };
311
- /** Begins `run` in the store; `runDir` gets the JSONL copy. */
312
- const createRecorder = (store, run, runDir) => {
313
- store.begin(run);
314
- return appendRecorder(store, run.id, runDir);
315
- };
316
275
  // src/runs/chat.ts
317
276
  /**
318
277
  * @file `ork chat`'s two paths. A node of a live run gets the message through
@@ -512,6 +471,15 @@ const briefOf = (followUps) => ["Do these follow-ups left by earlier changes:",
512
471
  ...f.body === "" ? [] : [f.body],
513
472
  ...f.where.length === 0 ? [] : [`Files: ${f.where.join(", ")}`]
514
473
  ])].join("\n");
474
+ /**
475
+ * Whether a run is going, as `ork ps` decides: running with its process alive.
476
+ * `undefined` for a run the store does not know yet: core holds its mark for a
477
+ * short while, as the run may be about to begin.
478
+ */
479
+ const runIsLive = (store) => (runId) => {
480
+ const [run] = store.lookup(runId);
481
+ return run === void 0 ? void 0 : liveStatus(run) === "running";
482
+ };
515
483
  const nothing = () => {};
516
484
  /**
517
485
  * The follow-ups `ids` (or prefixes) name, when every one can be taken as a
@@ -532,7 +500,8 @@ const checkTakeable = (store, project, ids) => {
532
500
  }, {
533
501
  project,
534
502
  run: "",
535
- ids: full
503
+ ids: full,
504
+ isLive: runIsLive(store)
536
505
  });
537
506
  const all = [...lines, ...refused];
538
507
  return all.length > 0 ? {
@@ -547,8 +516,8 @@ const checkTakeable = (store, project, ids) => {
547
516
  /**
548
517
  * @file Where a run's feedback comes from, beyond what its events say: Ork's
549
518
  * version (bound from the CLI's `package.json`) and the workflow file's
550
- * content hash; and the `follow_up` port of the one node `ork run --node`
551
- * runs.
519
+ * content hash; and the feedback and `follow_up` ports of the one node `ork
520
+ * run --node` runs.
552
521
  */
553
522
  /** Ork's version and the workflow's hash, for the run's feedback records. */
554
523
  /** The Ork version a run records in `run.started` and `run.resumed`. */
@@ -560,11 +529,27 @@ const feedbackOrigin = (workflowFile) => {
560
529
  } catch {}
561
530
  return origin;
562
531
  };
563
- /** The `follow_up` port of node `id`, kept as the project's rule says. */
564
- const nodeFollowUps = (options) => createFollowUps({
565
- runId: options.runId,
566
- sink: followUpSink(options)
567
- }).port(options.id, options.cwd);
532
+ /**
533
+ * Node `id`'s feedback port (with a graph) and `follow_up` port, kept as the
534
+ * project's rule says; both mask the values of what its run masks.
535
+ */
536
+ const nodeReports = (options, { workflow, graph, record }) => {
537
+ const { place, id } = options;
538
+ const scrub = runScrubber(maskedNamesOfRun(workflow, place, options.store.projects()), process.env);
539
+ const sink = followUpSink(options);
540
+ return {
541
+ ...graph === null ? {} : { feedback: createFeedback({
542
+ graph,
543
+ onEvent: record,
544
+ scrub
545
+ }).port(id) },
546
+ followUps: createFollowUps({
547
+ runId: options.runId,
548
+ sink,
549
+ scrub
550
+ }).port(id, options.cwd)
551
+ };
552
+ };
568
553
  // src/run/node.ts
569
554
  /**
570
555
  * @file `ork run --node`: checks a workflow and its inputs, plans one Claude
@@ -705,16 +690,16 @@ const runNode = async (options) => {
705
690
  ...servers.value
706
691
  }, {
707
692
  human: control.human,
708
- ...graph === null ? {} : { feedback: createFeedback({
709
- graph,
710
- onEvent: record
711
- }).port(id) },
712
- followUps: nodeFollowUps({
693
+ ...nodeReports({
713
694
  ...options,
714
695
  place,
715
696
  runId,
716
697
  id,
717
698
  cwd
699
+ }, {
700
+ workflow,
701
+ graph,
702
+ record
718
703
  })
719
704
  });
720
705
  started.resolve(session);
@@ -956,6 +941,15 @@ const dirtyAgentMessage = (files) => [
956
941
  ];
957
942
  /** Claude nodes that get their own worktree. */
958
943
  const worktreeNodes = (workflow) => Object.entries(workflow.nodes).filter(([, node]) => isClaudeNode(node) && node.type !== "agent.subagent" && (node.isolation ?? workflow.defaults?.isolation ?? "worktree") === "worktree").map(([id]) => id);
944
+ /**
945
+ * The project's folder for a message. Outside git, the place's root is the
946
+ * folder of the workflow file, which is `<project>/.ork/workflows` for a
947
+ * project's own workflow.
948
+ */
949
+ const projectFolder = (root) => {
950
+ const tail = path.sep + WORKFLOW_DIR;
951
+ return root.endsWith(tail) ? root.slice(0, -tail.length) : root;
952
+ };
959
953
  /** Checks the project for a run's worktrees, and resolves `git.base`. */
960
954
  const prepareCheckout = async (workflow, options, inputs) => {
961
955
  const isolated = worktreeNodes(workflow);
@@ -966,7 +960,7 @@ const prepareCheckout = async (workflow, options, inputs) => {
966
960
  const project = await inspectProject(options.cwd);
967
961
  if (project === null) return {
968
962
  ok: false,
969
- lines: [`${isolated.join(", ")} need a git worktree, but ${options.cwd} is not in a git repository with a commit; make a first commit (\`git commit --allow-empty -m "Start"\`) first, or pass --in-place to run them here`]
963
+ lines: [`${isolated.join(", ")} ${isolated.length === 1 ? "needs" : "need"} a git worktree, but ${projectFolder(options.cwd)} is not in a git repository with a commit; make a first commit (\`git commit --allow-empty -m "Start"\`) first, or pass --in-place to run them here`]
970
964
  };
971
965
  if (project.dirtyAgentFiles.length > 0 && options.allowDirty !== true) return {
972
966
  ok: false,
@@ -1252,7 +1246,7 @@ const isDriver = (value) => AGENT_DRIVERS.some((d) => d.id === value);
1252
1246
  /** Why `--driver` refuses a value: a retired id names its replacement. */
1253
1247
  const badDriver = (value) => `--${retiredDriverHint(value) ?? `driver must be one of ${AGENT_DRIVERS.map((d) => d.id).join(", ")}, got \`${value}\``}`;
1254
1248
  /** Loads the drivers only when a run starts, so other commands stay fast. */
1255
- const loadRuntime = async (driver, runs) => (await import("./src-BHod38UQ.mjs")).createRuntime(driver, sessionEnv(process.env), runs);
1249
+ const loadRuntime = async (driver, runs) => (await import("./src-D2qpd-G7.mjs")).createRuntime(driver, sessionEnv(process.env), runs);
1256
1250
  /**
1257
1251
  * Ctrl-C asks the run to stop, and so does a terminal closing or a polite kill,
1258
1252
  * so that the run ends tidily and leaves no result unscrubbed.
@@ -1374,35 +1368,20 @@ const run = defineCommand({
1374
1368
  process.exitCode = 1;
1375
1369
  return;
1376
1370
  }
1377
- const { prepareFollowUps: prepare, followUpsFlagFine: flagFine } = await import("./brief-Bs3cMQU0.mjs");
1371
+ const { prepareFollowUps: prepare, followUpsFlagFine: flagFine } = await import("./brief-BQbeoPMc.mjs");
1378
1372
  const cwd = process.cwd();
1379
1373
  if (refusedBuiltin([args.workflow], cwd) || !flagFine(rawArgs)) return;
1380
1374
  const target = workflowArg(args.workflow, cwd);
1381
1375
  const store = openStore();
1382
1376
  if (args.detach) {
1383
1377
  try {
1384
- const single = args.node !== void 0 && args.node !== "";
1385
- const runId = newRunId(store, single ? "node-" : "");
1386
- const detached = await detachRun({
1387
- store,
1388
- runId,
1389
- args: [
1390
- "run",
1391
- ...rawArgs.filter((arg) => arg !== "--detach"),
1392
- "--run-id",
1393
- runId
1394
- ],
1378
+ const { startDetached } = await import("./detached-BQlbmqR0.mjs");
1379
+ await startDetached(store, {
1380
+ rawArgs,
1395
1381
  cwd,
1396
- runDir: target.runDir(runId)
1382
+ target,
1383
+ node: args.node
1397
1384
  });
1398
- if (detached.ok) {
1399
- write(`▸ run ${detached.runId} started in the background`);
1400
- write(style("dim", ` ${detachHint(detached.runId)}`));
1401
- } else {
1402
- writeErr(detached.error);
1403
- writeErr(style("dim", `(output: ${detached.log})`));
1404
- process.exitCode = 1;
1405
- }
1406
1385
  } finally {
1407
1386
  store.close();
1408
1387
  }
@@ -1461,4 +1440,4 @@ const run = defineCommand({
1461
1440
  }
1462
1441
  }
1463
1442
  });
1464
- export { onInterrupt as a, runWorkflowFile as c, followUpsRule as d, refreshDue as f, machineSlotLedger as g, sweepLocks as h, loadRuntime as i, briefOf as l, machineLocksDir as m, flagValues as n, run as o, resumeChat as p, isDriver as r, terminalHuman as s, badDriver as t, checkTakeable as u };
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 };
@@ -1,4 +1,4 @@
1
- import { $t as git, en as gitOk } from "./src-DLsFsmOD.mjs";
1
+ import { nn as git, rn as gitOk } from "./src-Ciy7i3se.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";
@@ -1,6 +1,6 @@
1
- import { $ as sendFromScript, L as openStore, Q as scriptRefusal, Z as TOO_LONG } from "./src-DLsFsmOD.mjs";
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";
2
3
  import { l as writeErr } from "./output-B1kwo0YU.mjs";
3
- import { u as inheritedScrubber } from "./src-DmmrX2_C.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  // src/commands/send.ts
6
6
  /**