@kody-ade/kody-engine-lite 0.1.79 → 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.
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";
@@ -439,6 +444,41 @@ function syncWithDefault(cwd) {
439
444
  logger.warn(` Merge conflict with origin/${defaultBranch} \u2014 skipping sync`);
440
445
  }
441
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
+ }
442
482
  function commitAll(message, cwd) {
443
483
  const status = git(["status", "--porcelain"], { cwd });
444
484
  if (!status) {
@@ -2920,8 +2960,16 @@ If no pipeline flaw is detected, set "pipelineFlaw" to null.
2920
2960
  import * as fs15 from "fs";
2921
2961
  import * as path15 from "path";
2922
2962
  function ensureFeatureBranchIfNeeded(ctx) {
2923
- if (ctx.input.prNumber) return;
2924
- 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;
2925
2973
  try {
2926
2974
  const taskMdPath = path15.join(ctx.taskDir, "task.md");
2927
2975
  const title = fs15.existsSync(taskMdPath) ? fs15.readFileSync(taskMdPath, "utf-8").split("\n")[0].slice(0, 50) : ctx.taskId;
@@ -3346,12 +3394,13 @@ function parseArgs() {
3346
3394
  kody fix --task-id <id> [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
3347
3395
  kody fix-ci [--pr-number <n>] [--ci-run-id <id>] [--cwd <path>] [--issue-number <n>] [--feedback "<text>"]
3348
3396
  kody review [--pr-number <n>] [--issue-number <n>] [--cwd <path>] [--local]
3397
+ kody resolve --pr-number <n> [--cwd <path>] [--local]
3349
3398
  kody status --task-id <id> [--cwd <path>]
3350
3399
  kody --help`);
3351
3400
  process.exit(0);
3352
3401
  }
3353
3402
  const command2 = args2[0];
3354
- if (!["run", "rerun", "fix", "fix-ci", "status", "review"].includes(command2)) {
3403
+ if (!["run", "rerun", "fix", "fix-ci", "status", "review", "resolve"].includes(command2)) {
3355
3404
  console.error(`Unknown command: ${command2}`);
3356
3405
  process.exit(1);
3357
3406
  }
@@ -3584,6 +3633,133 @@ var init_task_state = __esm({
3584
3633
  }
3585
3634
  });
3586
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
+
3587
3763
  // src/entry.ts
3588
3764
  var entry_exports = {};
3589
3765
  import * as fs21 from "fs";
@@ -3773,6 +3949,42 @@ async function main() {
3773
3949
  }
3774
3950
  process.exit(0);
3775
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
+ }
3776
3988
  logger.info("Preflight checks:");
3777
3989
  runPreflight();
3778
3990
  if (input.task) {
@@ -3992,7 +4204,7 @@ var init_entry = __esm({
3992
4204
  // src/bin/cli.ts
3993
4205
  import * as fs22 from "fs";
3994
4206
  import * as path21 from "path";
3995
- import { execFileSync as execFileSync11 } from "child_process";
4207
+ import { execFileSync as execFileSync12 } from "child_process";
3996
4208
  import { fileURLToPath } from "url";
3997
4209
  var __dirname = path21.dirname(fileURLToPath(import.meta.url));
3998
4210
  var PKG_ROOT = path21.resolve(__dirname, "..", "..");
@@ -4003,7 +4215,7 @@ function getVersion() {
4003
4215
  }
4004
4216
  function checkCommand2(name, args2, fix) {
4005
4217
  try {
4006
- const output = execFileSync11(name, args2, {
4218
+ const output = execFileSync12(name, args2, {
4007
4219
  encoding: "utf-8",
4008
4220
  timeout: 1e4,
4009
4221
  stdio: ["pipe", "pipe", "pipe"]
@@ -4021,7 +4233,7 @@ function checkFile(filePath, description, fix) {
4021
4233
  }
4022
4234
  function checkGhAuth(cwd) {
4023
4235
  try {
4024
- const output = execFileSync11("gh", ["auth", "status"], {
4236
+ const output = execFileSync12("gh", ["auth", "status"], {
4025
4237
  encoding: "utf-8",
4026
4238
  timeout: 1e4,
4027
4239
  cwd,
@@ -4039,7 +4251,7 @@ function checkGhAuth(cwd) {
4039
4251
  }
4040
4252
  function checkGhRepoAccess(cwd) {
4041
4253
  try {
4042
- const remote = execFileSync11("git", ["remote", "get-url", "origin"], {
4254
+ const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
4043
4255
  encoding: "utf-8",
4044
4256
  timeout: 5e3,
4045
4257
  cwd,
@@ -4050,7 +4262,7 @@ function checkGhRepoAccess(cwd) {
4050
4262
  return { name: "GitHub repo", ok: false, fix: "Set git remote origin to a GitHub URL" };
4051
4263
  }
4052
4264
  const repoSlug = `${match[1]}/${match[2]}`;
4053
- execFileSync11("gh", ["repo", "view", repoSlug, "--json", "name"], {
4265
+ execFileSync12("gh", ["repo", "view", repoSlug, "--json", "name"], {
4054
4266
  encoding: "utf-8",
4055
4267
  timeout: 1e4,
4056
4268
  cwd,
@@ -4063,7 +4275,7 @@ function checkGhRepoAccess(cwd) {
4063
4275
  }
4064
4276
  function checkGhSecret(repoSlug, secretName) {
4065
4277
  try {
4066
- const output = execFileSync11("gh", ["secret", "list", "--repo", repoSlug], {
4278
+ const output = execFileSync12("gh", ["secret", "list", "--repo", repoSlug], {
4067
4279
  encoding: "utf-8",
4068
4280
  timeout: 1e4,
4069
4281
  stdio: ["pipe", "pipe", "pipe"]
@@ -4091,7 +4303,7 @@ function detectBasicConfig(cwd) {
4091
4303
  else if (!fs22.existsSync(path21.join(cwd, "pnpm-lock.yaml")) && fs22.existsSync(path21.join(cwd, "package-lock.json"))) pm = "npm";
4092
4304
  let defaultBranch = "main";
4093
4305
  try {
4094
- const ref = execFileSync11("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
4306
+ const ref = execFileSync12("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
4095
4307
  encoding: "utf-8",
4096
4308
  timeout: 5e3,
4097
4309
  cwd,
@@ -4100,7 +4312,7 @@ function detectBasicConfig(cwd) {
4100
4312
  defaultBranch = ref.replace("refs/remotes/origin/", "");
4101
4313
  } catch {
4102
4314
  try {
4103
- execFileSync11("git", ["rev-parse", "--verify", "origin/dev"], {
4315
+ execFileSync12("git", ["rev-parse", "--verify", "origin/dev"], {
4104
4316
  encoding: "utf-8",
4105
4317
  timeout: 5e3,
4106
4318
  cwd,
@@ -4113,7 +4325,7 @@ function detectBasicConfig(cwd) {
4113
4325
  let owner = "";
4114
4326
  let repo = "";
4115
4327
  try {
4116
- const remote = execFileSync11("git", ["remote", "get-url", "origin"], {
4328
+ const remote = execFileSync12("git", ["remote", "get-url", "origin"], {
4117
4329
  encoding: "utf-8",
4118
4330
  timeout: 5e3,
4119
4331
  cwd,
@@ -4305,7 +4517,7 @@ function initCommand(opts) {
4305
4517
  if (filesToCommit.length > 0) {
4306
4518
  try {
4307
4519
  const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
4308
- execFileSync11("npx", ["prettier", "--write", ...fullPaths], {
4520
+ execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
4309
4521
  cwd,
4310
4522
  encoding: "utf-8",
4311
4523
  timeout: 3e4,
@@ -4316,13 +4528,13 @@ function initCommand(opts) {
4316
4528
  }
4317
4529
  if (filesToCommit.length > 0) {
4318
4530
  try {
4319
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4320
- 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();
4321
4533
  if (staged) {
4322
- 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" });
4323
4535
  console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
4324
4536
  try {
4325
- execFileSync11("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4537
+ execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4326
4538
  console.log(" \u2713 Pushed to origin");
4327
4539
  } catch {
4328
4540
  console.log(" \u25CB Push failed \u2014 run 'git push' manually");
@@ -4416,7 +4628,7 @@ function ghComment(issueNumber, body, cwd) {
4416
4628
  } catch {
4417
4629
  }
4418
4630
  if (!repoSlug) return;
4419
- execFileSync11("gh", [
4631
+ execFileSync12("gh", [
4420
4632
  "issue",
4421
4633
  "comment",
4422
4634
  String(issueNumber),
@@ -4549,7 +4761,7 @@ Output ONLY valid JSON. No markdown fences. No explanation.
4549
4761
  ${repoContext}`;
4550
4762
  console.log(" \u23F3 Analyzing project...");
4551
4763
  try {
4552
- const output = execFileSync11("claude", [
4764
+ const output = execFileSync12("claude", [
4553
4765
  "--print",
4554
4766
  "--model",
4555
4767
  "haiku",
@@ -4652,7 +4864,7 @@ ${repoContext}
4652
4864
 
4653
4865
  REMINDER: Output the full prompt template first (unchanged), then your three appended sections. Do NOT include "${contextPlaceholder}".`;
4654
4866
  try {
4655
- const output = execFileSync11("claude", [
4867
+ const output = execFileSync12("claude", [
4656
4868
  "--print",
4657
4869
  "--model",
4658
4870
  "haiku",
@@ -4709,7 +4921,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4709
4921
  ];
4710
4922
  for (const label of labels) {
4711
4923
  try {
4712
- execFileSync11("gh", [
4924
+ execFileSync12("gh", [
4713
4925
  "label",
4714
4926
  "create",
4715
4927
  label.name,
@@ -4729,7 +4941,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4729
4941
  console.log(` \u2713 ${label.name}`);
4730
4942
  } catch {
4731
4943
  try {
4732
- execFileSync11("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
4944
+ execFileSync12("gh", ["label", "list", "--repo", repoSlug, "--search", label.name], {
4733
4945
  cwd,
4734
4946
  encoding: "utf-8",
4735
4947
  timeout: 1e4,
@@ -4768,7 +4980,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4768
4980
  try {
4769
4981
  const fullPaths = filesToCommit.map((f) => path21.join(cwd, f));
4770
4982
  for (let pass = 0; pass < 2; pass++) {
4771
- execFileSync11("npx", ["prettier", "--write", ...fullPaths], {
4983
+ execFileSync12("npx", ["prettier", "--write", ...fullPaths], {
4772
4984
  cwd,
4773
4985
  encoding: "utf-8",
4774
4986
  timeout: 3e4,
@@ -4783,13 +4995,13 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4783
4995
  if (filesToCommit.length > 0) {
4784
4996
  try {
4785
4997
  if (isCI3) {
4786
- const branchName = `kody/bootstrap-${Date.now()}`;
4787
- execFileSync11("git", ["checkout", "-b", branchName], { cwd, stdio: "pipe" });
4788
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4789
- const staged = execFileSync11("git", ["diff", "--cached", "--name-only"], { cwd, encoding: "utf-8" }).trim();
4998
+ const branchName = `kody-bootstrap-${Date.now()}`;
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();
4790
5002
  if (staged) {
4791
- 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" });
4792
- 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 });
4793
5005
  console.log(` \u2713 Pushed branch: ${branchName}`);
4794
5006
  let baseBranch = "main";
4795
5007
  try {
@@ -4801,7 +5013,7 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4801
5013
  } catch {
4802
5014
  }
4803
5015
  try {
4804
- const prUrl = execFileSync11("gh", [
5016
+ const prUrl = execFileSync12("gh", [
4805
5017
  "pr",
4806
5018
  "create",
4807
5019
  "--title",
@@ -4840,13 +5052,13 @@ Create it manually.`, cwd);
4840
5052
  console.log(" \u25CB No new changes to commit");
4841
5053
  }
4842
5054
  } else {
4843
- execFileSync11("git", ["add", ...filesToCommit], { cwd, stdio: "pipe" });
4844
- 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();
4845
5057
  if (staged) {
4846
- 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" });
4847
5059
  console.log(` \u2713 Committed: ${filesToCommit.join(", ")}`);
4848
5060
  try {
4849
- execFileSync11("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
5061
+ execFileSync12("git", ["push"], { cwd, stdio: "pipe", timeout: 6e4 });
4850
5062
  console.log(" \u2713 Pushed to origin");
4851
5063
  } catch {
4852
5064
  console.log(" \u25CB Push failed \u2014 run 'git push' manually");
@@ -4967,7 +5179,7 @@ function installSkillsForProject(cwd) {
4967
5179
  }
4968
5180
  try {
4969
5181
  console.log(` Installing: ${skill.label} (${skill.package})`);
4970
- execFileSync11("npx", ["skills", "add", skill.package, "--yes"], {
5182
+ execFileSync12("npx", ["skills", "add", skill.package, "--yes"], {
4971
5183
  cwd,
4972
5184
  encoding: "utf-8",
4973
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.79",
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"