@kody-ade/kody-engine 0.4.159 → 0.4.160

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.160",
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",
@@ -6931,17 +6931,14 @@ var dispatchClassified = async (ctx) => {
6931
6931
  if (!classification || !VALID_CLASSES2.has(classification)) return;
6932
6932
  const action = ctx.data.action;
6933
6933
  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}`;
6934
+ const base = typeof ctx.args.base === "string" && ctx.args.base.length > 0 ? ctx.args.base : void 0;
6936
6935
  const auditLine = ctx.data.classificationAudit ?? `\u{1F50E} kody classified as \`${classification}\``;
6937
6936
  const state = ctx.data.taskState ?? emptyState();
6938
6937
  const nextState = reduce(state, "classify", action, void 0);
6939
6938
  const stateBody = renderStateComment(nextState);
6940
6939
  ctx.data.taskState = nextState;
6941
6940
  ctx.data.taskStateRendered = stateBody;
6942
- const body = `${dispatchLine}
6943
-
6944
- ${auditLine}
6941
+ const body = `${auditLine}
6945
6942
 
6946
6943
  ${stateBody}`;
6947
6944
  try {
@@ -6952,17 +6949,16 @@ ${stateBody}`;
6952
6949
  });
6953
6950
  } catch (err) {
6954
6951
  process.stderr.write(
6955
- `[kody dispatchClassified] failed to dispatch ${dispatchLine}: ${err instanceof Error ? err.message : String(err)}
6952
+ `[kody dispatchClassified] failed to post state comment for #${issueNumber}: ${err instanceof Error ? err.message : String(err)}
6956
6953
  `
6957
6954
  );
6958
- ctx.data.action = failedAction3("dispatch post failed");
6959
- ctx.output.exitCode = 1;
6960
- ctx.output.reason = "classify: dispatch failed";
6961
6955
  }
6956
+ const cliArgs = { issue: issueNumber };
6957
+ if (base && getProfileInputs(classification)?.some((i) => i.name === "base")) {
6958
+ cliArgs.base = base;
6959
+ }
6960
+ ctx.output.nextDispatch = { executable: classification, cliArgs };
6962
6961
  };
6963
- function failedAction3(reason) {
6964
- return { type: "CLASSIFY_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
6965
- }
6966
6962
 
6967
6963
  // src/scripts/dispatchJobFileTicks.ts
6968
6964
  import * as fs29 from "fs";
@@ -9572,7 +9568,7 @@ function qaAction2(verdict, payload) {
9572
9568
  const type = verdict === "PASS" ? "QA_PASS" : verdict === "CONCERNS" ? "QA_CONCERNS" : verdict === "FAIL" ? "QA_FAIL" : "QA_COMPLETED";
9573
9569
  return { type, payload: { verdict, ...payload }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
9574
9570
  }
9575
- function failedAction4(reason) {
9571
+ function failedAction3(reason) {
9576
9572
  return { type: "QA_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
9577
9573
  }
9578
9574
  function slugifyScope(scope) {
@@ -9608,7 +9604,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9608
9604
  `);
9609
9605
  ctx.output.exitCode = 1;
9610
9606
  ctx.output.reason = reason;
9611
- ctx.data.action = failedAction4(reason);
9607
+ ctx.data.action = failedAction3(reason);
9612
9608
  return;
9613
9609
  }
9614
9610
  const reportBody = agentResult.finalText.trim();
@@ -9616,7 +9612,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9616
9612
  process.stderr.write("qa-engineer: agent produced no report body\n");
9617
9613
  ctx.output.exitCode = 1;
9618
9614
  ctx.output.reason = "empty report body";
9619
- ctx.data.action = failedAction4("empty report body");
9615
+ ctx.data.action = failedAction3("empty report body");
9620
9616
  return;
9621
9617
  }
9622
9618
  const verdict = detectVerdict(reportBody);
@@ -9630,7 +9626,7 @@ var openQaIssue = async (ctx, _profile, agentResult) => {
9630
9626
  const msg = err instanceof Error ? err.message : String(err);
9631
9627
  ctx.output.exitCode = 4;
9632
9628
  ctx.output.reason = `failed to comment on issue #${existingIssue}: ${msg}`;
9633
- ctx.data.action = failedAction4(ctx.output.reason);
9629
+ ctx.data.action = failedAction3(ctx.output.reason);
9634
9630
  return;
9635
9631
  }
