@kody-ade/kody-engine-lite 0.1.80 → 0.1.81

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 (71) hide show
  1. package/dist/bin/cli.js +256 -53
  2. package/package.json +1 -1
  3. package/templates/kody.yml +3 -2
  4. package/dist/agent-runner.d.ts +0 -4
  5. package/dist/agent-runner.js +0 -122
  6. package/dist/ci/parse-inputs.d.ts +0 -6
  7. package/dist/ci/parse-inputs.js +0 -76
  8. package/dist/ci/parse-safety.d.ts +0 -6
  9. package/dist/ci/parse-safety.js +0 -22
  10. package/dist/cli/args.d.ts +0 -13
  11. package/dist/cli/args.js +0 -42
  12. package/dist/cli/litellm.d.ts +0 -2
  13. package/dist/cli/litellm.js +0 -85
  14. package/dist/cli/task-resolution.d.ts +0 -2
  15. package/dist/cli/task-resolution.js +0 -41
  16. package/dist/config.d.ts +0 -49
  17. package/dist/config.js +0 -72
  18. package/dist/context.d.ts +0 -4
  19. package/dist/context.js +0 -83
  20. package/dist/definitions.d.ts +0 -3
  21. package/dist/definitions.js +0 -59
  22. package/dist/entry.d.ts +0 -1
  23. package/dist/entry.js +0 -236
  24. package/dist/git-utils.d.ts +0 -13
  25. package/dist/git-utils.js +0 -174
  26. package/dist/github-api.d.ts +0 -14
  27. package/dist/github-api.js +0 -114
  28. package/dist/kody-utils.d.ts +0 -1
  29. package/dist/kody-utils.js +0 -9
  30. package/dist/learning/auto-learn.d.ts +0 -2
  31. package/dist/learning/auto-learn.js +0 -169
  32. package/dist/logger.d.ts +0 -14
  33. package/dist/logger.js +0 -51
  34. package/dist/memory.d.ts +0 -1
  35. package/dist/memory.js +0 -20
  36. package/dist/observer.d.ts +0 -9
  37. package/dist/observer.js +0 -80
  38. package/dist/pipeline/complexity.d.ts +0 -3
  39. package/dist/pipeline/complexity.js +0 -12
  40. package/dist/pipeline/executor-registry.d.ts +0 -3
  41. package/dist/pipeline/executor-registry.js +0 -20
  42. package/dist/pipeline/hooks.d.ts +0 -17
  43. package/dist/pipeline/hooks.js +0 -110
  44. package/dist/pipeline/questions.d.ts +0 -2
  45. package/dist/pipeline/questions.js +0 -44
  46. package/dist/pipeline/runner-selection.d.ts +0 -2
  47. package/dist/pipeline/runner-selection.js +0 -13
  48. package/dist/pipeline/state.d.ts +0 -4
  49. package/dist/pipeline/state.js +0 -37
  50. package/dist/pipeline.d.ts +0 -3
  51. package/dist/pipeline.js +0 -213
  52. package/dist/preflight.d.ts +0 -1
  53. package/dist/preflight.js +0 -69
  54. package/dist/retrospective.d.ts +0 -26
  55. package/dist/retrospective.js +0 -211
  56. package/dist/stages/agent.d.ts +0 -2
  57. package/dist/stages/agent.js +0 -94
  58. package/dist/stages/gate.d.ts +0 -2
  59. package/dist/stages/gate.js +0 -32
  60. package/dist/stages/review.d.ts +0 -2
  61. package/dist/stages/review.js +0 -32
  62. package/dist/stages/ship.d.ts +0 -3
  63. package/dist/stages/ship.js +0 -154
  64. package/dist/stages/verify.d.ts +0 -2
  65. package/dist/stages/verify.js +0 -94
  66. package/dist/types.d.ts +0 -61
  67. package/dist/types.js +0 -1
  68. package/dist/validators.d.ts +0 -8
  69. package/dist/validators.js +0 -42
  70. package/dist/verify-runner.d.ts +0 -11
  71. package/dist/verify-runner.js +0 -110
package/dist/bin/cli.js CHANGED
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
2
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
4
  var __esm = (fn, res) => function __init() {
4
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
6
  };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
6
11
 
