@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
@@ -1,4 +1,4 @@
1
- import { At as runScope, Bt as MCP_FILE, Ht as serversIn, It as declaredOutputOf, Jn as markValue, Mt as declaredProblem, Nt as calledWorkflows, Pt as envReadsOf, Un as beforeOf, Vt as mcpNotText, Wn as programsRunBy, ar as INTEGRATIONS, ct as planNodeSession, ft as reportSchemaFor, ir as timeoutMs, nn as parseTemplate, nr as isToolNode, or as TOOL_PREFIX, rn as renderTemplate, s as planReason, sr as integrationFor, tn as evaluate, ut as sessionDriver, yt as heldTimeout } from "./src-DosUvy4B.mjs";
1
+ import { At as runScope, Bt as MCP_FILE, Ht as serversIn, It as declaredOutputOf, Jn as markValue, Mt as declaredProblem, Nt as calledWorkflows, Pt as envReadsOf, Un as beforeOf, Vt as mcpNotText, Wn as programsRunBy, ar as INTEGRATIONS, ct as planNodeSession, ft as reportSchemaFor, ir as timeoutMs, nn as parseTemplate, nr as isToolNode, or as TOOL_PREFIX, rn as renderTemplate, s as planReason, sr as integrationFor, tn as evaluate, ut as sessionDriver, yt as heldTimeout } from "./src-BwFxTank.mjs";
2
2
  import path from "node:path";
