@krapht/ork 1.0.0-alpha.8 → 1.0.0-alpha.9

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 (33) hide show
  1. package/dist/{__build_info__-B83zdwIv.mjs → __build_info__-y1TPvZvp.mjs} +2 -2
  2. package/dist/bin.mjs +597 -50
  3. package/dist/{clean-NtapkN2x.mjs → clean-BRUXyk87.mjs} +5 -2
  4. package/dist/{completion-DAQMrf1u.mjs → completion-cpZHtv50.mjs} +5 -5
  5. package/dist/{context-C5wQNjp9.mjs → context-Dbay8l7P.mjs} +8 -7
  6. package/dist/{decide-BaEOo7sO.mjs → decide-BphP3ONM.mjs} +1 -1
  7. package/dist/{find-DDAkEoda.mjs → find-BXZjliwr.mjs} +1 -1
  8. package/dist/format-DeT7vL-8.mjs +191 -0
  9. package/dist/{in-a-run-DENitTUe.mjs → in-a-run-C4E9HfED.mjs} +1 -1
  10. package/dist/{limits-DezRXN0Z.mjs → limits-CBeoYrUH.mjs} +1 -1
  11. package/dist/{list-CZTh_wdE.mjs → list-BmxgNyd3.mjs} +11 -4
  12. package/dist/{mcp-B2DW26HO.mjs → mcp-DTreb7Nq.mjs} +6 -6
  13. package/dist/{output-D1wMNIly.mjs → output-BVkI6ZVv.mjs} +1 -1
  14. package/dist/{pause-HuQhHyET.mjs → pause-h66SC4rV.mjs} +4 -4
  15. package/dist/{relay-DCGGYSdz.mjs → relay-BxRhxL6n.mjs} +2 -2
  16. package/dist/{remove-0L02cre2.mjs → remove-CYGd9Csj.mjs} +14 -7
  17. package/dist/{send-C8pQfhED.mjs → send-BskOwN4p.mjs} +3 -3
  18. package/dist/{src-DosUvy4B.mjs → src-BwFxTank.mjs} +291 -100
  19. package/dist/{src-COHxAj7X.mjs → src-W1i5Bl6N.mjs} +23 -9
  20. package/dist/{src-BNhCiDQw.mjs → src-bOImrq43.mjs} +30 -11
  21. package/dist/{src-DCCbIABO.mjs → src-xd9DbQw8.mjs} +7 -7
  22. package/dist/ui/assets/{app-DBYZFrdE.js → app-BMg0OOv4.js} +19 -19
  23. package/dist/ui/assets/app-C8uhHVYp.css +1 -0
  24. package/dist/ui/assets/{index-DXoKpYjA.js → index-DY1q4SDl.js} +2 -2
  25. package/dist/ui/index.html +1 -1
  26. package/dist/{ui-Cdb05xJw.mjs → ui-B46Z3e9E.mjs} +4 -4
  27. package/dist/{usage-jYI2QHt7.mjs → usage-DpHXbQEu.mjs} +5 -5
  28. package/dist/{watch-D4lFXnHT.mjs → watch-CJO1ee6Y.mjs} +6 -6
  29. package/dist/{workflows-BF9fO-ER.mjs → workflows-BJdSHnkr.mjs} +4 -3
  30. package/dist/{worktrees-0iUiA6eD.mjs → worktrees-Ccf2lUhE.mjs} +72 -19
  31. package/package.json +1 -1
  32. package/dist/format-sGEQmQid.mjs +0 -643
  33. package/dist/ui/assets/app-D14lfYns.css +0 -1