9636
9632
  process.stdout.write(
@@ -9652,7 +9648,7 @@ QA_REPORT_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.gith
9652
9648
  const msg = err instanceof Error ? err.message : String(err);
9653
9649
  ctx.output.exitCode = 4;
9654
9650
  ctx.output.reason = `failed to open QA issue: ${truncate2(msg, 1e3)}`;
9655
- ctx.data.action = failedAction4(ctx.output.reason);
9651
+ ctx.data.action = failedAction3(ctx.output.reason);
9656
9652
  return;
9657
9653
  }
9658
9654
  process.stdout.write(`
@@ -10964,7 +10960,7 @@ var recordClassification = async (ctx) => {
10964
10960
  reason = parsed?.reason ?? null;
10965
10961
  }
10966
10962
  if (!classification) {
10967
- ctx.data.action = failedAction5("classification missing or invalid");
10963
+ ctx.data.action = failedAction4("classification missing or invalid");
10968
10964
  tryAuditComment(
10969
10965
  issueNumber,
10970
10966
  "\u26A0\uFE0F kody classifier could not decide \u2014 please re-run with an explicit `@kody <type>`.",
@@ -11005,7 +11001,7 @@ function tryAuditComment(issueNumber, body, cwd) {
11005
11001
  function makeAction3(type, payload) {
11006
11002
  return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
11007
11003
  }
11008
- function failedAction5(reason) {
11004
+ function failedAction4(reason) {
11009
11005
  return { type: "CLASSIFY_FAILED", payload: { reason }, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
11010
11006
  }
11011
11007
 
@@ -13485,7 +13481,8 @@ async function runExecutable(profileName, input) {
13485
13481
  return finishAndEnd({
13486
13482
  exitCode: ctx.output.exitCode ?? 0,
13487
13483
  prUrl: ctx.output.prUrl,
13488
- reason: ctx.output.reason
13484
+ reason: ctx.output.reason,
13485
+ nextDispatch: ctx.output.nextDispatch
13489
13486
  });
13490
13487
  } finally {
13491
13488
  clearStampedLifecycleLabels(profile, ctx);
@@ -14384,13 +14381,33 @@ ${CI_HELP}`);
14384
14381
  `);
14385
14382
  try {
14386
14383
  const config = earlyConfig ?? loadConfig(cwd);
14387
- const result = await runExecutable(dispatch2.executable, {
14384
+ let result = await runExecutable(dispatch2.executable, {
14388
14385
  cliArgs: dispatch2.cliArgs,
14389
14386
  cwd,
14390
14387
  config,
14391
14388
  verbose: args.verbose,
14392
14389
  quiet: args.quiet
14393
14390
  });
14391
+ const MAX_CHAIN_HOPS = 4;
14392
+ for (let hops = 1; result.nextDispatch && hops <= MAX_CHAIN_HOPS; hops++) {
14393
+ const next = result.nextDispatch;
14394
+ process.stdout.write(`\u2192 kody: in-process hand-off \u2192 ${next.executable} (hop ${hops}/${MAX_CHAIN_HOPS})
14395
+
14396
+ `);
14397
+ result = await runExecutable(next.executable, {
14398
+ cliArgs: next.cliArgs,
14399
+ cwd,
14400
+ config,
14401
+ verbose: args.verbose,
14402
+ quiet: args.quiet
14403
+ });
14404
+ }
14405
+ if (result.nextDispatch) {
14406
+ process.stderr.write(
14407
+ `[kody] in-process hand-off cap (${MAX_CHAIN_HOPS}) reached; not running ${result.nextDispatch.executable}
14408
+ `
14409
+ );
14410
+ }
14394
14411
  if (result.exitCode !== 0 && result.exitCode !== 1 && result.exitCode !== 2) {
14395
14412
  postFailureTail(issueNumber, cwd, result.reason || `exit ${result.exitCode}`);
14396
14413
  }
@@ -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.160",
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",