3
3
  import { accessSync, constants, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { spawn } from "node:child_process";
@@ -453,25 +453,39 @@ const askFork = async (context, owner, question, deps) => {
453
453
  /** What the person sees of a question its asker's owner passed on. */
454
454
  const passedOnContext = (context, owner, note) => [...context === void 0 ? [] : [context, ""], note === void 0 ? `${owner} passed this on.` : `${owner} passed this on: ${note}`].join("\n");
455
455
  /**
456
+ * The node's channel to the person: what it asked is withdrawn when it stops,
457
+ * so a stopped node leaves no decision open.
458
+ */
459
+ const withdrawnOnStop = (context) => {
460
+ const { human } = context;
461
+ const signalOf = (asked) => asked === void 0 ? context.signal : AbortSignal.any([asked, context.signal]);
462
+ return {
463
+ permit: (request) => human.permit({
464
+ ...request,
465
+ signal: signalOf(request.signal)
466
+ }),
467
+ ask: (question) => human.ask({
468
+ ...question,
469
+ signal: signalOf(question.signal)
470
+ }),
471
+ ...human.settled === void 0 ? {} : { settled: human.settled }
472
+ };
473
+ };
474
+ /**
456
475
  * The child's channel when its owner takes its questions first: a question goes
457
476
  * to a fork of the owner's session, then to the person if the fork passes it on
458
477
  * or can't answer. Permission prompts go to the person as before.
459
478
  */
460
479
  const ownerFirst = (context, owner, deps) => {
461
- const { human } = context;
480
+ const human = withdrawnOnStop(context);
462
481
  return {
463
482
  permit: (request) => human.permit(request),
464
483
  ask: async (question) => {
465
484
  const answered = await askFork(context, owner, question, deps);
466
485
  if (context.signal.aborted) throw new Error(`${context.id} was stopped`);
467
- const signal = question.signal === void 0 ? context.signal : AbortSignal.any([question.signal, context.signal]);
468
- if (answered === null) return human.ask({
469
- ...question,
470
- signal
471
- });
486
+ if (answered === null) return human.ask(question);
472
487
  if (answered.choice === passOnId(question.options)) return human.ask({
473
488
  ...question,
474
- signal,
475
489
  owner: owner.id,
476
490
  context: passedOnContext(question.context, owner.id, answered.note)
477
491
  });
@@ -1613,7 +1627,7 @@ const claudeExecutor = (options) => async (context) => {
1613
1627
  });
1614
1628
  if (driver === void 0) return notStarted("no Claude driver is ready; see `ork doctor`");
1615
1629
  const runtime = await options.runtimeFor(driver);
1616
- const ports = { human: context.owner === void 0 ? context.human : ownerFirst(context, context.owner, {
1630
+ const ports = { human: context.owner === void 0 ? withdrawnOnStop(context) : ownerFirst(context, context.owner, {
1617
1631
  runtimeFor: options.runtimeFor,
1618
1632
  driver: options.driver,
1619
1633
  readyDriver: options.readyDriver,
@@ -1,4 +1,4 @@
1
- import { Gt as FEEDBACK_TARGETS, Ut as FEEDBACK_KINDS, Wt as FEEDBACK_SEVERITIES, dt as parseReport } from "./src-DosUvy4B.mjs";
1
+ import { Gt as FEEDBACK_TARGETS, Ut as FEEDBACK_KINDS, Wt as FEEDBACK_SEVERITIES, dt as parseReport, un as maskSecrets } from "./src-BwFxTank.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomBytes, timingSafeEqual } from "node:crypto";
4
4
  import { createInterface } from "node:readline";
@@ -263,7 +263,7 @@ const legStep = (message, input) => {
263
263
  * and the session resumed (ADR-041); a resumed leg carries what the legs
264
264
  * before it spent, and its start is not news.
265
265
  */
266
- const STDERR_LINES = 20;
266
+ const REASON_LIMIT = 500;
267
267
  const parseLine = (line) => {
268
268
  try {
269
269
  return JSON.parse(line);
@@ -271,6 +271,16 @@ const parseLine = (line) => {
271
271
  return;
272
272
  }
273
273
  };
274
+ /** Noise a Node crash ends stderr with, or a stack frame: never the reason. */
275
+ const isNoise = (line) => /^Node\.js v\d/u.test(line) || /^\s+at /u.test(line);
276
+ /**
277
+ * Why a process ended without a result: the last block of its stderr as one
278
+ * masked, capped line (the reason reaches the terminal, which is not masked).
279
+ */
280
+ const failureReason = (stderr, code) => {
281
+ const block = stderr.split("\n").filter((line) => !isNoise(line)).join("\n").split(/\n\s*\n/u).map((text) => text.trim().replaceAll(/\s*\n\s*/gu, " ")).findLast((text) => text !== "");
282
+ return block === void 0 ? `claude exited with code ${String(code)}` : maskSecrets(block).slice(0, REASON_LIMIT);
283
+ };
274
284
  /** Runs one `claude` process, yielding its events; returns how it ended. */
275
285
  const runLeg = async function* (input) {
276
286
  const child = spawn(input.bin, input.args, {
@@ -283,25 +293,29 @@ const runLeg = async function* (input) {
283
293
  ]
284
294
  });
285
295
  const exited = new Promise((resolve) => {
286
- child.on("close", (code) => {
287
- resolve(code);
296
+ child.on("close", (code, signal) => {
297
+ resolve({
298
+ code,
299
+ signal
300
+ });
288
301
  });
289
302
  });
290
303
  const spawnError = new Promise((resolve) => {
291
304
  child.on("error", resolve);
292
305
  });
293
- const stderr = [];
306
+ let stderr = "";
294
307
  child.stderr.setEncoding("utf8");
295
308
  child.stderr.on("data", (chunk) => {
296
- stderr.push(...chunk.split("\n").filter((l) => l.trim() !== ""));
297
- stderr.splice(0, Math.max(0, stderr.length - STDERR_LINES));
309
+ stderr = (stderr + chunk).slice(-16384);
298
310
  });
299
311
  const write = (line) => {
300
312
  if (child.stdin.writable) child.stdin.write(line);
301
313
  };
314
+ let stopped = false;
302
315
  input.attach({
303
316
  write,
304
317
  stop: () => {
318
+ stopped = true;
305
319
  child.kill("SIGINT");
306
320
  }
307
321
  });
@@ -320,10 +334,15 @@ const runLeg = async function* (input) {
320
334
  outcome = ended;
321
335
  }
322
336
  }
323
- const code = await Promise.race([exited, spawnError.then((error) => error)]);
324
- return outcome ?? {
337
+ const end = await Promise.race([exited, spawnError.then((error) => error)]);
338
+ if (outcome !== void 0) return outcome;
339
+ if (end instanceof Error) return {
340
+ kind: "failed",
341
+ reason: `could not start ${input.bin}: ${end.message}`
342
+ };
343
+ return {
325
344
  kind: "failed",
326
- reason: code instanceof Error ? `could not start ${input.bin}: ${code.message}` : stderr.at(-1) ?? `claude exited with code ${String(code)}`
345
+ reason: stopped || end.signal !== null ? "interrupted" : failureReason(stderr, end.code)
327
346
  };
328
347
  } finally {
329
348
  input.attach();
@@ -1220,7 +1239,7 @@ const createSdkRuntime = (env = process.env, holdWindowMs) => ({
1220
1239
  }
1221
1240
  } catch (error) {
1222
1241
  input.close();
1223
- yield driverFailure(error instanceof Error ? error.message : String(error));
1242
+ yield driverFailure(ended.signal.aborted ? "interrupted" : error instanceof Error ? error.message : String(error));
1224
1243
  }
1225
1244
  };
1226
1245
  return {
@@ -1,11 +1,11 @@
1
- import { An as workflowDirOf, Bn as applyEdits, En as placeFor, Et as processAlive, Ft as nodeSays, G as requestPause, Gn as renderJsonSchema, H as unlinkNodes, Hn as readDocument, Jt as runGh, K as requestStop, Kn as parseWorkflow, Kt as DISCUSSIONS, Nn as LESSON_CAP_TOKENS, On as runDirOf, Qn as expandEdge, Rn as skillsIn, St as runStatus, Tn as placeFiles, Vn as newWorkflowText, W as requestContinue, Yn as EdgeInputSchema, Yt as sendPost, at as followEvents, bn as loadAgents, bt as liveStatus, d as runningRunIds, er as NodeSchema, et as detachResume, f as runningScript, ht as walkSummary, in as readCondition, it as detachRun, jn as inside, kt as nestItems, l as planUpgrade, mt as walkChecks, o as limitsReport, ot as explainWorkflowText, p as detectInstaller, pt as checkWorkflowText, q as tellLiveRun, qt as planPost, r as capsHere, tt as resumable, u as releaseNotes, v as triggersReport, xt as pausedOf, z as linkNodes, zn as WorkflowEditSchema } from "./src-DosUvy4B.mjs";
2
- import { C as placeOf$1, S as lessonPlaceOf, T as openFixRun, _ as nodeSession, a as registryShown, b as recordNote, c as checkDue, f as readUpdateCache, g as activeTree, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, v as previewPost, w as feedbackActions, x as acceptItem } from "./__build_info__-B83zdwIv.mjs";
3
- import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-BaEOo7sO.mjs";
4
- import { n as newRunId, t as findRun } from "./find-DDAkEoda.mjs";
5
- import { c as openStore, l as storePath, s as isNodeEvent } from "./output-D1wMNIly.mjs";
1
+ import { An as workflowDirOf, Bn as applyEdits, En as placeFor, Et as processAlive, Ft as nodeSays, G as requestPause, Gn as renderJsonSchema, H as unlinkNodes, Hn as readDocument, Jt as runGh, K as requestStop, Kn as parseWorkflow, Kt as DISCUSSIONS, Nn as LESSON_CAP_TOKENS, On as runDirOf, Qn as expandEdge, Rn as skillsIn, St as runStatus, Tn as placeFiles, Vn as newWorkflowText, W as requestContinue, Yn as EdgeInputSchema, Yt as sendPost, at as followEvents, bn as loadAgents, bt as liveStatus, d as runningRunIds, er as NodeSchema, et as detachResume, f as runningScript, ht as walkSummary, in as readCondition, it as detachRun, jn as inside, kt as nestItems, l as planUpgrade, mt as walkChecks, o as limitsReport, ot as explainWorkflowText, p as detectInstaller, pt as checkWorkflowText, q as tellLiveRun, qt as planPost, r as capsHere, tt as resumable, u as releaseNotes, v as triggersReport, xt as pausedOf, z as linkNodes, zn as WorkflowEditSchema } from "./src-BwFxTank.mjs";
2
+ import { C as placeOf$1, S as lessonPlaceOf, T as openFixRun, _ as nodeSession, a as registryShown, b as recordNote, c as checkDue, f as readUpdateCache, g as activeTree, h as writeUpdateCache, i as registryOf, l as fetchLatest, m as updateCachePath, o as updateSwitchOff, p as refreshUpdateCache, s as runInstall, u as newerVersion, v as previewPost, w as feedbackActions, x as acceptItem } from "./__build_info__-y1TPvZvp.mjs";
3
+ import { n as pendingDecisions, r as builtinProblem, t as answerDecision } from "./decide-BphP3ONM.mjs";
4
+ import { n as newRunId, t as findRun } from "./find-BXZjliwr.mjs";
5
+ import { c as openStore, l as storePath, s as isNodeEvent } from "./output-BVkI6ZVv.mjs";
6
6
  import { n as usageReport } from "./report-DK4LGqwF.mjs";
7
- import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-NtapkN2x.mjs";
8
- import { a as readWorktrees, c as planLine, i as projectHead, l as removeRefusal, n as lostWork, o as labelOf, r as planRemove, s as mergeStateOf, t as applyRemove, u as stateParts } from "./remove-0L02cre2.mjs";
7
+ import { a as planClean, i as keyOf, o as stepActs, r as cleanStep, s as stepPrunes, t as applyClean } from "./clean-BRUXyk87.mjs";
8
+ import { a as readWorktrees, c as mergeStateOf, d as stateParts, i as projectHead, l as planLine, n as lostWork, r as planRemove, s as labelOf, t as applyRemove, u as removeRefusal } from "./remove-CYGd9Csj.mjs";
9
9
  import path from "node:path";
10
10
  import { z } from "zod";
11
11
  import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";