package/dist/bin.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { $ as adoptedCalls, $n as settingsOf, $t as normalizeTitle, B as peerOf, Cn as inRepoPlace, Ct as runTree, D as inspectProject, Dn as projectsHome, En as placeFor, F as createCalls, Gt as FEEDBACK_TARGETS, I as addressOf, K as requestStop, L as endLink, Lt as PROJECT_FILE, M as clearGitLocalEnv, Mn as projectRootOf, N as parseInputPairs, On as runDirOf, P as resolveInputs, Qt as fingerprint, R as endLinksOf, Rt as gitRulesOf, Sn as hasInRepoFiles, St as runStatus, Tn as placeFiles, U as flattenTree, Un as beforeOf, Ut as FEEDBACK_KINDS, V as tellNode, Wt as FEEDBACK_SEVERITIES, Xn as WorkflowSchema, Yt as sendPost, Zt as createFeedback, _ as lateTriggers, _n as createAgent, an as serveRun, ar as INTEGRATIONS, at as followEvents, bn as loadAgents, bt as liveStatus, cn as wakeRun, cr as AGENT_TOOL_LAYOUTS, ct as planNodeSession, d as runningRunIds, dn as planAgentMigration, dr as firstLine, et as detachResume, f as runningScript, fn as applySteps, fr as EXPERIMENTS, gn as toolsInUse, gt as startRun, h as isNewer, hn as toolLinks, ht as walkSummary, i as NOT_STARTED, it as detachRun, jn as inside, kn as shownPath, kt as nestItems, l as planUpgrade, ln as maskReplacer, lr as ORK_LAYOUT, lt as namingNoDriver, mn as linkTools, mr as knownExperiments, n as resolveBase, nt as listKey, on as socketPath, pn as planMoveInto, pr as experimentsOn, q as tellLiveRun, qn as serializeWorkflow, qt as planPost, sn as socketRoom, t as createWorkspace, tr as isClaudeNode, tt as resumable, u as releaseNotes, ur as CLAUDE_DRIVERS, ut as sessionDriver, v as triggersReport, vn as deleteAgent, vt as userMessageText, wn as newProjectId, wt as templateOf, yn as catalogAgent, zt as loadProject } from "./src-DosUvy4B.mjs";
3
- import { a as formatRunEvent, i as formatEvent, n as formatRuns, o as createTerminalHuman, r as formatTree, s as createDecisionQueue, t as ago } from "./format-sGEQmQid.mjs";
4
- import { C as placeOf, T as openFixRun, _ as nodeSession, b as recordNote, c as checkDue, d as pendingNotice, f as readUpdateCache, g as activeTree, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, n as ORK_VERSION, o as updateSwitchOff, p as refreshUpdateCache, r as isSwitchedOn, s as runInstall, t as ORK_NAME, u as newerVersion$1, v as previewPost, w as feedbackActions, x as acceptItem, y as checkNote } from "./__build_info__-B83zdwIv.mjs";
5
- import { i as builtinWorkflowFile, n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-BaEOo7sO.mjs";
6
- import { n as newRunId, t as findRun } from "./find-DDAkEoda.mjs";
7
- import { a as write, c as openStore, i as style, l as storePath, n as cost, o as writeErr, s as isNodeEvent, t as confirm } from "./output-D1wMNIly.mjs";
8
- import { n as listOrkWorktrees, t as createdWorktrees } from "./list-CZTh_wdE.mjs";
9
- import { a as planClean, t as applyClean } from "./clean-NtapkN2x.mjs";
2
+ import { $ as adoptedCalls, $n as settingsOf, $t as normalizeTitle, B as peerOf, Cn as inRepoPlace, Ct as runTree, D as inspectProject, Dn as projectsHome, En as placeFor, F as createCalls, Gt as FEEDBACK_TARGETS, I as addressOf, K as requestStop, L as endLink, Lt as PROJECT_FILE, M as clearGitLocalEnv, Mn as projectRootOf, N as parseInputPairs, On as runDirOf, P as resolveInputs, Qt as fingerprint, R as endLinksOf, Rt as gitRulesOf, Sn as hasInRepoFiles, St as runStatus, Tn as placeFiles, U as flattenTree, Un as beforeOf, Ut as FEEDBACK_KINDS, V as tellNode, Wt as FEEDBACK_SEVERITIES, Xn as WorkflowSchema, Yt as sendPost, Zt as createFeedback, _ as lateTriggers, _n as createAgent, an as serveRun, ar as INTEGRATIONS, at as followEvents, bn as loadAgents, bt as liveStatus, cn as wakeRun, cr as AGENT_TOOL_LAYOUTS, ct as planNodeSession, d as runningRunIds, dn as planAgentMigration, dr as firstLine, et as detachResume, f as runningScript, fn as applySteps, fr as EXPERIMENTS, gn as toolsInUse, gt as startRun, h as isNewer, hn as toolLinks, ht as walkSummary, i as NOT_STARTED, it as detachRun, jn as inside, kn as shownPath, kt as nestItems, l as planUpgrade, ln as maskReplacer, lr as ORK_LAYOUT, lt as namingNoDriver, mn as linkTools, mr as knownExperiments, n as resolveBase, nt as listKey, on as socketPath, pn as planMoveInto, pr as experimentsOn, q as tellLiveRun, qn as serializeWorkflow, qt as planPost, rt as DETACHED_ENV, sn as socketRoom, t as createWorkspace, tr as isClaudeNode, tt as resumable, u as releaseNotes, un as maskSecrets, ur as CLAUDE_DRIVERS, ut as sessionDriver, v as triggersReport, vn as deleteAgent, vt as userMessageText, wn as newProjectId, wt as templateOf, yn as catalogAgent, zt as loadProject } from "./src-BwFxTank.mjs";
3
+ import { C as placeOf, T as openFixRun, _ as nodeSession, b as recordNote, c as checkDue, d as pendingNotice, f as readUpdateCache, g as activeTree, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, n as ORK_VERSION, o as updateSwitchOff, p as refreshUpdateCache, r as isSwitchedOn, s as runInstall, t as ORK_NAME, u as newerVersion$1, v as previewPost, w as feedbackActions, x as acceptItem, y as checkNote } from "./__build_info__-y1TPvZvp.mjs";
4
+ import { i as builtinWorkflowFile, n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-BphP3ONM.mjs";
5
+ import { n as newRunId, t as findRun } from "./find-BXZjliwr.mjs";
6
+ import { a as write, c as openStore, i as style, l as storePath, n as cost, o as writeErr, s as isNodeEvent, t as confirm } from "./output-BVkI6ZVv.mjs";
7
+ import { n as listOrkWorktrees, t as createdWorktrees } from "./list-BmxgNyd3.mjs";
8
+ import { a as planClean, t as applyClean } from "./clean-BRUXyk87.mjs";
10
9
  import { c as subcommandsOf, i as argsOf, n as groupedEntries, o as publicArgs, s as resolved, t as groupOf } from "./help-groups-BwYoAWsh.mjs";
11
- import { _ as namedMcpEntries, a as builtinExecutors, d as maskedEnv, f as maskedNamesOfRun, g as clearOutputFiles, h as sessionEnv, i as onPath, l as clearStateFiles, m as runScrubber, n as missingProgramMessage, r as missingPrograms, t as envProblems, v as resultOf } from "./src-COHxAj7X.mjs";
12
- import { c as registeredProjects, i as refusedBuiltin, n as WORKFLOW_SUFFIX, o as workflowArg, s as projectAt, t as WORKFLOW_DIR } from "./workflows-BF9fO-ER.mjs";
13
- import { a as validate, c as warningLines, i as loadWorkflow, o as validateFile, r as formatReport, s as walkLoaded, t as context } from "./context-C5wQNjp9.mjs";
14
- import { i as runLimits, r as limitsRefusal, t as chatNotice } from "./limits-DezRXN0Z.mjs";
15
- import { i as decideRefusal, n as chatRefusal } from "./in-a-run-DENitTUe.mjs";
10
+ import { _ as namedMcpEntries, a as builtinExecutors, d as maskedEnv, f as maskedNamesOfRun, g as clearOutputFiles, h as sessionEnv, i as onPath, l as clearStateFiles, m as runScrubber, n as missingProgramMessage, r as missingPrograms, t as envProblems, v as resultOf } from "./src-W1i5Bl6N.mjs";
11
+ import { c as registeredProjects, i as refusedBuiltin, n as WORKFLOW_SUFFIX, o as workflowArg, s as projectAt, t as WORKFLOW_DIR } from "./workflows-BJdSHnkr.mjs";
12
+ import { a as validate, c as warningLines, i as loadWorkflow, o as validateFile, r as formatReport, s as walkLoaded, t as context } from "./context-Dbay8l7P.mjs";
13
+ import { a as nodeVerdict, i as hasConflict, n as formatRuns, o as firstLine$1, r as formatTree, s as formatBusEvent, t as ago } from "./format-DeT7vL-8.mjs";
14
+ import { i as runLimits, r as limitsRefusal, t as chatNotice } from "./limits-CBeoYrUH.mjs";
15
+ import { i as decideRefusal, n as chatRefusal } from "./in-a-run-C4E9HfED.mjs";
16
16
  import path from "node:path";
17
17
  import { stringify } from "yaml";
18
18
  import { z } from "zod";
@@ -53,6 +53,221 @@ const readyDriver = (checks) => {
53
53
  ready: ready.length
54
54
  };
55
55
  };
56
+ // ../core/src/control/queue.ts
57
+ const PERMISSION_OPTIONS = [{
58
+ id: "allow",
59
+ label: "Allow"
60
+ }, {
61
+ id: "deny",
62
+ label: "Deny"
63
+ }];
64
+ const DENIED = "The user did not allow this tool.";
65
+ /** The deny message a session gets, with the person's words when given. */
66
+ const deniedMessage = (note) => note === void 0 ? DENIED : `${DENIED} They said: ${note}`;
67
+ /** The input fields that say what a tool will do, the first one present. */
68
+ const TOOL_INPUT_KEYS = [
69
+ "command",
70
+ "file_path",
71
+ "path",
72
+ "url",
73
+ "pattern"
74
+ ];
75
+ /** A tool's input for the decision's context: as written, cut at `max`. */
76
+ const inputContext = (input, max = 4e3) => {
77
+ const key = TOOL_INPUT_KEYS.find((k) => typeof input[k] === "string");
78
+ const text = key === void 0 ? JSON.stringify(input, void 0, 2) : String(input[key]);
79
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
80
+ };
81
+ const createDecisionQueue = (options) => {
82
+ const { store, runId, emit } = options;
83
+ const earlier = store.decisions({ runId });
84
+ let count = Math.max(0, ...earlier.map(({ id }) => Number(id.slice(runId.length + 1)) || 0));
85
+ for (const { id, node, status } of earlier) {
86
+ if (status !== "open") continue;
87
+ store.withdrawDecision(id);
88
+ emit({
89
+ type: "decision.withdrawn",
90
+ node,
91
+ decision: id
92
+ });
93
+ }
94
+ /** Opens a decision and settles it with the first answer. */
95
+ const decide = (open, local, withdrawn) => {
96
+ count += 1;
97
+ const id = `${runId}-${String(count)}`;
98
+ const record = store.openDecision({
99
+ ...open,
100
+ id,
101
+ runId
102
+ });
103
+ const event = {
104
+ type: "decision.opened",
105
+ node: record.node,
106
+ decision: id,
107
+ kind: record.kind,
108
+ question: record.question,
109
+ options: record.options
110
+ };
111
+ if (record.recommended !== void 0) event.recommended = record.recommended;
112
+ if (record.owner !== void 0) event.owner = record.owner;
113
+ emit(event);
114
+ const { promise, resolve, reject } = Promise.withResolvers();
115
+ const settled = new AbortController();
116
+ /** `note` is the stored one: masked, and absent when blank. */
117
+ const finish = (answer, by, note) => {
118
+ if (settled.signal.aborted) return;
119
+ settled.abort();
120
+ const answered = {
121
+ type: "decision.answered",
122
+ node: open.node,
123
+ decision: id,
124
+ answer,
125
+ by
126
+ };
127
+ if (note !== void 0) answered.note = note;
128
+ emit(answered);
129
+ resolve(note === void 0 ? {
130
+ answer,
131
+ by
132
+ } : {
133
+ answer,
134
+ by,
135
+ note
136
+ });
137
+ };
138
+ const withdraw = () => {
139
+ if (settled.signal.aborted) return;
140
+ settled.abort();
141
+ store.withdrawDecision(id);
142
+ emit({
143
+ type: "decision.withdrawn",
144
+ node: open.node,
145
+ decision: id
146
+ });
147
+ reject(/* @__PURE__ */ new Error("the question was withdrawn"));
148
+ };
149
+ if (withdrawn?.aborted === true) withdraw();
150
+ withdrawn?.addEventListener("abort", withdraw, { once: true });
151
+ const fromStore = async () => {
152
+ try {
153
+ const closed = await options.waitFor(id, settled.signal);
154
+ if (closed.status === "answered" && closed.answer !== void 0) finish(closed.answer, closed.answeredBy ?? "decide", closed.note);
155
+ } catch {}
156
+ };
157
+ const fromTerminal = async (ask) => {
158
+ try {
159
+ const { answer, note } = await ask(settled.signal);
160
+ if (store.answerDecision(id, answer, "terminal", note)) finish(answer, "terminal", store.decision(id)?.note);
161
+ } catch {}
162
+ };
163
+ fromStore();
164
+ if (local !== void 0) fromTerminal(local);
165
+ return promise;
166
+ };
167
+ return {
168
+ ask: (question) => {
169
+ const open = {
170
+ node: question.nodeId,
171
+ kind: "question",
172
+ question: question.question,
173
+ options: question.options
174
+ };
175
+ if (question.recommended !== void 0) open.recommended = question.recommended;
176
+ if (question.context !== void 0) open.context = question.context;
177
+ if (question.document !== void 0) open.document = question.document;
178
+ if (question.owner !== void 0) open.owner = question.owner;
179
+ const { local } = options;
180
+ return decide(open, local === void 0 ? void 0 : (signal) => {
181
+ let note;
182
+ return local.ask({
183
+ ...question,
184
+ question: maskSecrets(question.question),
185
+ ...question.context === void 0 ? {} : { context: maskSecrets(question.context) },
186
+ ...question.document === void 0 ? {} : { document: maskSecrets(question.document) },
187
+ signal,
188
+ onNote: (given) => {
189
+ note = given;
190
+ }
191
+ }).then((answer) => note === void 0 ? { answer } : {
192
+ answer,
193
+ note
194
+ });
195
+ }, question.signal).then(({ answer, note }) => {
196
+ if (note !== void 0) question.onNote?.(note);
197
+ return answer;
198
+ });
199
+ },
200
+ settled: (question) => {
201
+ count += 1;
202
+ const id = `${runId}-${String(count)}`;
203
+ const { owner } = question;
204
+ const record = store.openDecision({
205
+ id,
206
+ runId,
207
+ node: question.nodeId,
208
+ kind: "question",
209
+ question: question.question,
210
+ options: question.options,
211
+ owner,
212
+ ...question.recommended === void 0 ? {} : { recommended: question.recommended },
213
+ ...question.context === void 0 ? {} : { context: question.context }
214
+ });
215
+ emit({
216
+ type: "decision.opened",
217
+ node: record.node,
218
+ decision: id,
219
+ kind: "question",
220
+ question: record.question,
221
+ options: record.options,
222
+ owner,
223
+ ...record.recommended === void 0 ? {} : { recommended: record.recommended }
224
+ });
225
+ store.answerDecision(id, question.answer, "owner", question.note);
226
+ const note = store.decision(id)?.note;
227
+ emit({
228
+ type: "decision.answered",
229
+ node: record.node,
230
+ decision: id,
231
+ answer: question.answer,
232
+ by: "owner",
233
+ owner,
234
+ ...note === void 0 ? {} : { note }
235
+ });
236
+ },
237
+ permit: async (request) => {
238
+ const { local } = options;
239
+ let localMessage = DENIED;
240
+ const { answer, note } = await decide({
241
+ node: request.nodeId,
242
+ kind: "permission",
243
+ question: `Allow ${request.toolName}?`,
244
+ options: PERMISSION_OPTIONS,
245
+ context: inputContext(request.input)
246
+ }, local === void 0 ? void 0 : (signal) => {
247
+ let said;
248
+ return local.permit({
249
+ ...request,
250
+ signal,
251
+ onNote: (given) => {
252
+ said = given;
253
+ }
254
+ }).then((result) => {
255
+ if (!result.allow) localMessage = result.message;
256
+ const choice = result.allow ? "allow" : "deny";
257
+ return said === void 0 ? { answer: choice } : {
258
+ answer: choice,
259
+ note: said
260
+ };
261
+ });
262
+ }, request.signal);
263
+ if (note !== void 0) request.onNote?.(note);
264
+ return answer === "allow" ? { allow: true } : {
265
+ allow: false,
266
+ message: note === void 0 ? localMessage : deniedMessage(note)
267
+ };
268
+ }
269
+ };
270
+ };
56
271
  // ../core/src/control/control.ts
57
272
  const startControl = async (options) => {
58
273
  const { store, runId } = options;
@@ -482,6 +697,7 @@ const createReplay = (history, cutOff = /* @__PURE__ */ new Map(), mail, earlier
482
697
  return null;
483
698
  },
484
699
  previousSession: ({ id, item, round = 0 }) => item === void 0 || renewed.has(item.of) ? void 0 : [...fanOuts.items.get(id) ?? []].findLast(([before]) => before < round)?.[1].sessionId,
700
+ lastOutput: (id) => history.get(id)?.at(-1)?.output,
485
701
  kept: () => [...history.keys(), ...fanOuts.items.keys()],
486
702
  ...mail === void 0 ? {} : { mail },
487
703
  ...earlier === void 0 ? {} : { earlier }
@@ -589,6 +805,285 @@ const renderHelp = async (cmd, parent) => {
589
805
  const showHelp = async (cmd, parent) => {
590
806
  process.stdout.write(`${await renderHelp(cmd, parent)}\n\n`);
591
807
  };
808
+ // src/human.ts
809
+ /**
810
+ * @file The terminal `HumanChannel`: answers `ask_user` questions, gates and
811
+ * permission prompts on the terminal, one at a time, and denies or defers
812
+ * when no one is there. After a choice it offers one optional line for a
813
+ * note, which Enter skips. In a run it is the decision queue's local
814
+ * answerer, racing `ork decide`.
815
+ */
816
+ const PREVIEW = 160;
817
+ /** A document longer than this is offered (`d`) rather than printed. */
818
+ const SHORT_DOCUMENT_LINES = 40;
819
+ const NO_ONE_TO_PERMIT = "No one is at the terminal to approve this tool, so it is not allowed in this run.";
820
+ const NOTE_PROMPT = " Note for the run (optional, Enter to skip): ";
821
+ const NO_ONE_TO_ASK = "no one (nobody is at the terminal; use your best judgment and say so in your report)";
822
+ /** One line that shows what a tool is about to do. */
823
+ const previewInput = (toolName, input) => {
824
+ const key = TOOL_INPUT_KEYS.find((k) => typeof input[k] === "string");
825
+ const line = (key === void 0 ? JSON.stringify(input) : `${key}: ${String(input[key])}`).replaceAll(/\s+/gu, " ").trim();
826
+ return line.length > PREVIEW ? `${toolName} ${line.slice(0, 159)}…` : `${toolName} ${line}`;
827
+ };
828
+ /** The option an answer names: its number, or its id. */
829
+ const pickOption = (answer, options, recommended) => {
830
+ const value = answer.trim();
831
+ if (value === "") return recommended;
832
+ const index = Number(value);
833
+ if (Number.isInteger(index) && index >= 1 && index <= options.length) return options[index - 1]?.id;
834
+ return options.find((o) => o.id === value)?.id;
835
+ };
836
+ const optionLine = (option, index, recommended) => {
837
+ const label = option.label === void 0 ? "" : ` ${option.label}`;
838
+ const description = option.description === void 0 ? "" : style("dim", ` - ${option.description}`);
839
+ const mark = option.id === recommended ? style("green", " (recommended)") : "";
840
+ return ` ${String(index + 1)}) ${style("bold", option.id)}${label}${description}${mark}`;
841
+ };
842
+ /**
843
+ * Answers permission prompts and `ask_user` questions on the terminal, one at a
844
+ * time. Without a terminal it denies tools and leaves questions to the node. A
845
+ * withdrawn prompt (answered elsewhere) rejects, which frees the turn.
846
+ */
847
+ const createTerminalHuman = (io) => {
848
+ let rl;
849
+ let turn = Promise.resolve();
850
+ const say = (text) => {
851
+ io.output.write(`${text}\n`);
852
+ };
853
+ const prompt = (text, signal) => {
854
+ if (rl === void 0) {
855
+ rl = createInterface({
856
+ input: io.input,
857
+ output: io.output
858
+ });
859
+ if (io.interrupt !== void 0) rl.on("SIGINT", io.interrupt);
860
+ }
861
+ return signal === void 0 ? rl.question(text) : rl.question(text, { signal });
862
+ };
863
+ /** The optional line after a choice, when the asker takes a note. */
864
+ const takeNote = async (onNote, signal) => {
865
+ if (onNote === void 0) return;
866
+ const note = (await prompt(NOTE_PROMPT, signal)).trim();
867
+ if (note !== "") onNote(note);
868
+ };
869
+ const choose = async (hint, options, recommended, signal, document) => {
870
+ const answer = await prompt(` Choose${hint}: `, signal);
871
+ const picked = pickOption(answer, options, recommended);
872
+ if (picked !== void 0) return picked;
873
+ if (document !== void 0 && answer.trim() === "d") say(document);
874
+ else say(style("dim", " Type an option's number or id."));
875
+ return choose(hint, options, recommended, signal, document);
876
+ };
877
+ const oneAtATime = (work) => {
878
+ const result = turn.then(work);
879
+ turn = result.catch(() => null);
880
+ return result;
881
+ };
882
+ return {
883
+ permit: ({ nodeId, toolName, input, signal, onNote }) => oneAtATime(async () => {
884
+ if (signal?.aborted === true) throw new Error("the prompt was withdrawn");
885
+ say(`${style(["yellow", "bold"], "?")} ${style("bold", nodeId)} wants to run ${previewInput(toolName, input)}`);
886
+ if (!io.interactive) {
887
+ say(style("dim", ` denied: ${NO_ONE_TO_PERMIT}`));
888
+ return {
889
+ allow: false,
890
+ message: NO_ONE_TO_PERMIT
891
+ };
892
+ }
893
+ const answer = (await prompt(" Allow? [y/N] ", signal)).trim().toLowerCase();
894
+ if (answer === "y" || answer === "yes") return { allow: true };
895
+ await takeNote(onNote, signal);
896
+ return {
897
+ allow: false,
898
+ message: "The user did not allow this tool."
899
+ };
900
+ }),
901
+ ask: ({ nodeId, question, options, recommended, context, document, signal, onNote }) => oneAtATime(async () => {
902
+ if (signal?.aborted === true) throw new Error("the question was withdrawn");
903
+ const documentLines = document?.trimEnd().split("\n").length ?? 0;
904
+ if (document !== void 0 && documentLines <= SHORT_DOCUMENT_LINES) say(document);
905
+ say(`${style(["yellow", "bold"], "?")} ${style("bold", nodeId)} asks: ${question}`);
906
+ if (context !== void 0) say(style("dim", ` ${context.replaceAll("\n", "\n ")}`));
907
+ for (const [index, option] of options.entries()) say(optionLine(option, index, recommended));
908
+ if (!io.interactive) {
909
+ const answer = recommended ?? NO_ONE_TO_ASK;
910
+ say(style("dim", ` no terminal; answered ${answer}`));
911
+ return answer;
912
+ }
913
+ const fallback = options.findIndex((o) => o.id === recommended);
914
+ const hint = fallback === -1 ? "" : ` [${String(fallback + 1)}]`;
915
+ if (documentLines > SHORT_DOCUMENT_LINES) say(` Document: ${String(documentLines)} lines. Type d to read it.`);
916
+ const picked = await choose(hint, options, recommended, signal, document);
917
+ await takeNote(onNote, signal);
918
+ return picked;
919
+ }),
920
+ close: () => {
921
+ rl?.close();
922
+ }
923
+ };
924
+ };
925
+ // src/run/format-result.ts
926
+ const RUN_MARK = {
927
+ succeeded: style("green", "✓"),
928
+ failed: style("red", "✗"),
929
+ budget_exhausted: style("yellow", "!"),
930
+ quota_exhausted: style("yellow", "!"),
931
+ timed_out: style("yellow", "!"),
932
+ interrupted: style("yellow", "!")
933
+ };
934
+ /** `1 failure handled`, `2 failures handled`. */
935
+ const failuresHandled = (count) => `${String(count)} ${count === 1 ? "failure" : "failures"} handled`;
936
+ /**
937
+ * The run summary: status, cost, what ran, what was skipped and which failures
938
+ * an edge handled, branches to look at, why, and mail to nodes that never ran.
939
+ */
940
+ const formatRunResult = (result) => {
941
+ const ran = result.nodes.filter((n) => n.runs > 0).length;
942
+ const skipped = result.skipped ?? result.nodes.length - ran;
943
+ const handled = result.failuresHandled ?? 0;
944
+ const lines = ["", `${RUN_MARK[result.status]} run ${result.runId} ${result.status.replace("_", " ")} ${style("dim", `· ${cost(result.costUsd)} · ${String(ran)} ran, ${String(skipped)} skipped${handled === 0 ? "" : `, ${failuresHandled(handled)}`}`)}`];
945
+ for (const kept of result.worktrees) lines.push(` ${kept.id}: ${kept.branch ?? "detached"} ${style("dim", `at ${kept.path} (${kept.reason})`)}`);
946
+ for (const reason of result.reasons) lines.push(` ${style("red", reason)}`);
947
+ for (const { node, messages } of result.unread ?? []) lines.push(` ${style(["yellow", "bold"], "warning")} ${node} never ran, so ${messages === 1 ? "1 message" : `${String(messages)} messages`} to it went unread`);
948
+ return lines;
949
+ };
950
+ // src/run/format.ts
951
+ /** Who answered a decision, as the log says it. */
952
+ const ANSWERED_BY = {
953
+ terminal: "terminal",
954
+ decide: "ork decide",
955
+ ui: "ork ui",
956
+ owner: "its owner"
957
+ };
958
+ const STATUS_MARK = {
959
+ pass: style("green", "✓"),
960
+ done: style("green", "✓"),
961
+ changes_requested: style("yellow", "!"),
962
+ fail: style("red", "✗")
963
+ };
964
+ const seconds = (ms) => `${(ms / 1e3).toFixed(1)}s`;
965
+ const indent = (text) => text.trimEnd().split("\n").map((line) => ` ${line}`);
966
+ /** The usage line: cost, tokens, turns and time. */
967
+ const formatUsage = ({ usage }) => style("dim", [
968
+ cost(usage.costUsd),
969
+ `${String(usage.inputTokens)} in / ${String(usage.outputTokens)} out (${String(usage.cacheReadTokens)} cached)`,
970
+ `${String(usage.turns)} turns`,
971
+ seconds(usage.durationMs)
972
+ ].join(" · "));
973
+ /** How a finished session reads on the terminal. */
974
+ const formatOutcome = (nodeId, outcome) => {
975
+ const { report } = outcome;
976
+ if (report === null) return [
977
+ `${style("red", "✗")} ${style("bold", nodeId)} ended without a report (${outcome.subtype})`,
978
+ ...outcome.errors.map((e) => ` ${style("red", e)}`),
979
+ ` ${formatUsage(outcome)}`
980
+ ];
981
+ const lines = [`${STATUS_MARK[report.status] ?? "-"} ${style("bold", nodeId)} ${report.status}: ${report.summary}`];
982
+ if (report.branch !== void 0) lines.push(` branch: ${report.branch}`);
983
+ for (const [name, file] of Object.entries(report.artifacts)) lines.push(` ${name}: ${file}`);
984
+ for (const [name, value] of Object.entries(report.fields)) lines.push(` ${name}: ${JSON.stringify(value)}`);
985
+ lines.push(` ${formatUsage(outcome)}`);
986
+ return lines;
987
+ };
988
+ /** The transcript lines for one event; tool names come from `tools`. */
989
+ const formatEvent = (nodeId, event, tools) => {
990
+ if (event.type === "session.started") {
991
+ const fork = event.fork === true ? ", a fork to answer a question" : "";
992
+ return [style("dim", `▸ ${nodeId} (${event.model}, session ${event.sessionId}${fork})`)];
993
+ }
994
+ if (event.type === "assistant.text") return indent(event.text);
995
+ if (event.type === "tool.called") {
996
+ tools.set(event.id, event.name);
997
+ return [style("dim", ` · ${previewInput(event.name, event.input)}`)];
998
+ }
999
+ if (event.type === "tool.result") return event.isError ? [style("red", ` ✗ ${tools.get(event.id) ?? "tool"} failed`)] : [];
1000
+ if (event.type === "plan.limit") return event.status === "allowed" ? [] : [style("yellow", ` ! plan: ${event.window.replaceAll("_", " ")} limit ${event.status === "rejected" ? "reached" : "is close"}`)];
1001
+ return formatOutcome(nodeId, event.outcome);
1002
+ };
1003
+ const items = (count) => `${String(count)} ${count === 1 ? "item" : "items"}`;
1004
+ /** Transcript lines for one run event, prefixed with the node they are from. */
1005
+ const formatRunEvent = (event, width, tools, terminal = false) => {
1006
+ const tag = (id) => style("cyan", `${id.padEnd(width)} │`);
1007
+ if (event.type === "run.started") return [style("dim", `▸ run ${event.runId} of ${event.workflow} (starts at ${event.entries.join(", ")})`), ...event.settings?.trigger === void 0 ? [] : [style("dim", ` started by trigger ${event.settings.trigger}; untrusted inputs: ${(event.settings.untrusted ?? []).join(", ") || "none"}`)]];
1008
+ if (event.type === "node.started") {
1009
+ const round = event.round > 1 ? ` (round ${String(event.round)})` : "";
1010
+ const owner = event.owner === void 0 ? "" : `, for ${event.owner}`;
1011
+ return [`${tag(event.id)} ${style("dim", `${event.nodeType}${round}${owner}`)}`];
1012
+ }
1013
+ if (event.type === "node.event") {
1014
+ const inner = event.event;
1015
+ if (inner.type === "session.finished") return [];
1016
+ const fork = inner.fork === true ? style("dim", "fork · ") : "";
1017
+ if (inner.type === "session.started") {
1018
+ const why = inner.fork === true ? ", to answer a question" : "";
1019
+ return [`${tag(event.id)} ${fork}${style("dim", `${inner.model}, session ${inner.sessionId}${why}`)}`];
1020
+ }
1021
+ return formatEvent(event.id, event.event, tools).map((line) => `${tag(event.id)} ${fork}${line.replace(/^ {2}/u, "")}`);
1022
+ }
1023
+ if (event.type === "node.finished") {
1024
+ const conflict = hasConflict(event.output);
1025
+ const mark = event.ok ? style(conflict ? "yellow" : "green", conflict ? "!" : "✓") : style("red", "✗");
1026
+ const spent = event.usage === void 0 ? "" : style("dim", ` · ${cost(event.usage.costUsd)}`);
1027
+ return [`${tag(event.id)} ${mark} ${nodeVerdict(event.output, event.ok, event.error)}${spent}`];
1028
+ }
1029
+ if (event.type === "node.skipped") return [`${tag(event.id)} ${style("dim", "- skipped")}`];
1030
+ if (event.type === "loop.exhausted") return [`${style(["yellow", "bold"], "!")} the loop ${event.from} -> ${event.to} used all ${String(event.maxRounds)} rounds`];
1031
+ if (event.type === "watch.started") return [`${tag(event.id)} ${style("dim", `watching until ${event.until}, every ${event.every}`)}`];
1032
+ if (event.type === "watch.changed") return [`${tag(event.id)} ${style("dim", `look ${String(event.looks)}:`)} ${event.said}`];
1033
+ if (event.type === "watch.ended") return [`${tag(event.id)} ${style("dim", `${event.outcome} after ${String(event.looks)} looks`)}`];
1034
+ if (event.type === "edge.taken") return [];
1035
+ if (event.type === "worktree") {
1036
+ const detail = event.detail === void 0 ? "" : ` (${event.detail})`;
1037
+ const what = event.action === "removed" && event.branch !== void 0 ? `worktree of ${event.branch} (branch kept)` : `${event.branch ?? event.path}${detail}`;
1038
+ const line = `${event.action} ${what}`;
1039
+ return [`${tag(event.id)} ${event.action === "conflict" ? style("yellow", `! ${line}`) : style("dim", `⎇ ${line}`)}`];
1040
+ }
1041
+ if (event.type === "decision.opened") {
1042
+ const what = event.kind === "permission" ? "asks to" : "asks:";
1043
+ const question = event.kind === "permission" ? event.question.replace(/^Allow /u, "run ").replace(/\?$/u, "") : event.question;
1044
+ const where = event.owner === void 0 ? `decision ${event.decision}; ${terminal ? "answer here or with ork decide" : "ork decide"}` : `decision ${event.decision}, via ${event.owner}`;
1045
+ return [`${tag(event.node)} ${style(["yellow", "bold"], "?")} ${what} ${question} ${style("dim", `(${where})`)}`];
1046
+ }
1047
+ if (event.type === "decision.answered") {
1048
+ const by = event.by === "owner" && event.owner !== void 0 ? event.owner : ANSWERED_BY[event.by];
1049
+ const said = event.note === void 0 ? "" : ` · said: ${event.note.replaceAll(/\s+/gu, " ")}`;
1050
+ return [`${tag(event.node)} ${style("dim", `→ ${event.answer} (${by})${said}`)}`];
1051
+ }
1052
+ if (event.type === "decision.withdrawn") return [`${tag(event.node)} ${style("dim", "→ question withdrawn")}`];
1053
+ if (event.type === "run.command") {
1054
+ const node = event.node === void 0 ? "" : ` --node ${event.node}`;
1055
+ return [style(["yellow", "bold"], `! ork ${event.command}${node} received`)];
1056
+ }
1057
+ if (event.type === "node.held") {
1058
+ const at = event.at === "tool" ? "its tool call waits for ork continue" : "it starts after ork continue";
1059
+ return [`${tag(event.id)} ${style("yellow", `‖ paused: ${at}`)}`];
1060
+ }
1061
+ if (event.type === "node.released") return [`${tag(event.id)} ${style("dim", "▸ continues")}`];
1062
+ if (event.type === "each.listed") {
1063
+ const round = event.round > 1 ? ` (round ${String(event.round)})` : "";
1064
+ return [`${tag(event.node)} ${style("dim", `${items(event.count)}${round}`)}`];
1065
+ }
1066
+ if (event.type === "each.exceeded") {
1067
+ const over = `${items(event.count)}, over maxItems ${String(event.maxItems)}`;
1068
+ return [`${tag(event.node)} ${style("yellow", `! ${over}`)}`];
1069
+ }
1070
+ if (event.type === "run.finished") return formatRunResult(event.result);
1071
+ if (event.type === "run.resumed") {
1072
+ const [one] = event.kept;
1073
+ const kept = one === void 0 ? "every node runs again" : event.kept.length === 1 ? `${one} keeps its result` : `${event.kept.join(", ")} keep their results`;
1074
+ return ["", style("dim", `▸ resumed: ${kept}`)];
1075
+ }
1076
+ if (event.type === "feedback.recorded") {
1077
+ const { target, kind, title } = event.feedback;
1078
+ const line = style("dim", `✎ feedback (${target}, ${kind}): ${title}`);
1079
+ return [event.node === void 0 ? line : `${tag(event.node)} ${line}`];
1080
+ }
1081
+ if (event.type === "user.message") {
1082
+ const note = event.delivered === "queued" ? " (for its next session)" : "";
1083
+ return [`${tag(event.node)} ${style(["magenta", "bold"], "you:")} ${firstLine$1(event.body)}${style("dim", note)}`];
1084
+ }
1085
+ return formatBusEvent(event).map((line) => `${tag(event.node)} ${line}`);
1086
+ };
592
1087
  // src/update/notify.ts
593
1088
  /**
594
1089
  * @file The new-version notice (ADR-038). At most once a day a command starts a
@@ -684,7 +1179,7 @@ const versionCheck = (current, cache, checksOff) => {
684
1179
  return {
685
1180
  name: "ork",
686
1181
  status: "ok",
687
- detail: `${current} (${cache?.latest === void 0 ? checksOff ? "update check off" : "not checked for updates yet" : `the latest as of ${cache.checkedAt.slice(0, 10)}`})`
1182
+ detail: `${current} (${cache?.latest === void 0 ? checksOff === null ? "not checked for updates yet" : `the daily update check is off here: ${checksOff}` : `the latest as of ${cache.checkedAt.slice(0, 10)}`})`
688
1183
  };
689
1184
  };
690
1185
  // src/doctor/checks.ts
@@ -708,7 +1203,7 @@ const exec = (program, args) => new Promise((resolve) => {
708
1203
  });
709
1204
  });
710
1205
  /** Ork's own version, against the last update check (no network). */
711
- const orkCheck = () => versionCheck(ORK_VERSION, readUpdateCache(updateCachePath()), updateCheckOff(process.env, [], true) !== null);
1206
+ const orkCheck = () => versionCheck(ORK_VERSION, readUpdateCache(updateCachePath()), updateCheckOff(process.env, [], process.stderr.isTTY));
712
1207
  const MIN_NODE = [24, 20];
713
1208
  const checkNode = (version) => {
714
1209
  const [major = 0, minor = 0] = version.split(".").map(Number);
@@ -724,6 +1219,23 @@ const checkNode = (version) => {
724
1219
  hint: `Ork needs Node ${MIN_NODE.join(".")} or later.`
725
1220
  };
726
1221
  };
1222
+ /** A work tree with no commit has no `HEAD` for a worktree to branch from. */
1223
+ const checkHead = async (run) => {
1224
+ return (await run("git", [
1225
+ "rev-parse",
1226
+ "--verify",
1227
+ "HEAD"
1228
+ ])).ok ? {
1229
+ name: "git commits",
1230
+ status: "ok",
1231
+ detail: "HEAD exists"
1232
+ } : {
1233
+ name: "git commits",
1234
+ status: "warn",
1235
+ detail: "no commit yet",
1236
+ hint: "Make a first commit: worktree runs branch from HEAD."
1237
+ };
1238
+ };
727
1239
  const checkGit = async (run) => {
728
1240
  const version = await run("git", ["--version"]);
729
1241
  if (!version.ok) return [{
@@ -733,20 +1245,30 @@ const checkGit = async (run) => {
733
1245
  hint: "Install git; Ork gives each writing node its own worktree."
734
1246
  }];
735
1247
  const inside = await run("git", ["rev-parse", "--is-inside-work-tree"]);
736
- return [{
737
- name: "git",
738
- status: "ok",
739
- detail: firstLine(version.stdout)
740
- }, inside.ok ? {
741
- name: "git repo",
742
- status: "ok",
743
- detail: "inside a work tree"
744
- } : {
745
- name: "git repo",
746
- status: "warn",
747
- detail: "not a git repository",
748
- hint: "Run Ork inside a git repository so nodes can use worktrees."
749
- }];
1248
+ const head = inside.ok ? await checkHead(run) : null;
1249
+ return [
1250
+ {
1251
+ name: "git",
1252
+ status: "ok",
1253
+ detail: firstLine(version.stdout)
1254
+ },
1255
+ inside.ok ? {
1256
+ name: "git repo",
1257
+ status: "ok",
1258
+ detail: "inside a work tree"
1259
+ } : {
1260
+ name: "git repo",
1261
+ status: "warn",
1262
+ detail: "not a git repository",
1263
+ hint: "Run Ork inside a git repository so nodes can use worktrees."
1264
+ },
1265
+ ...head === null ? [] : [head]
1266
+ ];
1267
+ };
1268
+ /** What `ork init` warns of: a work tree with no commit, else null. */
1269
+ const headWarning = async (run) => {
1270
+ const head = (await checkGit(run)).find((r) => r.name === "git commits");
1271
+ return head?.status === "warn" ? `${head.detail}. ${head.hint ?? ""}`.trim() : null;
750
1272
  };
751
1273
  /**
752
1274
  * Runs every check: Node and git, then every registered Claude driver and
@@ -1011,6 +1533,16 @@ const createLogPrinter = (options) => {
1011
1533
  };
1012
1534
  };
1013
1535
  /**
1536
+ * Why `--node` names nothing in this run, or `null`: no event names it and the
1537
+ * run didn't declare it. A live run may still start it, so that is not
1538
+ * refused.
1539
+ */
1540
+ const unknownNode = (stored, node, live) => {
1541
+ const named = stored.some(({ event }) => isNodeEvent(event, node));
1542
+ const declared = stored.some(({ event }) => event.type === "run.started" && event.nodes.some((n) => n.id === node));
1543
+ return named || declared || live ? null : `Run has no node ${node}.`;
1544
+ };
1545
+ /**
1014
1546
  * Prints a run's events; with `follow`, then each new one as it is stored:
1015
1547
  * pushed over the run's socket, or polled from the store when there is none.
1016
1548
  * Returns when `run.finished` is stored, the run's process is gone, or `signal`
@@ -1537,7 +2069,7 @@ const runWorkflowFile = async (options) => {
1537
2069
  for (const event of signals(raw)) {
1538
2070
  control.publish(record(event));
1539
2071
  if (options.json) options.out(JSON.stringify(event));
1540
- else for (const line of formatRunEvent(event, width, tools)) options.out(line);
2072
+ else for (const line of formatRunEvent(event, width, tools, options.human !== void 0)) options.out(line);
1541
2073
  }
1542
2074
  };
1543
2075
  const workspace = root === void 0 ? void 0 : createWorkspace({
@@ -1634,7 +2166,7 @@ const flagValues = (rawArgs, flag) => {
1634
2166
  };
1635
2167
  const isDriver = (value) => CLAUDE_DRIVERS.some((d) => d.id === value);
1636
2168
  /** Loads the drivers only when a run starts, so other commands stay fast. */
1637
- const loadRuntime = async (driver) => (await import("./src-BNhCiDQw.mjs")).createRuntime(driver, sessionEnv(process.env));
2169
+ const loadRuntime = async (driver) => (await import("./src-bOImrq43.mjs")).createRuntime(driver, sessionEnv(process.env));
1638
2170
  /**
1639
2171
  * Ctrl-C asks the run to stop, and so does a terminal closing or a polite kill,
1640
2172
  * so that the run ends tidily and leaves no result unscrubbed.
@@ -1652,11 +2184,18 @@ const onInterrupt = (stop) => {
1652
2184
  process.once("SIGHUP", interrupt);
1653
2185
  };
1654
2186
  /** The terminal that answers a run's questions; none in a detached run. */
1655
- const terminalHuman = () => process.env["ORK_DETACHED"] === "1" ? void 0 : createTerminalHuman({
1656
- input: process.stdin,
1657
- output: process.stderr,
1658
- interactive: process.stdin.isTTY
1659
- });
2187
+ const terminalHuman = () => {
2188
+ const detached = process.env[DETACHED_ENV] === "1";
2189
+ if (detached) writeErr(style("dim", "detached run: no terminal asks; answer with ork decide"));
2190
+ return detached ? void 0 : createTerminalHuman({
2191
+ input: process.stdin,
2192
+ output: process.stderr,
2193
+ interactive: process.stdin.isTTY,
2194
+ interrupt: () => {
2195
+ process.kill(process.pid, "SIGINT");
2196
+ }
2197
+ });
2198
+ };
1660
2199
  const run = defineCommand({
1661
2200
  meta: {
1662
2201
  name: "run",
@@ -4188,6 +4727,12 @@ const logs = defineCommand({
4188
4727
  process.exitCode = 1;
4189
4728
  return;
4190
4729
  }
4730
+ const problem = args.node === void 0 ? null : unknownNode(store.events(found.run.id), args.node, args.follow && found.run.status === "running");
4731
+ if (problem !== null) {
4732
+ writeErr(problem);
4733
+ process.exitCode = 1;
4734
+ return;
4735
+ }
4191
4736
  const abort = new AbortController();
4192
4737
  process.once("SIGINT", () => {
4193
4738
  abort.abort();
@@ -4352,6 +4897,8 @@ const init = defineCommand({
4352
4897
  skills: args.skills,
4353
4898
  link: args.link
4354
4899
  });
4900
+ const noCommit = await headWarning(exec);
4901
+ if (noCommit !== null) write(style("yellow", `\n! git: ${noCommit}`));
4355
4902
  write(`\nNext: edit ${WORKFLOW_DIR}/, then run ${style("bold", "ork validate")}.`);
4356
4903
  }
4357
4904
  });
@@ -4550,27 +5097,27 @@ const main = defineCommand({
4550
5097
  ps,
4551
5098
  logs,
4552
5099
  tree,
4553
- usage: () => import("./usage-jYI2QHt7.mjs").then((module) => module.usage),
4554
- prune: () => import("./usage-jYI2QHt7.mjs").then((module) => module.prune),
5100
+ usage: () => import("./usage-DpHXbQEu.mjs").then((module) => module.usage),
5101
+ prune: () => import("./usage-DpHXbQEu.mjs").then((module) => module.prune),
4555
5102
  decide,
4556
- relay: () => import("./relay-DCGGYSdz.mjs").then((module) => module.relay),
4557
- pause: () => import("./pause-HuQhHyET.mjs").then((module) => module.pause),
4558
- continue: () => import("./pause-HuQhHyET.mjs").then((module) => module.continueRun),
5103
+ relay: () => import("./relay-BxRhxL6n.mjs").then((module) => module.relay),
5104
+ pause: () => import("./pause-h66SC4rV.mjs").then((module) => module.pause),
5105
+ continue: () => import("./pause-h66SC4rV.mjs").then((module) => module.continueRun),
4559
5106
  stop,
4560
5107
  chat,
4561
- send: () => import("./send-C8pQfhED.mjs").then((module) => module.send),
5108
+ send: () => import("./send-BskOwN4p.mjs").then((module) => module.send),
4562
5109
  resume,
4563
5110
  feedback,
4564
5111
  context,
4565
- worktrees: () => import("./worktrees-0iUiA6eD.mjs").then((module) => module.worktrees),
4566
- wt: () => import("./worktrees-0iUiA6eD.mjs").then((module) => module.worktrees),
4567
- watch: () => import("./watch-D4lFXnHT.mjs").then((module) => module.watch),
4568
- mcp: () => import("./mcp-B2DW26HO.mjs").then((module) => module.mcp),
4569
- ui: () => import("./ui-Cdb05xJw.mjs").then((module) => module.ui),
5112
+ worktrees: () => import("./worktrees-Ccf2lUhE.mjs").then((module) => module.worktrees),
5113
+ wt: () => import("./worktrees-Ccf2lUhE.mjs").then((module) => module.worktrees),
5114
+ watch: () => import("./watch-CJO1ee6Y.mjs").then((module) => module.watch),
5115
+ mcp: () => import("./mcp-DTreb7Nq.mjs").then((module) => module.mcp),
5116
+ ui: () => import("./ui-B46Z3e9E.mjs").then((module) => module.ui),
4570
5117
  doctor,
4571
5118
  upgrade,
4572
- completion: () => import("./completion-DAQMrf1u.mjs").then((module) => module.completion),
4573
- __complete: () => import("./completion-DAQMrf1u.mjs").then((module) => module.completeCommand(main))
5119
+ completion: () => import("./completion-cpZHtv50.mjs").then((module) => module.completion),
5120
+ __complete: () => import("./completion-cpZHtv50.mjs").then((module) => module.completeCommand(main))
4574
5121
  }
4575
5122
  });
4576
5123
  // src/bin.ts
@@ -4588,7 +5135,7 @@ const main = defineCommand({
4588
5135
  clearGitLocalEnv();
4589
5136
  const argv = process.argv.slice(2);
4590
5137
  if (argv[0] === "__complete") {
4591
- const { printCompletions } = await import("./completion-DAQMrf1u.mjs");
5138
+ const { printCompletions } = await import("./completion-cpZHtv50.mjs");
4592
5139
  await printCompletions(main, argv.slice(1));
4593
5140
  } else if (process.env["ORK_UPDATE_CHECK_CHILD"] === "1") await runUpdateChild();
4594
5141
  else {