7
12
  // src/agent-runner.ts
8
13
  import { spawn, execFileSync } from "child_process";
@@ -290,7 +295,7 @@ function getProjectConfig() {
290
295
  }
291
296
  return _config;
292
297
  }
293
- var DEFAULT_CONFIG, LITELLM_DEFAULT_PORT, LITELLM_DEFAULT_URL, TIER_TO_ANTHROPIC_IDS, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
298
+ var DEFAULT_CONFIG, LITELLM_DEFAULT_PORT, LITELLM_DEFAULT_URL, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
294
299
  var init_config = __esm({
295
300
  "src/config.ts"() {
296
301
  "use strict";
@@ -320,11 +325,6 @@ var init_config = __esm({
320
325
  };
321
326
  LITELLM_DEFAULT_PORT = 4e3;
322
327
  LITELLM_DEFAULT_URL = `http://localhost:${LITELLM_DEFAULT_PORT}`;
323
- TIER_TO_ANTHROPIC_IDS = {
324
- cheap: ["claude-haiku-4-5-20251001", "claude-haiku-4-5", "haiku"],
325
- mid: ["claude-sonnet-4-6-20250514", "claude-sonnet-4-6", "sonnet"],
326
- strong: ["claude-opus-4-6-20250514", "claude-opus-4-6", "opus"]
327
- };
328
328
  VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
329
329
  FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
330
330
  _config = null;
@@ -444,6 +444,41 @@ function syncWithDefault(cwd) {
444
444
  logger.warn(` Merge conflict with origin/${defaultBranch} \u2014 skipping sync`);
445
445
  }
446
446
  }
447
+ function mergeDefault(cwd) {
448
+ const defaultBranch = getDefaultBranch(cwd);
449
+ const current = getCurrentBranch(cwd);
450
+ if (current === defaultBranch) return "clean";
451
+ try {
452
+ git(["fetch", "origin", defaultBranch], { cwd, timeout: 3e4 });
453
+ } catch {
454
+ logger.warn(" Failed to fetch latest from origin");
455
+ return "error";
456
+ }
457
+ try {
458
+ git(["merge", `origin/${defaultBranch}`, "--no-edit"], { cwd, timeout: 3e4 });
459
+ logger.info(` Merged origin/${defaultBranch} cleanly`);
460
+ return "clean";
461
+ } catch {
462
+ try {
463
+ const unmerged = git(["diff", "--name-only", "--diff-filter=U"], { cwd });
464
+ if (unmerged.trim()) return "conflict";
465
+ } catch {
466
+ }
467
+ try {
468
+ git(["merge", "--abort"], { cwd });
469
+ } catch {
470
+ }
471
+ return "error";
472
+ }
473
+ }
474
+ function getConflictedFiles(cwd) {
475
+ try {
476
+ const output = git(["diff", "--name-only", "--diff-filter=U"], { cwd });
477
+ return output ? output.split("\n") : [];
478
+ } catch {
479
+ return [];
480
+ }
481
+ }
447
482
  function commitAll(message, cwd) {
448
483
  const status = git(["status", "--porcelain"], { cwd });
449
484
  if (!status) {
@@ -1483,9 +1518,6 @@ ${prompt}` : prompt;
1483
1518
  }
1484
1519
  function resolveModel(modelTier, stageName) {
1485
1520
  const config = getProjectConfig();
1486
- if (config.agent.provider && config.agent.provider !== "anthropic") {
1487
- return DEFAULT_MODEL_MAP[modelTier] ?? "sonnet";
1488
- }
1489
1521
  const mapped = config.agent.modelMap[modelTier];
1490
1522
  if (mapped) return mapped;
1491
1523
  return DEFAULT_MODEL_MAP[modelTier] ?? "sonnet";
@@ -2928,8 +2960,16 @@ If no pipeline flaw is detected, set "pipelineFlaw" to null.
2928
2960
  import * as fs15 from "fs";
2929
2961
  import * as path15 from "path";
2930
2962
  function ensureFeatureBranchIfNeeded(ctx) {
2931
- if (ctx.input.prNumber) return;
2932
- if (!ctx.input.issueNumber || ctx.input.dryRun) return;
2963
+ if (ctx.input.dryRun) return;
2964
+ if (ctx.input.prNumber) {
2965
+ try {
2966
+ syncWithDefault(ctx.projectDir);
2967
+ } catch (err) {
2968
+ logger.warn(` Failed to sync with default branch: ${err}`);
2969
+ }
2970
+ return;
2971
+ }
2972
+ if (!ctx.input.issueNumber) return;
2933
2973
  try {
2934
2974
  const taskMdPath = path15.join(ctx.taskDir, "task.md");
2935
2975
  const title = fs15.existsSync(taskMdPath) ? fs15.readFileSync(taskMdPath, "utf-8").split("\n")[0].slice(0, 50) : ctx.taskId;
@@ -3354,12 +3394,13 @@ function parseArgs() {
3354
3394
  kody fix --task-id <id> [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
3355
3395
  kody fix-ci [--pr-number <n>] [--ci-run-id <id>] [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
3356
3396
  kody review [--pr-number <n>] [--issue-number <n>] [--cwd <path>] [--local]
3397
+ kody resolve --pr-number <n> [--cwd <path>] [--local]
3357
3398
  kody status --task-id <id> [--cwd <path>]
3358
3399
  kody --help`);
3359
3400
  process.exit(0);
3360
3401
  }
3361
3402
  const command2 = args2[0];
3362
- if (!["run", "rerun", "fix", "fix-ci", "status", "review"].includes(command2)) {
3403
+ if (!["run", "rerun", "fix", "fix-ci", "status", "review", "resolve"].includes(command2)) {
3363
3404
  console.error(`Unknown command: ${command2}`);
3364
3405
  process.exit(1);
3365
3406
  }
@@ -3437,15 +3478,14 @@ async function checkModelHealth(baseUrl, apiKey, model = "claude-haiku-4-5") {
3437
3478
  function generateLitellmConfig(provider, modelMap) {
3438
3479
  const apiKeyVar = providerApiKeyEnvVar(provider);
3439
3480
  const entries = ["model_list:"];
3440
- for (const [tier, providerModel] of Object.entries(modelMap)) {
3441
- const anthropicIds = TIER_TO_ANTHROPIC_IDS[tier];
3442
- if (!anthropicIds) continue;
3443
- for (const modelName of anthropicIds) {
3444
- entries.push(` - model_name: ${modelName}`);
3445
- entries.push(` litellm_params:`);
3446
- entries.push(` model: ${provider}/${providerModel}`);
3447
- entries.push(` api_key: os.environ/${apiKeyVar}`);
3448
- }
3481
+ const seen = /* @__PURE__ */ new Set();
3482
+ for (const providerModel of Object.values(modelMap)) {
3483
+ if (seen.has(providerModel)) continue;
3484
+ seen.add(providerModel);
3485
+ entries.push(` - model_name: ${providerModel}`);
3486
+ entries.push(` litellm_params:`);
3487
+ entries.push(` model: ${provider}/${providerModel}`);
3488
+ entries.push(` api_key: os.environ/${apiKeyVar}`);
3449
3489
  }
3450
3490
  return entries.join("\n") + "\n";
3451
3491
  }
@@ -3593,6 +3633,133 @@ var init_task_state = __esm({
3593
3633
  }
3594
3634
  });
3595
3635
 
3636
+ // src/resolve.ts
3637
+ var resolve_exports = {};
3638
+ __export(resolve_exports, {
3639
+ runResolve: () => runResolve
3640
+ });
3641
+ import { execFileSync as execFileSync11 } from "child_process";
3642
+ function getConflictContext(cwd, files) {
3643
+ const parts = [];
3644
+ for (const file of files.slice(0, 10)) {
3645
+ try {
3646
+ const content = execFileSync11("git", ["diff", file], {
3647
+ cwd,
3648
+ encoding: "utf-8",
3649
+ stdio: ["pipe", "pipe", "pipe"]
3650
+ }).trim();
3651
+ parts.push(`### ${file}
3652
+ \`\`\`diff
3653
+ ${content.slice(0, 3e3)}
3654
+ \`\`\``);
3655
+ } catch {
3656
+ parts.push(`### ${file}
3657
+ (could not read diff)`);
3658
+ }
3659
+ }
3660
+ return parts.join("\n\n");
3661
+ }
3662
+ async function runResolve(options) {
3663
+ const { prNumber, projectDir, runners, local } = options;
3664
+ const defaultBranch = getDefaultBranch(projectDir);
3665
+ logger.info(`Resolving PR #${prNumber} \u2014 merging ${defaultBranch}...`);
3666
+ const mergeResult = mergeDefault(projectDir);
3667
+ if (mergeResult === "error") {
3668
+ return { outcome: "failed", error: "Failed to merge default branch" };
3669
+ }
3670
+ if (mergeResult === "clean") {
3671
+ logger.info(" Clean merge \u2014 no conflicts");
3672
+ if (!local) {
3673
+ pushBranch(projectDir);
3674
+ }
3675
+ return { outcome: "merged" };
3676
+ }
3677
+ const conflictedFiles = getConflictedFiles(projectDir);
3678
+ if (conflictedFiles.length === 0) {
3679
+ return { outcome: "failed", error: "Merge reported conflict but no conflicted files found" };
3680
+ }
3681
+ logger.info(` ${conflictedFiles.length} conflicted file(s): ${conflictedFiles.join(", ")}`);
3682
+ const conflictContext = getConflictContext(projectDir, conflictedFiles);
3683
+ const prompt = buildResolvePrompt(conflictedFiles, conflictContext, defaultBranch);
3684
+ const config = getProjectConfig();
3685
+ const runnerName = config.agent.defaultRunner ?? Object.keys(runners)[0] ?? "claude";
3686
+ const runner = runners[runnerName];
3687
+ if (!runner) {
3688
+ return { outcome: "failed", error: `Runner "${runnerName}" not found` };
3689
+ }
3690
+ const model = resolveModel("mid");
3691
+ const extraEnv = {};
3692
+ if (needsLitellmProxy(config)) {
3693
+ extraEnv.ANTHROPIC_BASE_URL = getLitellmUrl();
3694
+ }
3695
+ logger.info(` Running agent to resolve conflicts (model=${model})...`);
3696
+ const result = await runner.run("resolve", prompt, model, 3e5, projectDir, {
3697
+ cwd: projectDir,
3698
+ env: extraEnv
3699
+ });
3700
+ if (result.outcome !== "completed") {
3701
+ return { outcome: "failed", error: `Agent failed: ${result.error}` };
3702
+ }
3703
+ logger.info(" Verifying resolution...");
3704
+ const verify = runQualityGates(projectDir, projectDir);
3705
+ if (!verify.pass) {
3706
+ const errorSummary = verify.errors.slice(0, 5).join("\n");
3707
+ logger.error(` Verification failed:
3708
+ ${errorSummary}`);
3709
+ return { outcome: "failed", error: `Conflict resolution failed verification:
3710
+ ${errorSummary}` };
3711
+ }
3712
+ logger.info(" Verification passed");
3713
+ commitAll(`chore: resolve merge conflicts with ${defaultBranch}`, projectDir);
3714
+ if (!local) {
3715
+ pushBranch(projectDir);
3716
+ try {
3717
+ const fileList = conflictedFiles.map((f) => `- \`${f}\``).join("\n");
3718
+ postPRComment(
3719
+ prNumber,
3720
+ `\u2705 **Merge conflicts resolved** with \`${defaultBranch}\`
3721
+
3722
+ **Conflicted files:**
3723
+ ${fileList}
3724
+
3725
+ _Verification passed. Please review the resolution._`
3726
+ );
3727
+ } catch {
3728
+ }
3729
+ }
3730
+ return { outcome: "resolved" };
3731
+ }
3732
+ function buildResolvePrompt(files, conflictContext, defaultBranch) {
3733
+ return `You are resolving merge conflicts between a feature branch and the \`${defaultBranch}\` branch.
3734
+
3735
+ ## Conflicted files
3736
+ ${files.map((f) => `- ${f}`).join("\n")}
3737
+
3738
+ ## Conflict diffs
3739
+ ${conflictContext}
3740
+
3741
+ ## Instructions
3742
+ 1. Read each conflicted file
3743
+ 2. Resolve the conflict markers (<<<<<<< / ======= / >>>>>>>) by combining both sides correctly:
3744
+ - For feature/business logic: preserve the PR branch's intent
3745
+ - For infrastructure/config/dependencies: prefer the \`${defaultBranch}\` branch
3746
+ - For imports/types: merge both sides
3747
+ 3. Write the resolved file using the Edit or Write tool
3748
+ 4. Do NOT add new features or refactor \u2014 only resolve the conflicts
3749
+ 5. After resolving all files, run \`git add .\` to stage the resolution`;
3750
+ }
3751
+ var init_resolve = __esm({
3752
+ "src/resolve.ts"() {
3753
+ "use strict";
3754
+ init_git_utils();
3755
+ init_github_api();
3756
+ init_verify_runner();
3757
+ init_logger();
3758
+ init_context();
3759
+ init_config();
3760
+ }
3761
+ });
3762
+
3596
3763
  // src/entry.ts
3597
3764
  var entry_exports = {};
3598
3765
  import * as fs21 from "fs";
@@ -3638,7 +3805,7 @@ async function runModelHealthCheck(config) {
3638
3805
  logger.warn(`Skipping model health check \u2014 ${keyName} not set`);
3639
3806
  return;
3640
3807
  }
3641
- const model = usesProxy ? "claude-haiku-4-5" : config.agent.modelMap.cheap;
3808
+ const model = config.agent.modelMap.cheap;
3642
3809
  logger.info(`Model health check (${model} via ${usesProxy ? "LiteLLM" : "Anthropic"})...`);
3643
3810
  const result = await checkModelHealth(baseUrl, apiKey, model);
3644
3811
  if (result.ok) {
@@ -3782,6 +3949,42 @@ async function main() {
3782
3949
  }
3783
3950
  process.exit(0);
3784
3951
  }
3952
+ if (input.command === "resolve") {
3953
+ if (!input.prNumber) {
3954
+ console.error("--pr-number is required for resolve command");
3955
+ process.exit(1);
3956
+ }
3957
+ runPreflight();
3958
+ const config2 = getProjectConfig();
3959
+ const litellmProcess2 = await ensureLitellmProxy(config2, projectDir);
3960
+ await runModelHealthCheck(config2);
3961
+ const runners2 = createRunners(config2);
3962
+ const defaultRunnerName2 = config2.agent.defaultRunner ?? Object.keys(runners2)[0] ?? "claude";
3963
+ const defaultRunner2 = runners2[defaultRunnerName2];
3964
+ if (!defaultRunner2) {
3965
+ console.error(`Default runner "${defaultRunnerName2}" not configured`);
3966
+ process.exit(1);
3967
+ }
3968
+ const healthy2 = await defaultRunner2.healthCheck();
3969
+ if (!healthy2) {
3970
+ console.error(`Runner "${defaultRunnerName2}" health check failed`);
3971
+ process.exit(1);
3972
+ }
3973
+ const { runResolve: runResolve2 } = await Promise.resolve().then(() => (init_resolve(), resolve_exports));
3974
+ const result = await runResolve2({
3975
+ prNumber: input.prNumber,
3976
+ projectDir,
3977
+ runners: runners2,
3978
+ local: input.local ?? true
3979
+ });
3980
+ if (litellmProcess2) litellmProcess2.kill?.();
3981
+ if (result.outcome === "failed") {
3982
+ console.error(`Resolve failed: ${result.error}`);
3983
+ process.exit(1);
3984
+ }
3985
+ console.log(`Resolve: ${result.outcome}`);
3986
+ process.exit(0);
3987
+ }
3785
3988
  logger.info("Preflight checks:");
3786
3989
  runPreflight();
3787
3990
  if (input.task) {
@@ -4001,7 +4204,7 @@ var init_entry = __esm({
4001
4204
  // src/bin/cli.ts
4002
4205
  import * as fs22 from "fs";
4003
4206
  import * as path21 from "path";
4004
- import { execFileSync as execFileSync11 } from "child_process";
4207
+ import { execFileSync as execFileSync12 } from "child_process";
4005
4208
  import { fileURLToPath } from "url";
4006
4209
  var __dirname = path21.dirname(fileURLToPath(import.meta.url));
4007
4210
  var PKG_ROOT = path21.resolve(__dirname, "..", "..");
@@ -4012,7 +4215,7 @@ function getVersion() {
4012
4215
  }
4013
4216
  function checkCommand2(name, args2, fix) {
4014
4217
  try {
4015
- const output = execFileSync11(name, args2, {
4218
+ const output = execFileSync12(name, args2, {
4016
4219
  encoding: "utf-8",
4017
4220
  timeout: 1e4,
4018
4221
  stdio: ["pipe", "pipe", "pipe"]
@@ -4030,7 +4233,7 @@ function checkFile(filePath, description, fix) {
4030
4233
  }
4031
4234
  function checkGhAuth(cwd) {
4032
4235
  try {
4033
- const output = execFileSync11("gh", ["auth", "status"], {
4236
+ const output = execFileSync12("gh", ["auth", "status"], {
4034
4237
  encoding: "utf-8",
4035
4238
  timeout: 1e4,
4036
4239
  cwd,
@@ -4048,7 +4251,7 @@ function checkGhAuth(cwd) {
4048
4251
  }
4049
4252
  function checkGhRepoAccess(cwd) {
4050
4253
  try {
4051
- const remote = execFileSync11("git", ["remote", "get-url", "origin"], {
4254
+ const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
4052
4255
  encoding: "utf-8",
4053
4256
  timeout: 5e3,
4054
4257
  cwd,
@@ -4059,7 +4262,7 @@ function checkGhRepoAccess(cwd) {
4059
4262
  return { name: "GitHub repo", ok: false, fix: "Set git remote origin to a GitHub URL" };
4060
4263
  }
4061
4264
  const repoSlug = `${match[1]}/${match[2]}`;
4062
- execFileSync11("gh", ["repo", "view", repoSlug, "--json", "name"], {
4265
+ execFileSync12("gh", ["repo", "view", repoSlug, "--json", "name"], {
4063
4266
  encoding: "utf-8",
4064
4267
  timeout: 1e4,
4065
4268
  cwd,
@@ -4072,7 +4275,7 @@ function checkGhRepoAccess(cwd) {
4072
4275
  }
4073
4276
  function checkGhSecret(repoSlug, secretName) {
4074
4277
  try {
4075
- const output = execFileSync11("gh", ["secret", "list", "--repo", repoSlug], {
4278
+ const output = execFileSync12("gh", ["secret", "list", "--repo", repoSlug], {
4076
4279
  encoding: "utf-8",
4077
4280
  timeout: 1e4,
4078
4281
  stdio: ["pipe", "pipe", "pipe"]
@@ -4100,7 +4303,7 @@ function detectBasicConfig(cwd) {
4100
4303
  else if (!fs22.existsSync(path21.join(cwd, "pnpm-lock.yaml")) && fs22.existsSync(path21.join(cwd, "package-lock.json"))) pm = "npm";
4101
4304
  let defaultBranch = "main";
4102
4305
  try {
4103
- const ref = execFileSync11("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
4306
+ const ref = execFileSync12("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
4104
4307
  encoding: "utf-8",
4105
4308
  timeout: 5e3,
4106
4309
  cwd,
@@ -4109,7 +4312,7 @@ function detectBasicConfig(cwd) {
4109
4312
  defaultBranch = ref.replace("refs/remotes/origin/", "");
4110
4313
  } catch {
4111
4314
  try {
4112
- execFileSync11("git", ["rev-parse", "--verify", "origin/dev"], {
4315
+ execFileSync12("git", ["rev-parse", "--verify", "origin/dev"], {
4113
4316
  encoding: "utf-8",
4114
4317
  timeout: 5e3,
4115
4318
  cwd,
@@ -4122,7 +4325,7 @@ function detectBasicConfig(cwd) {
4122
4325
  let owner = "";
4123
4326
  let repo = "";
4124
4327
  try {
4125
- const remote = execFileSync11("git", ["remote", "get-url", "origin"], {
4328
+ const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
4126
4329
  encoding: "utf-8",
4127
4330
  timeout: 5e3,
4128
4331
  cwd,
@@ -4314,7 +4517,7 @@ function initCommand(opts) {
4314
4517
  if (filesToCommit.length > 0) {
4315
4518
  try {
4316
4519
  const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
4317
- execFileSync11("npx", ["prettier", "--write", ...fullPaths], {
4520
+ execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
4318
4521
  cwd,
4319
4522
  encoding: "utf-8",
4320
4523
  timeout: 3e4,
@@ -4325,13 +4528,13 @@ function initCommand(opts) {
4325
4528
  }
4326
4529
  if (filesToCommit.length > 0) {
4327
4530
  try {
4328
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4329
- const staged = execFileSync11("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4531
+ execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4532
+ const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4330
4533
  if (staged) {
4331
- execFileSync11("git", ["commit", "-m", "chore: Add Kody Engine workflow and config\n\nAdd GitHub Actions workflow and auto-detected configuration for Kody Engine Lite."], { cwd, stdio: "pipe" });
4534
+ execFileSync12("git", ["commit", "-m", "chore: Add Kody Engine workflow and config\n\nAdd GitHub Actions workflow and auto-detected configuration for Kody Engine Lite."], { cwd, stdio: "pipe" });
4332
4535
  console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
4333
4536
  try {
4334
- execFileSync11("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4537
+ execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4335
4538
  console.log(" \u2713 Pushed to origin");
4336
4539
  } catch {
4337
4540
  console.log(" \u25CB Push failed \u2014 run 'git push' manually");
@@ -4425,7 +4628,7 @@ function ghComment(issueNumber, body, cwd) {
4425
4628
  } catch {
4426
4629
  }
4427
4630
  if (!repoSlug) return;
4428
- execFileSync11("gh", [
4631
+ execFileSync12("gh", [
4429
4632
  "issue",
4430
4633
  "comment",
4431
4634
  String(issueNumber),
@@ -4558,7 +4761,7 @@ Output ONLY valid JSON. No markdown fences. No explanation.
4558
4761
  ${repoContext}`;
4559
4762
  console.log(" \u23F3 Analyzing project...");
4560
4763
  try {
4561
- const output = execFileSync11("claude", [
4764
+ const output = execFileSync12("claude", [
4562
4765
  "--print",
4563
4766
  "--model",
4564
4767
  "haiku",
@@ -4661,7 +4864,7 @@ ${repoContext}
4661
4864
 
4662
4865
  REMINDER: Output the full prompt template first (unchanged), then your three appended sections. Do NOT include "${contextPlaceholder}".`;
4663
4866
  try {
4664
- const output = execFileSync11("claude", [
4867
+ const output = execFileSync12("claude", [
4665
4868
  "--print",
4666
4869
  "--model",
4667
4870
  "haiku",
@@ -4718,7 +4921,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4718
4921
  ];
4719
4922
  for (const label of labels) {
4720
4923
  try {
4721
- execFileSync11("gh", [
4924
+ execFileSync12("gh", [
4722
4925
  "label",
4723
4926
  "create",
4724
4927
  label.name,
@@ -4738,7 +4941,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4738
4941
  console.log(` \u2713 ${label.name}`);
4739
4942
  } catch {
4740
4943
  try {
4741
- execFileSync11("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
4944
+ execFileSync12("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
4742
4945
  cwd,
4743
4946
  encoding: "utf-8",
4744
4947
  timeout: 1e4,
@@ -4777,7 +4980,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4777
4980
  try {
4778
4981
  const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
4779
4982
  for (let pass = 0; pass < 2; pass++) {
4780
- execFileSync11("npx", ["prettier", "--write", ...fullPaths], {
4983
+ execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
4781
4984
  cwd,
4782
4985
  encoding: "utf-8",
4783
4986
  timeout: 3e4,
@@ -4793,12 +4996,12 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4793
4996
  try {
4794
4997
  if (isCI3) {
4795
4998
  const branchName = `kody-bootstrap-${Date.now()}`;
4796
- execFileSync11("git", ["checkout", "-b", branchName], { cwd, stdio: "pipe" });
4797
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4798
- const staged = execFileSync11("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4999
+ execFileSync12("git", ["checkout", "-b", branchName], { cwd, stdio: "pipe" });
5000
+ execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
5001
+ const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4799
5002
  if (staged) {
4800
- execFileSync11("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
4801
- execFileSync11("git", ["push", "-u", "origin", branchName], { cwd, stdio: "pipe", timeout: 6e4 });
5003
+ execFileSync12("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
5004
+ execFileSync12("git", ["push", "-u", "origin", branchName], { cwd, stdio: "pipe", timeout: 6e4 });
4802
5005
  console.log(` \u2713 Pushed branch: ${branchName}`);
4803
5006
  let baseBranch = "main";
4804
5007
  try {
@@ -4810,7 +5013,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4810
5013
  } catch {
4811
5014
  }
4812
5015
  try {
4813
- const prUrl = execFileSync11("gh", [
5016
+ const prUrl = execFileSync12("gh", [
4814
5017
  "pr",
4815
5018
  "create",
4816
5019
  "--title",
@@ -4849,13 +5052,13 @@ Create it manually.`, cwd);
4849
5052
  console.log(" \u25CB No new changes to commit");
4850
5053
  }
4851
5054
  } else {
4852
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4853
- const staged = execFileSync11("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
5055
+ execFileSync12("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
5056
+ const staged = execFileSync12("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4854
5057
  if (staged) {
4855
- execFileSync11("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
5058
+ execFileSync12("git", ["commit", "-m", "chore: Add Kody project memory and step files\n\nBootstrap Kody Engine with project-specific architecture, conventions, and pipeline step files."], { cwd, stdio: "pipe" });
4856
5059
  console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
4857
5060
  try {
4858
- execFileSync11("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
5061
+ execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4859
5062
  console.log(" \u2713 Pushed to origin");
4860
5063
  } catch {
4861
5064
  console.log(" \u25CB Push failed \u2014 run 'git push' manually");
@@ -4976,7 +5179,7 @@ function installSkillsForProject(cwd) {
4976
5179
  }
4977
5180
  try {
4978
5181
  console.log(` Installing: ${skill.label} (${skill.package})`);
4979
- execFileSync11("npx", ["skills", "add", skill.package, "--yes"], {
5182
+ execFileSync12("npx", ["skills", "add", skill.package, "--yes"], {
4980
5183
  cwd,
4981
5184
  encoding: "utf-8",
4982
5185
  timeout: 6e4,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.80",
3
+ "version": "0.1.81",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -119,7 +119,7 @@ jobs:
119
119
 
120
120
  # Validate mode
121
121
  case "$MODE" in
122
- full|rerun|fix|fix-ci|status|approve|review|bootstrap) ;;
122
+ full|rerun|fix|fix-ci|status|approve|review|resolve|bootstrap) ;;
123
123
  *)
124
124
  # If first arg isn't a mode, it might be a task-id or nothing
125
125
  if [ -n "$MODE" ] && [ "$MODE" != "" ]; then
@@ -219,7 +219,7 @@ jobs:
219
219
  token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
220
220
 
221
221
  - name: Checkout PR branch (for fix/rerun/review on PRs)
222
- if: github.event.issue.pull_request && (needs.parse.outputs.mode == 'fix' || needs.parse.outputs.mode == 'fix-ci' || needs.parse.outputs.mode == 'rerun' || needs.parse.outputs.mode == 'review')
222
+ if: github.event.issue.pull_request && (needs.parse.outputs.mode == 'fix' || needs.parse.outputs.mode == 'fix-ci' || needs.parse.outputs.mode == 'rerun' || needs.parse.outputs.mode == 'review' || needs.parse.outputs.mode == 'resolve')
223
223
  env:
224
224
  GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }}
225
225
  run: |
@@ -277,6 +277,7 @@ jobs:
277
277
  [ "$MODE" = "fix" ] && CMD="fix"
278
278
  [ "$MODE" = "fix-ci" ] && CMD="fix-ci"
279
279
  [ "$MODE" = "review" ] && CMD="review"
280
+ [ "$MODE" = "resolve" ] && CMD="resolve"
280
281
  ARGS="--issue-number $ISSUE_NUMBER"
281
282
  [ -n "$TASK_ID" ] && ARGS="$ARGS --task-id $TASK_ID"
282
283
  [ -n "$PR_NUMBER" ] && ARGS="$ARGS --pr-number $PR_NUMBER"
@@ -1,4 +0,0 @@
1
- import type { AgentRunner } from "./types.js";
2
- import type { KodyConfig } from "./config.js";
3
- export declare function createClaudeCodeRunner(): AgentRunner;
4
- export declare function createRunners(config: KodyConfig): Record<string, AgentRunner>;