@kynver-app/runtime 0.1.38 → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2002,6 +2002,19 @@ import { existsSync as existsSync10, openSync as openSync3, closeSync as closeSy
2002
2002
  import path11 from "node:path";
2003
2003
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2004
2004
 
2005
+ // src/completion-ack.ts
2006
+ function hasCompletionAck(worker) {
2007
+ return Boolean(worker.completionReportedAt?.trim());
2008
+ }
2009
+ function persistCompletionAck(worker, runId, fields) {
2010
+ worker.completionReportedAt = fields.completionReportedAt;
2011
+ worker.completionOutcome = fields.completionOutcome;
2012
+ if (fields.completionResponse !== void 0) {
2013
+ worker.completionResponse = fields.completionResponse;
2014
+ }
2015
+ saveWorker(runId, worker);
2016
+ }
2017
+
2005
2018
  // src/worker-ops.ts
2006
2019
  import path10 from "node:path";
2007
2020
 
@@ -2339,19 +2352,6 @@ function ensurePrReadyHandoff(input, exec = defaultPrHandoffExec) {
2339
2352
  };
2340
2353
  }
2341
2354
 
2342
- // src/completion-ack.ts
2343
- function hasCompletionAck(worker) {
2344
- return Boolean(worker.completionReportedAt?.trim());
2345
- }
2346
- function persistCompletionAck(worker, runId, fields) {
2347
- worker.completionReportedAt = fields.completionReportedAt;
2348
- worker.completionOutcome = fields.completionOutcome;
2349
- if (fields.completionResponse !== void 0) {
2350
- worker.completionResponse = fields.completionResponse;
2351
- }
2352
- saveWorker(runId, worker);
2353
- }
2354
-
2355
2355
  // src/worker-lifecycle.ts
2356
2356
  import path9 from "node:path";
