@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/cli.js CHANGED
@@ -1962,6 +1962,19 @@ import { existsSync as existsSync9, openSync as openSync3, closeSync as closeSyn
1962
1962
  import path11 from "node:path";
1963
1963
  import { fileURLToPath } from "node:url";
1964
1964
 
1965
+ // src/completion-ack.ts
1966
+ function hasCompletionAck(worker) {
1967
+ return Boolean(worker.completionReportedAt?.trim());
1968
+ }
1969
+ function persistCompletionAck(worker, runId, fields) {
1970
+ worker.completionReportedAt = fields.completionReportedAt;
1971
+ worker.completionOutcome = fields.completionOutcome;
1972
+ if (fields.completionResponse !== void 0) {
1973
+ worker.completionResponse = fields.completionResponse;
1974
+ }
1975
+ saveWorker(runId, worker);
1976
+ }
1977
+
1965
1978
  // src/worker-ops.ts
1966
1979
  import path10 from "node:path";
1967
1980
 
@@ -2299,19 +2312,6 @@ function ensurePrReadyHandoff(input, exec = defaultPrHandoffExec) {
2299
2312
  };
2300
2313
  }
2301
2314
 
2302
- // src/completion-ack.ts
2303
- function hasCompletionAck(worker) {
2304
- return Boolean(worker.completionReportedAt?.trim());
2305
- }
2306
- function persistCompletionAck(worker, runId, fields) {
2307
- worker.completionReportedAt = fields.completionReportedAt;
2308
- worker.completionOutcome = fields.completionOutcome;
2309
- if (fields.completionResponse !== void 0) {
2310
- worker.completionResponse = fields.completionResponse;
2311
- }
2312
- saveWorker(runId, worker);
2313
- }
2314
-
2315
2315
  // src/worker-lifecycle.ts
2316
2316
  import path9 from "node:path";
2317
2317
  var TASK_LEFT_RUNNING = /* @__PURE__ */ new Set([
@@ -2808,7 +2808,7 @@ async function autoCompleteWorker(raw) {
2808
2808
  const maxTotalMs = args.maxTotalMs ?? DEFAULT_MAX_TOTAL_MS;
2809
2809
  const completeAttempts = args.completeAttempts ?? DEFAULT_COMPLETE_ATTEMPTS;
2810
2810
  const completeBackoffMs = args.completeBackoffMs ?? DEFAULT_COMPLETE_BACKOFF_MS;
2811
- const worker = loadWorker(args.run, args.name);
2811
+ let worker = loadWorker(args.run, args.name);
2812
2812
  if (!worker.agentOsId || !worker.taskId) {
2813
2813
  return {
2814
2814
  worker: worker.name,
@@ -2818,8 +2818,29 @@ async function autoCompleteWorker(raw) {
2818
2818
  reason: "worker has no agentOsId/taskId \u2014 nothing to attribute completion to"
2819
2819
  };
2820
2820
  }
2821
+ if (hasCompletionAck(worker)) {
2822
+ return {
2823
+ worker: worker.name,
2824
+ runId: worker.runId,
2825
+ outcome: "completed",
2826
+ httpStatus: 200,
2827
+ attempts: 0,
2828
+ reason: "completion-already-acknowledged"
2829
+ };
2830
+ }
2821
2831
  const startMs = Date.now();
2822
2832
  while (true) {
2833
+ worker = loadWorker(args.run, args.name);
2834
+ if (hasCompletionAck(worker)) {
2835
+ return {
2836
+ worker: worker.name,
2837
+ runId: worker.runId,
2838
+ outcome: "completed",
2839
+ httpStatus: 200,
2840
+ attempts: 0,
2841
+ reason: "completion-already-acknowledged"
2842
+ };
2843
+ }
2823
2844
  const status = computeWorkerStatus(worker);
2824
2845
  if (isFinishedWorkerStatus(status)) break;
2825
2846
  if (!isPidAlive(worker.pid)) break;
@@ -2883,11 +2904,12 @@ async function autoCompleteWorkerCli(raw) {
2883
2904
  const outcome = await autoCompleteWorker(raw);
2884
2905
  console.log(JSON.stringify(outcome, null, 2));
2885
2906
  if (outcome.outcome === "missing_link" || outcome.outcome === "timed_out") {
2886
- process.exitCode = 1;
2907
+ process.exit(1);
2887
2908
  }
2909
+ process.exit(0);
2888
2910
  } catch (error) {
2889
2911
  console.error(`worker auto-complete failed: ${error.message}`);
2890
- process.exitCode = 1;
2912
+ process.exit(1);
2891
2913
  }
2892
2914
  }
2893
2915
  function resolveDefaultCliPath() {
@@ -4297,6 +4319,24 @@ function reconcileStaleWorkers() {
4297
4319
  }
4298
4320
  return { workers: outcomes, finalizedRuns: finalizeStaleRuns() };
4299
4321
  }
4322
+ function reconcileRunsCli() {
4323
+ const result = reconcileStaleWorkers();
4324
+ const markedExited = result.workers.filter((w) => w.action === "marked_exited").length;
4325
+ const killedStale = result.workers.filter((w) => w.action === "killed_stale").length;
4326
+ const skipped = result.workers.filter((w) => w.action === "skipped").length;
4327
+ console.log(
4328
+ JSON.stringify(
4329
+ {
4330
+ ok: true,
4331
+ workers: { markedExited, killedStale, skipped, total: result.workers.length },
4332
+ finalizedRuns: result.finalizedRuns.length,
4333
+ details: { workers: result.workers, finalizedRuns: result.finalizedRuns }
4334
+ },
4335
+ null,
4336
+ 2
4337
+ )
4338
+ );
4339
+ }
4300
4340
 
4301
4341
  // src/plan-progress-daemon-sync.ts
4302
4342
  import path22 from "node:path";
@@ -5701,7 +5741,7 @@ function usage(code = 0) {
5701
5741
  " kynver run create --repo /path/repo [--name name] [--base origin/main]",
5702
5742
  " kynver run list",
5703
5743
  " kynver run status --run RUN_ID",
5704
- " 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 /]",
5744
+ " 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 /]",
5705
5745
  " kynver run sweep --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--grace-ms MS]",
5706
5746
  ' 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]',
5707
5747
  " kynver worker status --run RUN_ID --name worker",
@@ -5709,6 +5749,7 @@ function usage(code = 0) {
5709
5749
  " kynver worker stop --run RUN_ID --name worker",
5710
5750
  " kynver worker complete --run RUN_ID --name worker [--agent-os-id AOS_ID] [--task-id TASK_ID] [--base-url URL] [--secret SECRET]",
5711
5751
  " 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]",
5752
+ " kynver run reconcile",
5712
5753
  " 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]",
5713
5754
  " kynver plan verify --plan PLAN_ID [--worktree PATH] [--task TASK_ID] [--human-override]",
5714
5755
  " 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]",
@@ -5762,6 +5803,7 @@ async function main(argv = process.argv.slice(2)) {
5762
5803
  if (scope === "run" && action === "status") return runStatus(args);
5763
5804
  if (scope === "run" && action === "dispatch") return void await dispatchRun(args);
5764
5805
  if (scope === "run" && action === "sweep") return void await sweepRun(args);
5806
+ if (scope === "run" && action === "reconcile") return reconcileRunsCli();
5765
5807
  if (scope === "worker" && action === "start") return void await startWorker(args);
5766
5808
  if (scope === "worker" && action === "status") return workerStatus(args);
5767
5809
  if (scope === "worker" && action === "tail") return tailWorker(args);