@kody-ade/kody-engine 0.4.159 → 0.4.161

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/bin/kody.js CHANGED
@@ -1061,7 +1061,7 @@ var init_loadPriorArt = __esm({
1061
1061
  // package.json
1062
1062
  var package_default = {
1063
1063
  name: "@kody-ade/kody-engine",
1064
- version: "0.4.159",
1064
+ version: "0.4.161",
1065
1065
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
1066
1066
  license: "MIT",
1067
1067
  type: "module",
@@ -1117,7 +1117,7 @@ var package_default = {
1117
1117
  };
1118
1118
 
1119
1119
  // src/chat-cli.ts
1120
- import { execFileSync as execFileSync31 } from "child_process";
1120
+ import { execFileSync as execFileSync29 } from "child_process";
1121
1121
  import * as fs43 from "fs";
1122
1122
  import * as path39 from "path";
1123
1123
 
@@ -2819,7 +2819,7 @@ async function emit2(sink, type, sessionId, suffix, payload) {
2819
2819
  }
2820
2820
 
2821
2821
  // src/kody-cli.ts
2822
- import { execFileSync as execFileSync30 } from "child_process";
2822
+ import { execFileSync as execFileSync28 } from "child_process";
2823
2823
  import * as fs42 from "fs";
2824
2824
  import * as path38 from "path";
2825
2825
 
@@ -3227,7 +3227,7 @@ function coerceBare(spec, value) {
3227
3227
  }
3228
3228
 
3229
3229
  // src/executor.ts
3230
- import { execFileSync as execFileSync29, spawn as spawn9 } from "child_process";
3230
+ import { execFileSync as execFileSync27, spawn as spawn9 } from "child_process";
3231
3231
  import * as fs41 from "fs";
3232
3232
  import * as path37 from "path";
3233
3233
 
@@ -4699,7 +4699,7 @@ var advanceFlow = async (ctx, profile) => {
4699
4699
  `
4700
4700
  );
4701
4701
  }
4702
- ghComment(flow.issueNumber, `@kody ${flow.name}`, ctx.cwd, "re-trigger orchestrator");
4702
+ ctx.output.nextDispatch = { executable: flow.name, cliArgs: { issue: flow.issueNumber } };
4703
4703
  };
4704
4704
 
4705
4705
  // src/scripts/brainServe.ts
@@ -6865,8 +6865,6 @@ var discoverQaContext = async (ctx) => {
6865
6865
  };
6866
6866
 
6867
6867
  // src/scripts/dispatch.ts
6868
- import { execFileSync as execFileSync11 } from "child_process";
6869
- var API_TIMEOUT_MS4 = 3e4;
6870
6868
  var dispatch = async (ctx, _profile, _agentResult, args) => {
6871
6869
  const next = args?.next;
6872
6870
  if (!next) {
@@ -6898,20 +6896,10 @@ var dispatch = async (ctx, _profile, _agentResult, args) => {
6898
6896
  }
6899
6897
  const usePr = target === "pr" && state?.core.prUrl;
6900
6898
  const targetNumber = usePr ? parsePr(state.core.prUrl) ?? issueNumber : issueNumber;
6901
- const sub = usePr ? "pr" : "issue";
6902
- const body = `@kody ${next}`;
6903
- try {
6904
- execFileSync11("gh", [sub, "comment", String(targetNumber), "--body", body], {
6905
- timeout: API_TIMEOUT_MS4,
6906
- cwd: ctx.cwd,
6907
- stdio: ["ignore", "pipe", "pipe"]
6908
- });
6909
- } catch (err) {
6910
- process.stderr.write(
6911
- `[kody dispatch] failed to post @kody ${next} on ${sub} #${targetNumber}: ${err instanceof Error ? err.message : String(err)}
6912
- `
6913
- );
6914
- }
6899
+ ctx.output.nextDispatch = {
6900
+ executable: next,
6901
+ cliArgs: usePr ? { pr: targetNumber } : { issue: targetNumber }
6902
+ };
6915
6903
  };
6916
6904
  function parsePr(url) {
6917
6905
  const m = url.match(/\/pull\/(\d+)(?:[/?#]|$)/);
@@ -6921,8 +6909,8 @@ function parsePr(url) {
6921
6909
  }
6922
6910
 
6923
6911
  // src/scripts/dispatchClassified.ts
6924
- import { execFileSync as execFileSync12 } from "child_process";
6925
- var API_TIMEOUT_MS5 = 3e4;
6912
+ import { execFileSync as execFileSync11 } from "child_process";
6913
+ var API_TIMEOUT_MS4 = 3e4;
6926
6914
  var VALID_CLASSES2 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
6927
6915
  var dispatchClassified = async (ctx) => {
6928
6916
  const issueNumber = ctx.args.issue;
@@ -6931,38 +6919,34 @@ var dispatchClassified = async (ctx) => {
6931
6919
  if (!classification || !VALID_CLASSES2.has(classification)) return;
6932
6920
  const action = ctx.data.action;
6933
6921
  if (!action) return;
6934
- const baseArg = typeof ctx.args.base === "string" && ctx.args.base.length > 0 ? ` --base ${ctx.args.base}` : "";
6935
- const dispatchLine = `@kody ${classification}${baseArg}`;
6922
+ const base = typeof ctx.args.base === "string" && ctx.args.base.length > 0 ? ctx.args.base : void 0;
6936
6923
  const auditLine = ctx.data.classificationAudit ?? `\u{1F50E} kody classified as \`${classification}\``;
6937
6924
  const state = ctx.data.taskState ?? emptyState();
6938
6925
  const nextState = reduce(state, "classify", action, void 0);
6939
6926
  const stateBody = renderStateComment(nextState);
6940
6927
  ctx.data.taskState = nextState;
6941
6928
  ctx.data.taskStateRendered = stateBody;
6942
- const body = `${dispatchLine}
6943
-
6944
- ${auditLine}
6929
+ const body = `${auditLine}
6945
6930
 
6946
6931
  ${stateBody}`;
6947
6932
  try {
6948
- execFileSync12("gh", ["issue", "comment", String(issueNumber), "--body", body], {
6933
+ execFileSync11("gh", ["issue", "comment", String(issueNumber), "--body", body], {
6949
6934
  cwd: ctx.cwd,
6950
- timeout: API_TIMEOUT_MS5,
6935
+ timeout: API_TIMEOUT_MS4,
6951
6936
  stdio: ["ignore", "pipe", "pipe"]
6952
6937
  });
6953
6938
  } catch (err) {
6954
6939
  process.stderr.write(
6955
- `[kody dispatchClassified] failed to dispatch ${dispatchLine}: ${err instanceof Error ? err.message : String(err)}
6940
+ `[kody dispatchClassified] failed to post state comment for #${issueNumber}: ${err instanceof Error ? err.message : String(err)}
6956
6941
  `
6957
6942
  );
6958
- ctx.data.action = failedAction3("dispatch post failed");
6959
- ctx.output.exitCode = 1;
6960
- ctx.output.reason = "classify: dispatch failed";
6961
6943
  }
6944
+ const cliArgs = { issue: issueNumber };
6945
+ if (base && getProfileInputs(classification)?.some((i) => i.name === "base")) {
6946
+ cliArgs.base = base;
6947
+ }
6948
+ ctx.output.nextDispatch = { executable: classification, cliArgs };
6962
6949
  };
6963
- function failedAction3(reason) {
6964
- return { type: "CLASSIFY_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
6965
- }
6966
6950
 
6967
6951
  // src/scripts/dispatchJobFileTicks.ts
6968
6952
  import * as fs29 from "fs";
@@ -7620,20 +7604,18 @@ var dispatchNextTask = async (ctx) => {
7620
7604
  return;
7621
7605
  }
7622
7606
  const base = goal.leafPr?.headRefName ?? goal.defaultBranch;
7623
- process.stdout.write(`[goal-tick] dispatching @kody on #${next.number} (--base ${base})
7624
- `);
7625
- const comment = commentOnIssue(next.number, `@kody --base ${base}`, ctx.cwd);
7626
- if (!comment.ok) {
7627
- process.stderr.write(`[goal-tick] dispatchNextTask: comment failed on #${next.number}: ${comment.error}
7607
+ process.stdout.write(`[goal-tick] dispatching #${next.number} in-process via classify (--base ${base})
7628
7608
  `);
7629
- return;
7630
- }
7609
+ ctx.output.nextDispatch = {
7610
+ executable: "classify",
7611
+ cliArgs: { issue: next.number, base }
7612
+ };
7631
7613
  goal.lastDispatchedIssue = next.number;
7632
7614
  };
7633
7615
 
7634
7616
  // src/pr.ts
7635
7617
  init_issue();
7636
- import { execFileSync as execFileSync13 } from "child_process";
7618
+ import { execFileSync as execFileSync12 } from "child_process";
7637
7619
  function prMergeStatus(prNumber, cwd) {
7638
7620
  try {
7639
7621
  const out = gh(
@@ -7759,7 +7741,7 @@ function isAlreadyExistsError(err) {
7759
7741
  return ALREADY_EXISTS_RE.test(msg);
7760
7742
  }
7761
7743
  function git2(args, cwd) {
7762
- return execFileSync13("git", args, {
7744
+ return execFileSync12("git", args, {
7763
7745
  encoding: "utf-8",
7764
7746
  timeout: 3e4,
7765
7747
  cwd,
@@ -8090,14 +8072,14 @@ var finalizeTerminal = async (ctx) => {
8090
8072
 
8091
8073
  // src/scripts/finishFlow.ts
8092
8074
  init_issue();
8093
- import { execFileSync as execFileSync14 } from "child_process";
8075
+ import { execFileSync as execFileSync13 } from "child_process";
8094
8076
  var TERMINAL_PHASE = {
8095
8077
  "review-passed": { phase: "shipped", status: "succeeded" },
8096
8078
  "fix-applied": { phase: "shipped", status: "succeeded" },
8097
8079
  "review-failed": { phase: "failed", status: "failed" },
8098
8080
  aborted: { phase: "failed", status: "failed" }
8099
8081
  };
8100
- var API_TIMEOUT_MS6 = 3e4;
8082
+ var API_TIMEOUT_MS5 = 3e4;
8101
8083
  var STATUS_ICON = {
8102
8084
  "review-passed": "\u2705",
8103
8085
  "fix-applied": "\u2705",
@@ -8130,8 +8112,8 @@ var finishFlow = async (ctx, profile, _agentResult, args) => {
8130
8112
  **PR:** ${state.core.prUrl}` : "";
8131
8113
  const body = `${icon} kody flow \`${flowName}\` finished \u2014 \`${reason}\`${prSuffix}`;
8132
8114
  try {
8133
- execFileSync14("gh", ["issue", "comment", String(issueNumber), "--body", body], {
8134
- timeout: API_TIMEOUT_MS6,
8115
+ execFileSync13("gh", ["issue", "comment", String(issueNumber), "--body", body], {
8116
+ timeout: API_TIMEOUT_MS5,
8135
8117
  cwd: ctx.cwd,
8136
8118
  stdio: ["ignore", "pipe", "pipe"]
8137
8119
  });
@@ -8160,9 +8142,9 @@ var finishFlow = async (ctx, profile, _agentResult, args) => {
8160
8142
  };
8161
8143
 
8162
8144
  // src/branch.ts
8163
- import { execFileSync as execFileSync15 } from "child_process";
8145
+ import { execFileSync as execFileSync14 } from "child_process";
8164
8146
  function git3(args, cwd) {
8165
- return execFileSync15("git", args, {
8147
+ return execFileSync14("git", args, {
8166
8148
  encoding: "utf-8",
8167
8149
  timeout: 3e4,
8168
8150
  cwd,
@@ -8179,11 +8161,11 @@ function getCurrentBranch(cwd) {
8179
8161
  }
8180
8162
  function resetWorkingTree(cwd) {
8181
8163
  try {
8182
- execFileSync15("git", ["reset", "--hard", "HEAD"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8164
+ execFileSync14("git", ["reset", "--hard", "HEAD"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8183
8165
  } catch {
8184
8166
  }
8185
8167
  try {
8186
- execFileSync15("git", ["clean", "-fd"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8168
+ execFileSync14("git", ["clean", "-fd"], { cwd, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8187
8169
  } catch {
8188
8170
  }
8189
8171
  }
@@ -8195,14 +8177,14 @@ function checkoutPrBranch(prNumber, cwd) {
8195
8177
  GH_TOKEN: process.env.GH_PAT?.trim() || process.env.GH_TOKEN || ""
8196
8178
  };
8197
8179
  try {
8198
- execFileSync15("git", ["reset", "--hard", "HEAD"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8180
+ execFileSync14("git", ["reset", "--hard", "HEAD"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8199
8181
  } catch {
8200
8182
  }
8201
8183
  try {
8202
- execFileSync15("git", ["clean", "-fd"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8184
+ execFileSync14("git", ["clean", "-fd"], { cwd, env, stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
8203
8185
  } catch {
8204
8186
  }
8205
- execFileSync15("gh", ["pr", "checkout", String(prNumber)], {
8187
+ execFileSync14("gh", ["pr", "checkout", String(prNumber)], {
8206
8188
  cwd,
8207
8189
  env,
8208
8190
  stdio: ["ignore", "pipe", "pipe"],
@@ -8328,7 +8310,7 @@ function ensureFeatureBranch(issueNumber, title, defaultBranch2, cwd, baseBranch
8328
8310
  }
8329
8311
 
8330
8312
  // src/gha.ts
8331
- import { execFileSync as execFileSync16 } from "child_process";
8313
+ import { execFileSync as execFileSync15 } from "child_process";
8332
8314
  import * as fs30 from "fs";
8333
8315
  function getRunUrl() {
8334
8316
  const server = process.env.GITHUB_SERVER_URL;
@@ -8371,7 +8353,7 @@ function reactToTriggerComment(cwd) {
8371
8353
  for (let attempt = 0; attempt < 3; attempt++) {
8372
8354
  if (attempt > 0) sleepMs(attempt === 1 ? 500 : 1500);
8373
8355
  try {
8374
- execFileSync16("gh", args, opts);
8356
+ execFileSync15("gh", args, opts);
8375
8357
  return;
8376
8358
  } catch (err) {
8377
8359
  lastErr = err;
@@ -8384,7 +8366,7 @@ function reactToTriggerComment(cwd) {
8384
8366
  }
8385
8367
  function sleepMs(ms) {
8386
8368
  try {
8387
- execFileSync16("sleep", [(ms / 1e3).toString()], { stdio: "ignore", timeout: ms + 1e3 });
8369
+ execFileSync15("sleep", [(ms / 1e3).toString()], { stdio: "ignore", timeout: ms + 1e3 });
8388
8370
  } catch {
8389
8371
  }
8390
8372
  }
@@ -8393,7 +8375,7 @@ function sleepMs(ms) {
8393
8375
  init_issue();
8394
8376
 
8395
8377
  // src/workflow.ts
8396
- import { execFileSync as execFileSync17 } from "child_process";
8378
+ import { execFileSync as execFileSync16 } from "child_process";
8397
8379
  var GH_TIMEOUT_MS = 3e4;
8398
8380
  function ghToken3() {
8399
8381
  return process.env.GH_PAT?.trim() || process.env.GH_TOKEN;
@@ -8401,7 +8383,7 @@ function ghToken3() {
8401
8383
  function gh3(args, cwd) {
8402
8384
  const token = ghToken3();
8403
8385
  const env = token ? { ...process.env, GH_TOKEN: token } : { ...process.env };
8404
- return execFileSync17("gh", args, {
8386
+ return execFileSync16("gh", args, {
8405
8387
  encoding: "utf-8",
8406
8388
  timeout: GH_TIMEOUT_MS,
8407
8389
  cwd,
@@ -8636,7 +8618,7 @@ var handleAbandonedGoal = async (ctx) => {
8636
8618
  };
8637
8619
 
8638
8620
  // src/scripts/initFlow.ts
8639
- import { execFileSync as execFileSync18 } from "child_process";
8621
+ import { execFileSync as execFileSync17 } from "child_process";
8640
8622
  import * as fs31 from "fs";
8641
8623
  import * as path29 from "path";
8642
8624
  function detectPackageManager(cwd) {
@@ -8662,7 +8644,7 @@ function schemaUrlFromPkg() {
8662
8644
  function detectOwnerRepo(cwd) {
8663
8645
  let url;
8664
8646
  try {
8665
- url = execFileSync18("git", ["remote", "get-url", "origin"], {
8647
+ url = execFileSync17("git", ["remote", "get-url", "origin"], {
8666
8648
  cwd,
8667
8649
  encoding: "utf-8",
8668
8650
  stdio: ["ignore", "pipe", "pipe"]
@@ -8747,7 +8729,7 @@ jobs:
8747
8729
  `;
8748
8730
  function defaultBranchFromGit(cwd) {
8749
8731
  try {
8750
- const ref = execFileSync18("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
8732
+ const ref = execFileSync17("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
8751
8733
  cwd,
8752
8734
  encoding: "utf-8",
8753
8735
  stdio: ["ignore", "pipe", "pipe"]
@@ -8755,7 +8737,7 @@ function defaultBranchFromGit(cwd) {
8755
8737
  return ref.replace("refs/remotes/origin/", "");
8756
8738
  } catch {
8757
8739
  try {
8758
- return execFileSync18("git", ["branch", "--show-current"], {
8740
+ return execFileSync17("git", ["branch", "--show-current"], {
8759
8741
  cwd,
8760
8742
  encoding: "utf-8",
8761
8743
  stdio: ["ignore", "pipe", "pipe"]
@@ -9445,8 +9427,8 @@ var mergeFlow = async (ctx) => {
9445
9427
  };
9446
9428
 
9447
9429
  // src/scripts/mergeReleasePr.ts
9448
- import { execFileSync as execFileSync19 } from "child_process";
9449
- var API_TIMEOUT_MS7 = 6e4;
9430
+ import { execFileSync as execFileSync18 } from "child_process";
9431
+ var API_TIMEOUT_MS6 = 6e4;
9450
9432
  var mergeReleasePr = async (ctx) => {
9451
9433
  const state = ctx.data.taskState;
9452
9434
  const prUrl = state?.core.prUrl;
@@ -9464,8 +9446,8 @@ var mergeReleasePr = async (ctx) => {
9464
9446
  process.stderr.write(`[kody mergeReleasePr] merging PR #${prNumber} (${prUrl})
9465
9447
  `);
9466
9448
  try {
9467
- const out = execFileSync19("gh", ["pr", "merge", String(prNumber), "--merge"], {
9468
- timeout: API_TIMEOUT_MS7,
9449
+ const out = execFileSync18("gh", ["pr", "merge", String(prNumber), "--merge"], {
9450
+ timeout: API_TIMEOUT_MS6,
9469
9451
  cwd: ctx.cwd,
9470
9452
  stdio: ["ignore", "pipe", "pipe"]
9471
9453
  });
@@ -9572,7 +9554,7 @@ function qaAction2(verdict, payload) {
9572
9554
  const type = verdict === "PASS" ? "QA_PASS" : verdict === "CONCERNS" ? "QA_CONCERNS" : verdict === "FAIL" ? "QA_FAIL" : "QA_COMPLETED";
9573
9555
  return { type, payload: { verdict, ...payload }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
9574
9556
  }
9575
- function failedAction4(reason) {
9557
+ function failedAction3(reason) {
9576
9558
  return { type: "QA_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
9577
9559
  }
9578
9560
  function slugifyScope(scope) {
@@ -9608,7 +9590,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9608
9590
  `);
9609
9591
  ctx.output.exitCode = 1;
9610
9592
  ctx.output.reason = reason;
9611
- ctx.data.action = failedAction4(reason);
9593
+ ctx.data.action = failedAction3(reason);
9612
9594
  return;
9613
9595
  }
9614
9596
  const reportBody = agentResult.finalText.trim();
@@ -9616,7 +9598,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9616
9598
  process.stderr.write("qa-engineer: agent produced no report body\n");
9617
9599
  ctx.output.exitCode = 1;
9618
9600
  ctx.output.reason = "empty report body";
9619
- ctx.data.action = failedAction4("empty report body");
9601
+ ctx.data.action = failedAction3("empty report body");
9620
9602
  return;
9621
9603
  }
9622
9604
  const verdict = detectVerdict(reportBody);
@@ -9630,7 +9612,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9630
9612
  const msg = err instanceof Error ? err.message : String(err);
9631
9613
  ctx.output.exitCode = 4;
9632
9614
  ctx.output.reason = `failed to comment on issue #${existingIssue}: ${msg}`;
9633
- ctx.data.action = failedAction4(ctx.output.reason);
9615
+ ctx.data.action = failedAction3(ctx.output.reason);
9634
9616
  return;
9635
9617
  }
9636
9618
  process.stdout.write(
@@ -9652,7 +9634,7 @@ QA_REPORT_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.gith
9652
9634
  const msg = err instanceof Error ? err.message : String(err);
9653
9635
  ctx.output.exitCode = 4;
9654
9636
  ctx.output.reason = `failed to open QA issue: ${truncate2(msg, 1e3)}`;
9655
- ctx.data.action = failedAction4(ctx.output.reason);
9637
+ ctx.data.action = failedAction3(ctx.output.reason);
9656
9638
  return;
9657
9639
  }
9658
9640
  process.stdout.write(`
@@ -10946,8 +10928,8 @@ ${body}`;
10946
10928
  }
10947
10929
 
10948
10930
  // src/scripts/recordClassification.ts
10949
- import { execFileSync as execFileSync20 } from "child_process";
10950
- var API_TIMEOUT_MS8 = 3e4;
10931
+ import { execFileSync as execFileSync19 } from "child_process";
10932
+ var API_TIMEOUT_MS7 = 3e4;
10951
10933
  var VALID_CLASSES3 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
10952
10934
  var recordClassification = async (ctx) => {
10953
10935
  const issueNumber = ctx.args.issue;
@@ -10964,7 +10946,7 @@ var recordClassification = async (ctx) => {
10964
10946
  reason = parsed?.reason ?? null;
10965
10947
  }
10966
10948
  if (!classification) {
10967
- ctx.data.action = failedAction5("classification missing or invalid");
10949
+ ctx.data.action = failedAction4("classification missing or invalid");
10968
10950
  tryAuditComment(
10969
10951
  issueNumber,
10970
10952
  "\u26A0\uFE0F kody classifier could not decide \u2014 please re-run with an explicit `@kody <type>`.",
@@ -10994,9 +10976,9 @@ function parseClassification(prSummary) {
10994
10976
  }
10995
10977
  function tryAuditComment(issueNumber, body, cwd) {
10996
10978
  try {
10997
- execFileSync20("gh", ["issue", "comment", String(issueNumber), "--body", body], {
10979
+ execFileSync19("gh", ["issue", "comment", String(issueNumber), "--body", body], {
10998
10980
  cwd,
10999
- timeout: API_TIMEOUT_MS8,
10981
+ timeout: API_TIMEOUT_MS7,
11000
10982
  stdio: ["ignore", "pipe", "pipe"]
11001
10983
  });
11002
10984
  } catch {
@@ -11005,7 +10987,7 @@ function tryAuditComment(issueNumber, body, cwd) {
11005
10987
  function makeAction3(type, payload) {
11006
10988
  return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
11007
10989
  }
11008
- function failedAction5(reason) {
10990
+ function failedAction4(reason) {
11009
10991
  return { type: "CLASSIFY_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
11010
10992
  }
11011
10993
 
@@ -11108,7 +11090,7 @@ var resolveArtifacts = async (ctx, profile) => {
11108
11090
  };
11109
11091
 
11110
11092
  // src/scripts/resolveFlow.ts
11111
- import { execFileSync as execFileSync21 } from "child_process";
11093
+ import { execFileSync as execFileSync20 } from "child_process";
11112
11094
  init_issue();
11113
11095
  var CONFLICT_DIFF_MAX_BYTES = 4e4;
11114
11096
  var resolveFlow = async (ctx) => {
@@ -11202,7 +11184,7 @@ function buildPreferBlock(prefer, baseBranch) {
11202
11184
  }
11203
11185
  function getConflictedFiles(cwd) {
11204
11186
  try {
11205
- const out = execFileSync21("git", ["diff", "--name-only", "--diff-filter=U"], {
11187
+ const out = execFileSync20("git", ["diff", "--name-only", "--diff-filter=U"], {
11206
11188
  encoding: "utf-8",
11207
11189
  cwd,
11208
11190
  env: { ...process.env, HUSKY: "0" }
@@ -11217,7 +11199,7 @@ function getConflictMarkersPreview(files, cwd, maxBytes = CONFLICT_DIFF_MAX_BYTE
11217
11199
  let total = 0;
11218
11200
  for (const f of files) {
11219
11201
  try {
11220
- const content = execFileSync21("cat", [f], { encoding: "utf-8", cwd }).toString();
11202
+ const content = execFileSync20("cat", [f], { encoding: "utf-8", cwd }).toString();
11221
11203
  const snippet = `### ${f}
11222
11204
 
11223
11205
  \`\`\`
@@ -11241,12 +11223,12 @@ function tryPostPr3(prNumber, body, cwd) {
11241
11223
  function pushEmptyCommit(branch, cwd) {
11242
11224
  const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
11243
11225
  try {
11244
- execFileSync21(
11226
+ execFileSync20(
11245
11227
  "git",
11246
11228
  ["commit", "--allow-empty", "-m", "chore: kody resolve refresh \u2014 empty commit to recompute mergeable status"],
11247
11229
  { cwd, env, stdio: ["ignore", "pipe", "pipe"] }
11248
11230
  );
11249
- execFileSync21("git", ["push", "-u", "origin", branch], {
11231
+ execFileSync20("git", ["push", "-u", "origin", branch], {
11250
11232
  cwd,
11251
11233
  env,
11252
11234
  stdio: ["ignore", "pipe", "pipe"]
@@ -11377,10 +11359,10 @@ var resolvePreviewUrl = async (ctx) => {
11377
11359
  };
11378
11360
 
11379
11361
  // src/scripts/resolveQaUrl.ts
11380
- import { execFileSync as execFileSync22 } from "child_process";
11362
+ import { execFileSync as execFileSync21 } from "child_process";
11381
11363
  function ghQuery(args, cwd) {
11382
11364
  try {
11383
- const out = execFileSync22("gh", args, {
11365
+ const out = execFileSync21("gh", args, {
11384
11366
  cwd,
11385
11367
  stdio: ["ignore", "pipe", "pipe"],
11386
11368
  encoding: "utf-8",
@@ -11450,7 +11432,7 @@ var resolveQaUrl = async (ctx) => {
11450
11432
  };
11451
11433
 
11452
11434
  // src/scripts/revertFlow.ts
11453
- import { execFileSync as execFileSync23 } from "child_process";
11435
+ import { execFileSync as execFileSync22 } from "child_process";
11454
11436
  init_issue();
11455
11437
  var SHA_RE = /^[0-9a-f]{4,40}$/i;
11456
11438
  var revertFlow = async (ctx) => {
@@ -11533,7 +11515,7 @@ function buildPrSummary(resolved) {
11533
11515
  return resolved.map((r) => `- Reverted \`${r.full.slice(0, 7)}\`${r.subject ? ` \u2014 ${r.subject}` : ""}`).join("\n");
11534
11516
  }
11535
11517
  function git4(args, cwd) {
11536
- return execFileSync23("git", args, {
11518
+ return execFileSync22("git", args, {
11537
11519
  encoding: "utf-8",
11538
11520
  timeout: 3e4,
11539
11521
  cwd,
@@ -11543,7 +11525,7 @@ function git4(args, cwd) {
11543
11525
  }
11544
11526
  function isAncestorOfHead(sha, cwd) {
11545
11527
  try {
11546
- execFileSync23("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
11528
+ execFileSync22("git", ["merge-base", "--is-ancestor", sha, "HEAD"], {
11547
11529
  cwd,
11548
11530
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
11549
11531
  stdio: ["ignore", "ignore", "ignore"]
@@ -12189,11 +12171,11 @@ var skipAgent = async (ctx) => {
12189
12171
  };
12190
12172
 
12191
12173
  // src/scripts/stageMergeConflicts.ts
12192
- import { execFileSync as execFileSync24 } from "child_process";
12174
+ import { execFileSync as execFileSync23 } from "child_process";
12193
12175
  var stageMergeConflicts = async (ctx) => {
12194
12176
  if (ctx.data.agentDone === false) return;
12195
12177
  try {
12196
- execFileSync24("git", ["add", "-A"], {
12178
+ execFileSync23("git", ["add", "-A"], {
12197
12179
  cwd: ctx.cwd,
12198
12180
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
12199
12181
  stdio: "pipe"
@@ -12204,8 +12186,6 @@ var stageMergeConflicts = async (ctx) => {
12204
12186
 
12205
12187
  // src/scripts/startFlow.ts
12206
12188
  init_issue();
12207
- import { execFileSync as execFileSync25 } from "child_process";
12208
- var API_TIMEOUT_MS9 = 3e4;
12209
12189
  var startFlow = async (ctx, profile, _agentResult, args) => {
12210
12190
  const entry = args?.entry;
12211
12191
  if (!entry) {
@@ -12232,28 +12212,16 @@ var startFlow = async (ctx, profile, _agentResult, args) => {
12232
12212
  hops: 0
12233
12213
  };
12234
12214
  }
12235
- postKodyComment(target, issueNumber, state, entry, ctx.cwd);
12215
+ const usePr = target === "pr" && !!state?.core.prUrl;
12216
+ const targetNumber = usePr ? parsePrNumber(state.core.prUrl) ?? issueNumber : issueNumber;
12217
+ ctx.output.nextDispatch = {
12218
+ executable: entry,
12219
+ cliArgs: usePr ? { pr: targetNumber } : { issue: targetNumber }
12220
+ };
12236
12221
  };
12237
- function postKodyComment(target, issueNumber, state, next, cwd) {
12238
- const targetNumber = target === "pr" && state?.core.prUrl ? parsePrNumber(state.core.prUrl) ?? issueNumber : issueNumber;
12239
- const sub = target === "pr" && state?.core.prUrl ? "pr" : "issue";
12240
- const body = `@kody ${next}`;
12241
- try {
12242
- execFileSync25("gh", [sub, "comment", String(targetNumber), "--body", body], {
12243
- timeout: API_TIMEOUT_MS9,
12244
- cwd,
12245
- stdio: ["ignore", "pipe", "pipe"]
12246
- });
12247
- } catch (err) {
12248
- process.stderr.write(
12249
- `[kody startFlow] failed to post @kody ${next} on ${sub} #${targetNumber}: ${err instanceof Error ? err.message : String(err)}
12250
- `
12251
- );
12252
- }
12253
- }
12254
12222
 
12255
12223
  // src/scripts/syncFlow.ts
12256
- import { execFileSync as execFileSync26 } from "child_process";
12224
+ import { execFileSync as execFileSync24 } from "child_process";
12257
12225
  init_issue();
12258
12226
  var DONE2 = {
12259
12227
  label: "kody:done",
@@ -12331,7 +12299,7 @@ function bail2(ctx, prNumber, reason) {
12331
12299
  }
12332
12300
  function revParseHead(cwd) {
12333
12301
  try {
12334
- return execFileSync26("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
12302
+ return execFileSync24("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
12335
12303
  } catch {
12336
12304
  return "";
12337
12305
  }
@@ -12588,8 +12556,8 @@ var verifyWithRetry = async (ctx) => {
12588
12556
 
12589
12557
  // src/scripts/waitForCi.ts
12590
12558
  init_issue();
12591
- import { execFileSync as execFileSync27 } from "child_process";
12592
- var API_TIMEOUT_MS10 = 3e4;
12559
+ import { execFileSync as execFileSync25 } from "child_process";
12560
+ var API_TIMEOUT_MS8 = 3e4;
12593
12561
  var waitForCi = async (ctx, _profile, _agentResult, args) => {
12594
12562
  const timeoutMinutes = numArg(args, "timeoutMinutes", 30);
12595
12563
  const pollSeconds = numArg(args, "pollSeconds", 30);
@@ -12666,9 +12634,9 @@ var waitForCi = async (ctx, _profile, _agentResult, args) => {
12666
12634
  };
12667
12635
  function fetchChecks(prNumber, cwd) {
12668
12636
  try {
12669
- const raw = execFileSync27("gh", ["pr", "checks", String(prNumber), "--json", "bucket,state,name,workflow,link"], {
12637
+ const raw = execFileSync25("gh", ["pr", "checks", String(prNumber), "--json", "bucket,state,name,workflow,link"], {
12670
12638
  encoding: "utf-8",
12671
- timeout: API_TIMEOUT_MS10,
12639
+ timeout: API_TIMEOUT_MS8,
12672
12640
  cwd,
12673
12641
  stdio: ["ignore", "pipe", "pipe"]
12674
12642
  });
@@ -13142,7 +13110,7 @@ var allScriptNames = /* @__PURE__ */ new Set([
13142
13110
  ]);
13143
13111
 
13144
13112
  // src/tools.ts
13145
- import { execFileSync as execFileSync28 } from "child_process";
13113
+ import { execFileSync as execFileSync26 } from "child_process";
13146
13114
  function verifyCliTools(tools, cwd) {
13147
13115
  const out = [];
13148
13116
  for (const t of tools) out.push(verifyOne(t, cwd));
@@ -13179,7 +13147,7 @@ function verifyOne(tool4, cwd) {
13179
13147
  }
13180
13148
  function runShell(cmd, cwd, timeoutMs = 3e4) {
13181
13149
  try {
13182
- const stdout = execFileSync28("sh", ["-c", cmd], {
13150
+ const stdout = execFileSync26("sh", ["-c", cmd], {
13183
13151
  cwd,
13184
13152
  stdio: ["ignore", "pipe", "pipe"],
13185
13153
  timeout: timeoutMs,
@@ -13485,7 +13453,8 @@ async function runExecutable(profileName, input) {
13485
13453
  return finishAndEnd({
13486
13454
  exitCode: ctx.output.exitCode ?? 0,
13487
13455
  prUrl: ctx.output.prUrl,
13488
- reason: ctx.output.reason
13456
+ reason: ctx.output.reason,
13457
+ nextDispatch: ctx.output.nextDispatch
13489
13458
  });
13490
13459
  } finally {
13491
13460
  clearStampedLifecycleLabels(profile, ctx);
@@ -13968,7 +13937,7 @@ async function runContainerLoop(profile, ctx, input) {
13968
13937
  }
13969
13938
  function resetWorkingTree2(cwd) {
13970
13939
  try {
13971
- execFileSync29("git", ["reset", "--hard", "HEAD"], {
13940
+ execFileSync27("git", ["reset", "--hard", "HEAD"], {
13972
13941
  cwd,
13973
13942
  stdio: ["ignore", "pipe", "pipe"],
13974
13943
  timeout: 3e4
@@ -14154,7 +14123,7 @@ function detectPackageManager2(cwd) {
14154
14123
  }
14155
14124
  function shellOut(cmd, args, cwd, stream = true) {
14156
14125
  try {
14157
- execFileSync30(cmd, args, {
14126
+ execFileSync28(cmd, args, {
14158
14127
  cwd,
14159
14128
  stdio: stream ? "inherit" : "pipe",
14160
14129
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" }
@@ -14167,7 +14136,7 @@ function shellOut(cmd, args, cwd, stream = true) {
14167
14136
  }
14168
14137
  function isOnPath(bin) {
14169
14138
  try {
14170
- execFileSync30("which", [bin], { stdio: "pipe" });
14139
+ execFileSync28("which", [bin], { stdio: "pipe" });
14171
14140
  return true;
14172
14141
  } catch {
14173
14142
  return false;
@@ -14208,7 +14177,7 @@ function installLitellmIfNeeded(cwd) {
14208
14177
  } catch {
14209
14178
  }
14210
14179
  try {
14211
- execFileSync30("python3", ["-c", "import litellm"], { stdio: "pipe" });
14180
+ execFileSync28("python3", ["-c", "import litellm"], { stdio: "pipe" });
14212
14181
  process.stdout.write("\u2192 kody: litellm already installed\n");
14213
14182
  return 0;
14214
14183
  } catch {
@@ -14218,16 +14187,16 @@ function installLitellmIfNeeded(cwd) {
14218
14187
  }
14219
14188
  function configureGitIdentity(cwd) {
14220
14189
  try {
14221
- const name = execFileSync30("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
14190
+ const name = execFileSync28("git", ["config", "user.name"], { cwd, stdio: "pipe", encoding: "utf-8" }).trim();
14222
14191
  if (name) return;
14223
14192
  } catch {
14224
14193
  }
14225
14194
  try {
14226
- execFileSync30("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
14195
+ execFileSync28("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
14227
14196
  } catch {
14228
14197
  }
14229
14198
  try {
14230
- execFileSync30("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
14199
+ execFileSync28("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
14231
14200
  cwd,
14232
14201
  stdio: "pipe"
14233
14202
  });
@@ -14384,13 +14353,33 @@ ${CI_HELP}`);
14384
14353
  `);
14385
14354
  try {
14386
14355
  const config = earlyConfig ?? loadConfig(cwd);
14387
- const result = await runExecutable(dispatch2.executable, {
14356
+ let result = await runExecutable(dispatch2.executable, {
14388
14357
  cliArgs: dispatch2.cliArgs,
14389
14358
  cwd,
14390
14359
  config,
14391
14360
  verbose: args.verbose,
14392
14361
  quiet: args.quiet
14393
14362
  });
14363
+ const MAX_CHAIN_HOPS = 60;
14364
+ for (let hops = 1; result.nextDispatch && hops <= MAX_CHAIN_HOPS; hops++) {
14365
+ const next = result.nextDispatch;
14366
+ process.stdout.write(`\u2192 kody: in-process hand-off \u2192 ${next.executable} (hop ${hops}/${MAX_CHAIN_HOPS})
14367
+
14368
+ `);
14369
+ result = await runExecutable(next.executable, {
14370
+ cliArgs: next.cliArgs,
14371
+ cwd,
14372
+ config,
14373
+ verbose: args.verbose,
14374
+ quiet: args.quiet
14375
+ });
14376
+ }
14377
+ if (result.nextDispatch) {
14378
+ process.stderr.write(
14379
+ `[kody] in-process hand-off cap (${MAX_CHAIN_HOPS}) reached; not running ${result.nextDispatch.executable}
14380
+ `
14381
+ );
14382
+ }
14394
14383
  if (result.exitCode !== 0 && result.exitCode !== 1 && result.exitCode !== 2) {
14395
14384
  postFailureTail(issueNumber, cwd, result.reason || `exit ${result.exitCode}`);
14396
14385
  }
@@ -14547,8 +14536,8 @@ function commitChatFiles(cwd, sessionId, verbose) {
14547
14536
  if (paths.length === 0) return;
14548
14537
  const opts = { cwd, stdio: verbose ? "inherit" : "pipe" };
14549
14538
  try {
14550
- execFileSync31("git", ["add", "-f", ...paths], opts);
14551
- execFileSync31("git", ["commit", "--quiet", "-m", `chat: reply for ${sessionId}`], opts);
14539
+ execFileSync29("git", ["add", "-f", ...paths], opts);
14540
+ execFileSync29("git", ["commit", "--quiet", "-m", `chat: reply for ${sessionId}`], opts);
14552
14541
  } catch (err) {
14553
14542
  const msg = err instanceof Error ? err.message : String(err);
14554
14543
  process.stderr.write(`[kody:chat] commit skipped: ${msg}
@@ -347,6 +347,14 @@ export interface Context {
347
347
  exitCode: number
348
348
  prUrl?: string
349
349
  reason?: string
350
+ /**
351
+ * In-process hand-off to the next stage. A stage (e.g. `classify`) sets
352
+ * this so the orchestrator runs the chosen sub-orchestrator
353
+ * (feature/bug/spec/chore) in the same process — instead of posting an
354
+ * `@kody <next>` comment, which is silently ignored when Kody comments as
355
+ * a GitHub App (bot author), stalling the pipeline at classify.
356
+ */
357
+ nextDispatch?: { executable: string; cliArgs: Record<string, unknown> }
350
358
  }
351
359
  /**
352
360
  * If a preflight script sets this to true, the executor skips the agent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.159",
3
+ "version": "0.4.161",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",