2357
2357
  var TASK_LEFT_RUNNING = /* @__PURE__ */ new Set([
@@ -2848,7 +2848,7 @@ async function autoCompleteWorker(raw) {
2848
2848
  const maxTotalMs = args.maxTotalMs ?? DEFAULT_MAX_TOTAL_MS;
2849
2849
  const completeAttempts = args.completeAttempts ?? DEFAULT_COMPLETE_ATTEMPTS;
2850
2850
  const completeBackoffMs = args.completeBackoffMs ?? DEFAULT_COMPLETE_BACKOFF_MS;
2851
- const worker = loadWorker(args.run, args.name);
2851
+ let worker = loadWorker(args.run, args.name);
2852
2852
  if (!worker.agentOsId || !worker.taskId) {
2853
2853
  return {
2854
2854
  worker: worker.name,
@@ -2858,8 +2858,29 @@ async function autoCompleteWorker(raw) {
2858
2858
  reason: "worker has no agentOsId/taskId \u2014 nothing to attribute completion to"
2859
2859
  };
2860
2860
  }
2861
+ if (hasCompletionAck(worker)) {
2862
+ return {
2863
+ worker: worker.name,
2864
+ runId: worker.runId,
2865
+ outcome: "completed",
2866
+ httpStatus: 200,
2867
+ attempts: 0,
2868
+ reason: "completion-already-acknowledged"
2869
+ };
2870
+ }
2861
2871
  const startMs = Date.now();
2862
2872
  while (true) {
2873
+ worker = loadWorker(args.run, args.name);
2874
+ if (hasCompletionAck(worker)) {
2875
+ return {
2876
+ worker: worker.name,
2877
+ runId: worker.runId,
2878
+ outcome: "completed",
2879
+ httpStatus: 200,
2880
+ attempts: 0,
2881
+ reason: "completion-already-acknowledged"
2882
+ };
2883
+ }
2863
2884
  const status = computeWorkerStatus(worker);
2864
2885
  if (isFinishedWorkerStatus(status)) break;
2865
2886
  if (!isPidAlive(worker.pid)) break;
@@ -2923,11 +2944,12 @@ async function autoCompleteWorkerCli(raw) {
2923
2944
  const outcome = await autoCompleteWorker(raw);
2924
2945
  console.log(JSON.stringify(outcome, null, 2));
2925
2946
  if (outcome.outcome === "missing_link" || outcome.outcome === "timed_out") {
2926
- process.exitCode = 1;
2947
+ process.exit(1);
2927
2948
  }
2949
+ process.exit(0);
2928
2950
  } catch (error) {
2929
2951
  console.error(`worker auto-complete failed: ${error.message}`);
2930
- process.exitCode = 1;
2952
+ process.exit(1);
2931
2953
  }
2932
2954
  }
2933
2955
  function resolveDefaultCliPath() {
@@ -4368,6 +4390,24 @@ function reconcileStaleWorkers() {
4368
4390
  }
4369
4391
  return { workers: outcomes, finalizedRuns: finalizeStaleRuns() };
4370
4392
  }
4393
+ function reconcileRunsCli() {
4394
+ const result = reconcileStaleWorkers();
4395
+ const markedExited = result.workers.filter((w) => w.action === "marked_exited").length;
4396
+ const killedStale = result.workers.filter((w) => w.action === "killed_stale").length;
4397
+ const skipped = result.workers.filter((w) => w.action === "skipped").length;
4398
+ console.log(
4399
+ JSON.stringify(
4400
+ {
4401
+ ok: true,
4402
+ workers: { markedExited, killedStale, skipped, total: result.workers.length },
4403
+ finalizedRuns: result.finalizedRuns.length,
4404
+ details: { workers: result.workers, finalizedRuns: result.finalizedRuns }
4405
+ },
4406
+ null,
4407
+ 2
4408
+ )
4409
+ );
4410
+ }
4371
4411
 
4372
4412
  // src/plan-progress-daemon-sync.ts
4373
4413
  import path22 from "node:path";
@@ -5736,7 +5776,7 @@ function usage(code = 0) {
5736
5776
  " kynver run create --repo /path/repo [--name name] [--base origin/main]",
5737
5777
  " kynver run list",
5738
5778
  " kynver run status --run RUN_ID",
5739
- " kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-7] [--disk-path /]",
5779
+ " kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /]",
5740
5780
  " kynver run sweep --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--grace-ms MS]",
5741
5781
  ' kynver worker start --run RUN_ID --name worker --task "..." [--owned path[,path]] [--model MODEL] [--provider claude|cursor] [--agent-os-id AOS_ID] [--task-id TASK_ID] [--wait]',
5742
5782
  " kynver worker status --run RUN_ID --name worker",
@@ -5744,6 +5784,7 @@ function usage(code = 0) {
5744
5784
  " kynver worker stop --run RUN_ID --name worker",
5745
5785
  " kynver worker complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--task-id TASK_ID] [--base-url URL] [--secret SECRET]",
5746
5786
  " kynver worker auto-complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--poll-ms 5000] [--max-total-ms 21600000] [--complete-attempts 3] [--complete-backoff-ms 5000] [--base-url URL] [--secret SECRET]",
5787
+ " kynver run reconcile",
5747
5788
  " kynver plan progress --plan PLAN_ID --row ROW_KEY --role ROLE --status STATUS [--task TASK_ID] [--note NOTE] [--evidence type:value] [--agent-os-id AOS_ID]",
5748
5789
  " kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override]",
5749
5790
  " kynver plan persist --operation create|add_version|update_metadata --title TITLE (--body-file PATH | --body TEXT) [--slug SLUG] [--plan PLAN_ID] [--summary TEXT] [--failure-kind approval_guard|auth|network|server|tool_interruption]",
@@ -5797,6 +5838,7 @@ async function main(argv = process.argv.slice(2)) {
5797
5838
  if (scope === "run" && action === "status") return runStatus(args);
5798
5839
  if (scope === "run" && action === "dispatch") return void await dispatchRun(args);
5799
5840
  if (scope === "run" && action === "sweep") return void await sweepRun(args);
5841
+ if (scope === "run" && action === "reconcile") return reconcileRunsCli();
5800
5842
  if (scope === "worker" && action === "start") return void await startWorker(args);
5801
5843
  if (scope === "worker" && action === "status") return workerStatus(args);
5802
5844
  if (scope === "worker" && action === "tail") return tailWorker(args);
@@ -5868,6 +5910,8 @@ export {
5868
5910
  persistPlan,
5869
5911
  postJson,
5870
5912
  preflightCursorModel,
5913
+ reconcileRunsCli,
5914
+ reconcileStaleWorkers,
5871
5915
  redactHarness,
5872
5916
  resolveBaseUrl,
5873
5917
  resolveCallbackSecret,