@kody-ade/kody-engine 0.3.21 → 0.3.22

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
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@kody-ade/kody-engine",
6
- version: "0.3.21",
6
+ version: "0.3.22",
7
7
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
8
8
  license: "MIT",
9
9
  type: "module",
@@ -51,8 +51,8 @@ var package_default = {
51
51
 
52
52
  // src/chat-cli.ts
53
53
  import { execFileSync as execFileSync22 } from "child_process";
54
- import * as fs23 from "fs";
55
- import * as path20 from "path";
54
+ import * as fs22 from "fs";
55
+ import * as path19 from "path";
56
56
 
57
57
  // src/chat/events.ts
58
58
  import * as fs from "fs";
@@ -154,7 +154,7 @@ function loadConfig(projectDir = process.cwd()) {
154
154
  throw new Error(`kody.config.json is invalid JSON: ${msg}`);
155
155
  }
156
156
  const quality = raw.quality ?? {};
157
- const git4 = raw.git ?? {};
157
+ const git3 = raw.git ?? {};
158
158
  const github = raw.github ?? {};
159
159
  const agent = raw.agent ?? {};
160
160
  if (!agent.model || typeof agent.model !== "string") {
@@ -170,7 +170,7 @@ function loadConfig(projectDir = process.cwd()) {
170
170
  testUnit: typeof quality.testUnit === "string" ? quality.testUnit : ""
171
171
  },
172
172
  git: {
173
- defaultBranch: typeof git4.defaultBranch === "string" ? git4.defaultBranch : "main"
173
+ defaultBranch: typeof git3.defaultBranch === "string" ? git3.defaultBranch : "main"
174
174
  },
175
175
  github: {
176
176
  owner: String(github.owner),
@@ -223,6 +223,7 @@ function parseReleaseConfig(raw) {
223
223
  if (Array.isArray(r.versionFiles)) out.versionFiles = r.versionFiles.filter((f) => typeof f === "string");
224
224
  if (typeof r.publishCommand === "string") out.publishCommand = r.publishCommand;
225
225
  if (typeof r.notifyCommand === "string") out.notifyCommand = r.notifyCommand;
226
+ if (typeof r.deployCommand === "string") out.deployCommand = r.deployCommand;
226
227
  if (typeof r.e2eCommand === "string") out.e2eCommand = r.e2eCommand;
227
228
  if (typeof r.draftRelease === "boolean") out.draftRelease = r.draftRelease;
228
229
  if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
@@ -577,8 +578,8 @@ async function emit(sink, type, sessionId, suffix, payload) {
577
578
 
578
579
  // src/kody-cli.ts
579
580
  import { execFileSync as execFileSync21 } from "child_process";
580
- import * as fs22 from "fs";
581
- import * as path19 from "path";
581
+ import * as fs21 from "fs";
582
+ import * as path18 from "path";
582
583
 
583
584
  // src/dispatch.ts
584
585
  import * as fs6 from "fs";
@@ -680,19 +681,7 @@ function autoDispatch(opts) {
680
681
  if (eventName === "schedule") {
681
682
  return { executable: "mission-scheduler", cliArgs: {}, target: 0 };
682
683
  }
683
- if (eventName === "pull_request") {
684
- const merged = event.pull_request?.merged === true;
685
- const headRef = String(event.pull_request?.head?.ref ?? "");
686
- const prNumber = Number(event.pull_request?.number ?? 0);
687
- if (merged && /^release\/v\d+\.\d+\.\d+/.test(headRef) && prNumber > 0) {
688
- return {
689
- executable: "release",
690
- cliArgs: { mode: "finalize", issue: prNumber },
691
- target: prNumber
692
- };
693
- }
694
- return null;
695
- }
684
+ if (eventName === "pull_request") return null;
696
685
  if (eventName !== "issue_comment") return null;
697
686
  const rawBody = String(event.comment?.body ?? "");
698
687
  const authorLogin = String(event.comment?.user?.login ?? "");
@@ -816,9 +805,9 @@ function coerceBare(spec, value) {
816
805
  }
817
806
 
818
807
  // src/executor.ts
819
- import { spawnSync as spawnSync2 } from "child_process";
820
- import * as fs21 from "fs";
821
- import * as path18 from "path";
808
+ import { spawnSync } from "child_process";
809
+ import * as fs20 from "fs";
810
+ import * as path17 from "path";
822
811
 
823
812
  // src/litellm.ts
824
813
  import { execFileSync, spawn } from "child_process";
@@ -4044,6 +4033,53 @@ var loadTaskState = async (ctx) => {
4044
4033
  ctx.data.taskState = readTaskState(target, number, ctx.cwd);
4045
4034
  };
4046
4035
 
4036
+ // src/scripts/mergeReleasePr.ts
4037
+ import { execFileSync as execFileSync14 } from "child_process";
4038
+ var API_TIMEOUT_MS6 = 6e4;
4039
+ var mergeReleasePr = async (ctx) => {
4040
+ const state = ctx.data.taskState;
4041
+ const prUrl = state?.core.prUrl;
4042
+ if (!prUrl) {
4043
+ ctx.data.action = makeAction("RELEASE_MERGE_FAILED", { reason: "no prUrl on task state" });
4044
+ if (state) state.core.lastOutcome = ctx.data.action;
4045
+ return;
4046
+ }
4047
+ const prNumber = parsePrNumber2(prUrl);
4048
+ if (!prNumber) {
4049
+ ctx.data.action = makeAction("RELEASE_MERGE_FAILED", { reason: `cannot parse PR number from ${prUrl}` });
4050
+ if (state) state.core.lastOutcome = ctx.data.action;
4051
+ return;
4052
+ }
4053
+ try {
4054
+ execFileSync14("gh", ["pr", "merge", String(prNumber), "--merge"], {
4055
+ timeout: API_TIMEOUT_MS6,
4056
+ cwd: ctx.cwd,
4057
+ stdio: ["ignore", "pipe", "pipe"]
4058
+ });
4059
+ } catch (err) {
4060
+ const msg = err instanceof Error ? err.message : String(err);
4061
+ if (/already merged/i.test(msg)) {
4062
+ ctx.data.action = makeAction("RELEASE_MERGE_COMPLETED", { prUrl, alreadyMerged: true });
4063
+ if (state) state.core.lastOutcome = ctx.data.action;
4064
+ return;
4065
+ }
4066
+ ctx.data.action = makeAction("RELEASE_MERGE_FAILED", { reason: msg, prUrl });
4067
+ if (state) state.core.lastOutcome = ctx.data.action;
4068
+ return;
4069
+ }
4070
+ ctx.data.action = makeAction("RELEASE_MERGE_COMPLETED", { prUrl });
4071
+ if (state) state.core.lastOutcome = ctx.data.action;
4072
+ };
4073
+ function makeAction(type, payload) {
4074
+ return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
4075
+ }
4076
+ function parsePrNumber2(prUrl) {
4077
+ const m = prUrl.match(/\/pull\/(\d+)(?:[/?#]|$)/);
4078
+ if (!m) return null;
4079
+ const n = parseInt(m[1], 10);
4080
+ return Number.isFinite(n) ? n : null;
4081
+ }
4082
+
4047
4083
  // src/scripts/mirrorStateToPr.ts
4048
4084
  var mirrorStateToPr = async (ctx) => {
4049
4085
  const issueNumber = ctx.data.commentTargetNumber;
@@ -4051,7 +4087,7 @@ var mirrorStateToPr = async (ctx) => {
4051
4087
  if (!issueNumber || issueTarget !== "issue") return;
4052
4088
  const prUrl = ctx.output.prUrl ?? ctx.data.prResult?.url;
4053
4089
  if (!prUrl) return;
4054
- const prNumber = parsePrNumber2(prUrl);
4090
+ const prNumber = parsePrNumber3(prUrl);
4055
4091
  if (!prNumber) return;
4056
4092
  let state;
4057
4093
  try {
@@ -4069,18 +4105,49 @@ var mirrorStateToPr = async (ctx) => {
4069
4105
  );
4070
4106
  }
4071
4107
  };
4072
- function parsePrNumber2(prUrl) {
4108
+ function parsePrNumber3(prUrl) {
4073
4109
  const m = prUrl.match(/\/pull\/(\d+)(?:[/?#]|$)/);
4074
4110
  if (!m) return null;
4075
4111
  const n = parseInt(m[1], 10);
4076
4112
  return Number.isFinite(n) ? n : null;
4077
4113
  }
4078
4114
 
4115
+ // src/scripts/notifyTerminal.ts
4116
+ var notifyTerminal = async (ctx, _profile, _agentResult, args) => {
4117
+ const issueNumber = ctx.args.issue;
4118
+ if (!issueNumber || issueNumber <= 0) return;
4119
+ const label = args?.label ?? "kody run";
4120
+ const dryRun = ctx.args["dry-run"] === true || ctx.args.dryRun === true;
4121
+ const exit = ctx.output.exitCode ?? 0;
4122
+ const reason = ctx.output.reason;
4123
+ const prUrl = ctx.output.prUrl;
4124
+ const body = composeBody({ label, exit, prUrl, reason, dryRun });
4125
+ try {
4126
+ postIssueComment(issueNumber, body, ctx.cwd);
4127
+ } catch (err) {
4128
+ process.stderr.write(
4129
+ `[kody notifyTerminal] failed to post comment on #${issueNumber}: ${err instanceof Error ? err.message : String(err)}
4130
+ `
4131
+ );
4132
+ }
4133
+ };
4134
+ function composeBody({ label, exit, prUrl, reason, dryRun }) {
4135
+ if (exit !== 0) {
4136
+ const suffix = prUrl ? ` \u2014 ${prUrl}` : "";
4137
+ return `\u26A0\uFE0F kody ${label} failed: ${truncate2(reason ?? "unknown error", 1500)}${suffix}`;
4138
+ }
4139
+ if (dryRun) {
4140
+ return `\u2139\uFE0F kody ${label} (dry-run): ${reason ?? "plan printed, no changes applied"}`;
4141
+ }
4142
+ if (prUrl) return `\u2705 kody ${label}: ${prUrl}`;
4143
+ return `\u2705 kody ${label} complete`;
4144
+ }
4145
+
4079
4146
  // src/scripts/parseAgentResult.ts
4080
4147
  var parseAgentResult2 = async (ctx, profile, agentResult) => {
4081
4148
  if (!agentResult) {
4082
4149
  ctx.data.agentDone = false;
4083
- ctx.data.action = makeAction("AGENT_NOT_RUN", { reason: "no agent result" });
4150
+ ctx.data.action = makeAction2("AGENT_NOT_RUN", { reason: "no agent result" });
4084
4151
  return;
4085
4152
  }
4086
4153
  const parsed = parseAgentResult(agentResult.finalText);
@@ -4095,17 +4162,17 @@ var parseAgentResult2 = async (ctx, profile, agentResult) => {
4095
4162
  ctx.data.agentError = agentResult.error;
4096
4163
  const modeSeg = (ctx.args.mode ?? profile.name).replace(/-/g, "_").toUpperCase();
4097
4164
  if (parsed.done) {
4098
- ctx.data.action = makeAction(`${modeSeg}_COMPLETED`, {
4165
+ ctx.data.action = makeAction2(`${modeSeg}_COMPLETED`, {
4099
4166
  commitMessage: parsed.commitMessage,
4100
4167
  prSummary: parsed.prSummary
4101
4168
  });
4102
4169
  } else {
4103
- ctx.data.action = makeAction(`${modeSeg}_FAILED`, {
4170
+ ctx.data.action = makeAction2(`${modeSeg}_FAILED`, {
4104
4171
  reason: parsed.failureReason || agentResult.error || "unknown failure"
4105
4172
  });
4106
4173
  }
4107
4174
  };
4108
- function makeAction(type, payload) {
4175
+ function makeAction2(type, payload) {
4109
4176
  return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
4110
4177
  }
4111
4178
 
@@ -4202,8 +4269,8 @@ var persistFlowState = async (ctx) => {
4202
4269
  };
4203
4270
 
4204
4271
  // src/scripts/postClassification.ts
4205
- import { execFileSync as execFileSync14 } from "child_process";
4206
- var API_TIMEOUT_MS6 = 3e4;
4272
+ import { execFileSync as execFileSync15 } from "child_process";
4273
+ var API_TIMEOUT_MS7 = 3e4;
4207
4274
  var VALID_CLASSES2 = /* @__PURE__ */ new Set(["feature", "bug", "spec", "chore"]);
4208
4275
  var postClassification = async (ctx) => {
4209
4276
  const issueNumber = ctx.args.issue;
@@ -4232,9 +4299,9 @@ var postClassification = async (ctx) => {
4232
4299
  ctx.cwd
4233
4300
  );
4234
4301
  try {
4235
- execFileSync14("gh", ["issue", "comment", String(issueNumber), "--body", `@kody ${classification}`], {
4302
+ execFileSync15("gh", ["issue", "comment", String(issueNumber), "--body", `@kody ${classification}`], {
4236
4303
  cwd: ctx.cwd,
4237
- timeout: API_TIMEOUT_MS6,
4304
+ timeout: API_TIMEOUT_MS7,
4238
4305
  stdio: ["ignore", "pipe", "pipe"]
4239
4306
  });
4240
4307
  } catch (err) {
@@ -4247,7 +4314,7 @@ var postClassification = async (ctx) => {
4247
4314
  ctx.output.reason = "classify: dispatch failed";
4248
4315
  return;
4249
4316
  }
4250
- ctx.data.action = makeAction2(`CLASSIFIED_AS_${classification.toUpperCase()}`, {
4317
+ ctx.data.action = makeAction3(`CLASSIFIED_AS_${classification.toUpperCase()}`, {
4251
4318
  classification,
4252
4319
  reason: reason ?? "",
4253
4320
  source: ctx.data.classificationSource ?? "agent"
@@ -4266,15 +4333,15 @@ function parseClassification(prSummary) {
4266
4333
  }
4267
4334
  function tryAuditComment(issueNumber, body, cwd) {
4268
4335
  try {
4269
- execFileSync14("gh", ["issue", "comment", String(issueNumber), "--body", body], {
4336
+ execFileSync15("gh", ["issue", "comment", String(issueNumber), "--body", body], {
4270
4337
  cwd,
4271
- timeout: API_TIMEOUT_MS6,
4338
+ timeout: API_TIMEOUT_MS7,
4272
4339
  stdio: ["ignore", "pipe", "pipe"]
4273
4340
  });
4274
4341
  } catch {
4275
4342
  }
4276
4343
  }
4277
- function makeAction2(type, payload) {
4344
+ function makeAction3(type, payload) {
4278
4345
  return { type, payload, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
4279
4346
  }
4280
4347
  function failedAction(reason) {
@@ -4449,385 +4516,21 @@ REVIEW_POSTED=https://github.com/${ctx.config.github.owner}/${ctx.config.github.
4449
4516
  );
4450
4517
  };
4451
4518
 
4452
- // src/scripts/releaseFlow.ts
4453
- import { execFileSync as execFileSync15, spawnSync } from "child_process";
4454
- import * as fs19 from "fs";
4455
- import * as path17 from "path";
4456
- function notifyIssue(issueNumber, body, cwd) {
4457
- if (!issueNumber || issueNumber <= 0) return;
4458
- try {
4459
- postIssueComment(issueNumber, body, cwd);
4460
- } catch {
4461
- }
4462
- }
4463
- function bumpVersion(current, bump) {
4464
- const m = current.match(/^(\d+)\.(\d+)\.(\d+)(.*)$/);
4465
- if (!m) throw new Error(`cannot parse version '${current}' (expected x.y.z[-suffix])`);
4466
- let [major, minor, patch] = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)];
4467
- if (bump === "major") {
4468
- major++;
4469
- minor = 0;
4470
- patch = 0;
4471
- } else if (bump === "minor") {
4472
- minor++;
4473
- patch = 0;
4474
- } else patch++;
4475
- return `${major}.${minor}.${patch}`;
4476
- }
4477
- function updateVersionInFile(file, newVersion, cwd) {
4478
- const abs = path17.join(cwd, file);
4479
- if (!fs19.existsSync(abs)) return false;
4480
- const content = fs19.readFileSync(abs, "utf-8");
4481
- const updated = content.replace(/"version"\s*:\s*"[^"]+"/, `"version": "${newVersion}"`);
4482
- if (updated === content) return false;
4483
- fs19.writeFileSync(abs, updated);
4484
- return true;
4485
- }
4486
- var FIRST_RELEASE_COMMIT_CAP = 100;
4487
- function generateChangelog(cwd, newVersion, lastTag) {
4488
- const logArgs = ["log", "--pretty=format:%s||%h", "--no-merges"];
4489
- if (lastTag) logArgs.splice(1, 0, `${lastTag}..HEAD`);
4490
- else logArgs.splice(1, 0, `-n${FIRST_RELEASE_COMMIT_CAP}`, "HEAD");
4491
- let log = "";
4492
- try {
4493
- log = execFileSync15("git", logArgs, {
4494
- cwd,
4495
- encoding: "utf-8",
4496
- stdio: ["ignore", "pipe", "pipe"]
4497
- }).trim();
4498
- } catch {
4499
- }
4500
- const commits = log.split("\n").filter((l) => l.length > 0).map((line) => {
4501
- const [subject, sha] = line.split("||");
4502
- return { subject: subject ?? "", sha: sha ?? "" };
4503
- }).filter((c) => !/^chore:\s*release\s+v\d/i.test(c.subject));
4504
- const groups = { feat: [], fix: [], perf: [], refactor: [], docs: [], chore: [], other: [] };
4505
- for (const c of commits) {
4506
- const m = c.subject.match(/^(\w+)(?:\(.*?\))?\s*:\s*(.+)$/);
4507
- const type = m?.[1]?.toLowerCase() ?? "other";
4508
- const msg = m?.[2] ?? c.subject;
4509
- const bucket = groups[type] ?? groups.other;
4510
- bucket.push(`- ${msg} (${c.sha})`);
4511
- }
4512
- const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4513
- const parts = [`## v${newVersion} \u2014 ${date}`, ""];
4514
- const labels = [
4515
- ["feat", "Features"],
4516
- ["fix", "Fixes"],
4517
- ["perf", "Performance"],
4518
- ["refactor", "Refactoring"],
4519
- ["docs", "Docs"],
4520
- ["chore", "Chores"],
4521
- ["other", "Other"]
4522
- ];
4523
- for (const [key, label] of labels) {
4524
- const items = groups[key];
4525
- if (!items || items.length === 0) continue;
4526
- parts.push(`### ${label}`);
4527
- parts.push(...items);
4528
- parts.push("");
4529
- }
4530
- if (parts.length === 2) parts.push("_No notable commits since the last release._", "");
4531
- return parts.join("\n");
4532
- }
4533
- function prependChangelog(cwd, entry) {
4534
- const p = path17.join(cwd, "CHANGELOG.md");
4535
- const header = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n";
4536
- if (fs19.existsSync(p)) {
4537
- const prior = fs19.readFileSync(p, "utf-8");
4538
- if (/^#\s*Changelog\b/m.test(prior)) {
4539
- const idx = prior.indexOf("\n", prior.indexOf("# Changelog"));
4540
- fs19.writeFileSync(p, `${prior.slice(0, idx + 1)}
4541
- ${entry}${prior.slice(idx + 1)}`);
4542
- } else {
4543
- fs19.writeFileSync(p, `${header}${entry}${prior}`);
4544
- }
4545
- } else {
4546
- fs19.writeFileSync(p, `${header}${entry}`);
4547
- }
4548
- }
4549
- function git3(args, cwd, timeout = 6e4) {
4550
- return execFileSync15("git", args, {
4551
- encoding: "utf-8",
4552
- timeout,
4553
- cwd,
4554
- env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
4555
- stdio: ["pipe", "pipe", "pipe"]
4556
- }).trim();
4557
- }
4558
- function lastReleaseTag(cwd) {
4559
- try {
4560
- return git3(["describe", "--tags", "--abbrev=0", "--match", "v*"], cwd);
4561
- } catch {
4562
- return null;
4563
- }
4564
- }
4565
- function remoteBranchExists(branch, cwd) {
4566
- try {
4567
- const out = git3(["ls-remote", "--heads", "origin", branch], cwd, 3e4);
4568
- return out.length > 0;
4569
- } catch {
4570
- return false;
4571
- }
4572
- }
4573
- function findOpenPrForBranch(branch, cwd) {
4574
- try {
4575
- const out = gh2(["pr", "list", "--head", branch, "--state", "open", "--json", "url", "--limit", "1"], { cwd });
4576
- const parsed = JSON.parse(out || "[]");
4577
- const first = parsed[0];
4578
- return first?.url ?? null;
4579
- } catch {
4580
- return null;
4581
- }
4582
- }
4583
- function runShell(cmd, cwd, timeoutMs) {
4584
- const r = spawnSync(cmd, {
4585
- cwd,
4586
- shell: true,
4587
- env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1", CI: process.env.CI ?? "1" },
4588
- encoding: "utf-8",
4589
- timeout: timeoutMs
4590
- });
4591
- return { exitCode: r.status ?? -1, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
4592
- }
4593
- var releaseFlow = async (ctx) => {
4594
- const mode = ctx.args.mode ?? "prepare";
4595
- const bump = ctx.args.bump ?? "patch";
4596
- const dryRun = ctx.args["dry-run"] === true || ctx.args.dryRun === true;
4597
- const prefer = ctx.args.prefer ?? void 0;
4598
- const issueNumber = typeof ctx.args.issue === "number" ? ctx.args.issue : void 0;
4599
- const cwd = ctx.cwd;
4600
- const releaseCfg = ctx.config.release ?? {};
4601
- const versionFiles = releaseCfg.versionFiles && releaseCfg.versionFiles.length > 0 ? releaseCfg.versionFiles : ["package.json"];
4602
- const timeoutMs = releaseCfg.timeoutMs ?? 6e5;
4603
- ctx.skipAgent = true;
4604
- if (mode === "prepare") {
4605
- await runPrepare({ cwd, bump, dryRun, prefer, versionFiles, ctx });
4606
- } else if (mode === "finalize") {
4607
- await runFinalize({ cwd, dryRun, timeoutMs, releaseCfg, ctx });
4608
- } else {
4609
- ctx.output.exitCode = 64;
4610
- ctx.output.reason = `release: unknown mode '${mode}'`;
4611
- }
4612
- notifyIssue(issueNumber, buildIssueNotice(mode, dryRun, ctx), cwd);
4519
+ // src/scripts/recordOutcome.ts
4520
+ var recordOutcome = async (ctx, profile) => {
4521
+ const seg = profile.name.replace(/-/g, "_").toUpperCase();
4522
+ const ok = (ctx.output.exitCode ?? 0) === 0;
4523
+ const action = {
4524
+ type: ok ? `${seg}_COMPLETED` : `${seg}_FAILED`,
4525
+ payload: {
4526
+ exitCode: ctx.output.exitCode ?? 0,
4527
+ reason: ctx.output.reason,
4528
+ prUrl: ctx.output.prUrl
4529
+ },
4530
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4531
+ };
4532
+ ctx.data.action = action;
4613
4533
  };
4614
- function buildIssueNotice(mode, dryRun, ctx) {
4615
- const exit = ctx.output.exitCode ?? 0;
4616
- const url = ctx.output.prUrl;
4617
- const reason = ctx.output.reason;
4618
- const label = mode === "finalize" ? "release finalize" : mode === "prepare" ? "release prepare" : `release ${mode}`;
4619
- if (exit !== 0) {
4620
- const suffix = url ? ` \u2014 ${url}` : "";
4621
- return `\u26A0\uFE0F kody ${label} failed: ${truncate2(reason ?? "unknown error", 1500)}${suffix}`;
4622
- }
4623
- if (dryRun) {
4624
- return `\u2139\uFE0F kody ${label} (dry-run): ${reason ?? "plan printed, no changes applied"}`;
4625
- }
4626
- if (mode === "prepare") {
4627
- return url ? `\u2705 kody release PR opened: ${url}` : "\u2705 kody release prepared";
4628
- }
4629
- if (mode === "finalize") {
4630
- return url ? `\u2705 kody release published: ${url}` : "\u2705 kody release finalized (tag pushed)";
4631
- }
4632
- return `\u2705 kody ${label} complete`;
4633
- }
4634
- async function runPrepare(args) {
4635
- const { cwd, bump, dryRun, prefer, versionFiles, ctx } = args;
4636
- const pkgPath = path17.join(cwd, "package.json");
4637
- if (!fs19.existsSync(pkgPath)) {
4638
- ctx.output.exitCode = 99;
4639
- ctx.output.reason = "release prepare: package.json not found";
4640
- return;
4641
- }
4642
- const pkg = JSON.parse(fs19.readFileSync(pkgPath, "utf-8"));
4643
- if (typeof pkg.version !== "string") {
4644
- ctx.output.exitCode = 99;
4645
- ctx.output.reason = "release prepare: package.json has no version";
4646
- return;
4647
- }
4648
- const oldVersion = pkg.version;
4649
- const newVersion = bumpVersion(oldVersion, bump);
4650
- const tag = `v${newVersion}`;
4651
- process.stdout.write(`\u2192 release prepare: ${oldVersion} \u2192 ${newVersion} (${bump})
4652
- `);
4653
- if (dryRun) {
4654
- ctx.output.exitCode = 0;
4655
- ctx.output.reason = `dry-run \u2014 would bump to ${newVersion}${prefer ? ` (--prefer ${prefer})` : ""}`;
4656
- process.stdout.write(`RELEASE_PLAN=bump=${newVersion} tag=${tag}
4657
- `);
4658
- return;
4659
- }
4660
- const releaseBranch = `release/${tag}`;
4661
- const collides = remoteBranchExists(releaseBranch, cwd);
4662
- if (collides) {
4663
- if (prefer === "theirs") {
4664
- const existingPr = findOpenPrForBranch(releaseBranch, cwd);
4665
- if (existingPr) {
4666
- process.stdout.write(` reusing existing PR (--prefer theirs): ${existingPr}
4667
- `);
4668
- ctx.output.prUrl = existingPr;
4669
- ctx.output.exitCode = 0;
4670
- return;
4671
- }
4672
- ctx.output.exitCode = 4;
4673
- ctx.output.reason = `release prepare --prefer theirs: ${releaseBranch} exists on remote but has no open PR \u2014 nothing to reuse`;
4674
- return;
4675
- }
4676
- if (prefer !== "ours") {
4677
- ctx.output.exitCode = 4;
4678
- ctx.output.reason = `release prepare: branch ${releaseBranch} already exists on remote. Use --prefer ours to force-push, or --prefer theirs to reuse the existing PR.`;
4679
- return;
4680
- }
4681
- process.stdout.write(` branch ${releaseBranch} exists on remote \u2014 will force-push (--prefer ours)
4682
- `);
4683
- }
4684
- const touched = [];
4685
- for (const f of versionFiles) {
4686
- if (updateVersionInFile(f, newVersion, cwd)) touched.push(f);
4687
- }
4688
- if (touched.length === 0) {
4689
- ctx.output.exitCode = 1;
4690
- ctx.output.reason = `release prepare: no version strings updated (files: ${versionFiles.join(", ")})`;
4691
- return;
4692
- }
4693
- process.stdout.write(` wrote ${touched.join(", ")}
4694
- `);
4695
- const entry = generateChangelog(cwd, newVersion, lastReleaseTag(cwd));
4696
- prependChangelog(cwd, entry);
4697
- process.stdout.write(` wrote CHANGELOG.md
4698
- `);
4699
- try {
4700
- git3(["checkout", "-b", releaseBranch], cwd);
4701
- for (const f of [...touched, "CHANGELOG.md"]) git3(["add", "--", f], cwd);
4702
- git3(["commit", "--no-gpg-sign", "-m", `chore: release ${tag}`], cwd);
4703
- const pushArgs = collides && prefer === "ours" ? ["push", "-u", "--force-with-lease", "origin", releaseBranch] : ["push", "-u", "origin", releaseBranch];
4704
- git3(pushArgs, cwd, 12e4);
4705
- } catch (err) {
4706
- const msg = err instanceof Error ? err.message : String(err);
4707
- ctx.output.exitCode = 4;
4708
- ctx.output.reason = `release prepare: git commit/push failed: ${msg}`;
4709
- return;
4710
- }
4711
- const base = ctx.config.git.defaultBranch;
4712
- const title = `chore: release ${tag}`;
4713
- const bodyMax = 6e4;
4714
- const rawEntry = entry.length > bodyMax ? `${entry.slice(0, bodyMax)}
4715
-
4716
- _\u2026 truncated; see CHANGELOG.md_` : entry;
4717
- const body = `Automated release PR opened by kody.
4718
-
4719
- ${rawEntry}
4720
-
4721
- Merge this and then run \`kody release --mode finalize\`.`;
4722
- let prUrl = "";
4723
- const preexistingPr = collides && prefer === "ours" ? findOpenPrForBranch(releaseBranch, cwd) : null;
4724
- if (preexistingPr) {
4725
- process.stdout.write(` PR already open for ${releaseBranch}: ${preexistingPr}
4726
- `);
4727
- prUrl = preexistingPr;
4728
- } else {
4729
- try {
4730
- prUrl = gh2(["pr", "create", "--head", releaseBranch, "--base", base, "--title", title, "--body-file", "-"], {
4731
- input: body,
4732
- cwd
4733
- }).trim();
4734
- } catch (err) {
4735
- const msg = err instanceof Error ? err.message : String(err);
4736
- ctx.output.exitCode = 4;
4737
- ctx.output.reason = `release prepare: gh pr create failed: ${msg}`;
4738
- return;
4739
- }
4740
- }
4741
- ctx.output.prUrl = prUrl;
4742
- ctx.output.exitCode = 0;
4743
- process.stdout.write(`RELEASE_PR=${prUrl}
4744
- `);
4745
- }
4746
- async function runFinalize(args) {
4747
- const { cwd, dryRun, timeoutMs, releaseCfg, ctx } = args;
4748
- const pkgPath = path17.join(cwd, "package.json");
4749
- const pkg = JSON.parse(fs19.readFileSync(pkgPath, "utf-8"));
4750
- if (typeof pkg.version !== "string") {
4751
- ctx.output.exitCode = 99;
4752
- ctx.output.reason = "release finalize: package.json has no version";
4753
- return;
4754
- }
4755
- const version = pkg.version;
4756
- const tag = `v${version}`;
4757
- process.stdout.write(`\u2192 release finalize: ${tag}
4758
- `);
4759
- try {
4760
- git3(["rev-parse", "--verify", tag], cwd);
4761
- ctx.output.exitCode = 1;
4762
- ctx.output.reason = `release finalize: tag ${tag} already exists`;
4763
- return;
4764
- } catch {
4765
- }
4766
- if (dryRun) {
4767
- ctx.output.exitCode = 0;
4768
- ctx.output.reason = `dry-run \u2014 would tag + publish ${tag}`;
4769
- return;
4770
- }
4771
- if (releaseCfg.e2eCommand && releaseCfg.e2eCommand.trim().length > 0) {
4772
- const cmd = releaseCfg.e2eCommand.replace(/\$VERSION/g, version);
4773
- process.stdout.write(` E2E gate: ${cmd}
4774
- `);
4775
- const r = runShell(cmd, cwd, timeoutMs);
4776
- if (r.exitCode !== 0) {
4777
- ctx.output.exitCode = 2;
4778
- ctx.output.reason = `release finalize: E2E gate failed (exit ${r.exitCode}): ${truncate2(r.stderr, 600)}`;
4779
- return;
4780
- }
4781
- }
4782
- try {
4783
- git3(["tag", "-a", tag, "-m", `Release ${tag}`], cwd);
4784
- git3(["push", "origin", tag], cwd, 12e4);
4785
- } catch (err) {
4786
- const msg = err instanceof Error ? err.message : String(err);
4787
- ctx.output.exitCode = 4;
4788
- ctx.output.reason = `release finalize: tag/push failed: ${msg}`;
4789
- return;
4790
- }
4791
- let publishStatus = "skipped";
4792
- if (releaseCfg.publishCommand && releaseCfg.publishCommand.trim().length > 0) {
4793
- const cmd = releaseCfg.publishCommand.replace(/\$VERSION/g, version);
4794
- process.stdout.write(` publish: ${cmd}
4795
- `);
4796
- const r = runShell(cmd, cwd, timeoutMs);
4797
- publishStatus = r.exitCode === 0 ? "ok" : "failed";
4798
- if (r.exitCode !== 0) {
4799
- process.stderr.write(`[kody release] publishCommand exit ${r.exitCode}
4800
- ${truncate2(r.stderr, 2e3)}
4801
- `);
4802
- }
4803
- }
4804
- let releaseUrl = "";
4805
- try {
4806
- const releaseArgs = ["release", "create", tag, "--title", tag, "--notes", `Release ${tag} \u2014 automated by kody.`];
4807
- if (releaseCfg.draftRelease) releaseArgs.push("--draft");
4808
- releaseUrl = gh2(releaseArgs, { cwd }).trim();
4809
- } catch (err) {
4810
- process.stderr.write(
4811
- `[kody release] gh release create failed: ${err instanceof Error ? err.message : String(err)}
4812
- `
4813
- );
4814
- }
4815
- if (releaseCfg.notifyCommand && releaseCfg.notifyCommand.trim().length > 0) {
4816
- const cmd = releaseCfg.notifyCommand.replace(/\$VERSION/g, version);
4817
- runShell(cmd, cwd, timeoutMs);
4818
- }
4819
- if (releaseUrl) ctx.output.prUrl = releaseUrl;
4820
- if (publishStatus === "failed") {
4821
- ctx.output.exitCode = 1;
4822
- ctx.output.reason = `release finalize: tag + gh release created, but publishCommand failed`;
4823
- return;
4824
- }
4825
- ctx.output.exitCode = 0;
4826
- process.stdout.write(`RELEASE_TAG=${tag}
4827
- `);
4828
- if (releaseUrl) process.stdout.write(`RELEASE_URL=${releaseUrl}
4829
- `);
4830
- }
4831
4534
 
4832
4535
  // src/scripts/requireFeedbackActions.ts
4833
4536
  var MIN_ITEMS = 1;
@@ -5137,6 +4840,16 @@ function synthesizeAction(ctx) {
5137
4840
  };
5138
4841
  }
5139
4842
 
4843
+ // src/scripts/setCommentTarget.ts
4844
+ var setCommentTarget = async (ctx, _profile, args) => {
4845
+ const type = args?.type ?? "issue";
4846
+ const argName = type === "pr" ? "pr" : "issue";
4847
+ const num = ctx.args[argName];
4848
+ if (typeof num !== "number" || num <= 0) return;
4849
+ ctx.data.commentTargetType = type;
4850
+ ctx.data.commentTargetNumber = num;
4851
+ };
4852
+
5140
4853
  // src/scripts/setLifecycleLabel.ts
5141
4854
  var setLifecycleLabel = async (ctx, _profile, args) => {
5142
4855
  const label = args?.label;
@@ -5188,7 +4901,7 @@ var stageMergeConflicts = async (ctx) => {
5188
4901
 
5189
4902
  // src/scripts/startFlow.ts
5190
4903
  import { execFileSync as execFileSync18 } from "child_process";
5191
- var API_TIMEOUT_MS7 = 3e4;
4904
+ var API_TIMEOUT_MS8 = 3e4;
5192
4905
  var startFlow = async (ctx, profile, _agentResult, args) => {
5193
4906
  const entry = args?.entry;
5194
4907
  if (!entry) {
@@ -5222,7 +4935,7 @@ function postKodyComment(target, issueNumber, state, next, cwd) {
5222
4935
  const body = `@kody ${next}`;
5223
4936
  try {
5224
4937
  execFileSync18("gh", [sub, "comment", String(targetNumber), "--body", body], {
5225
- timeout: API_TIMEOUT_MS7,
4938
+ timeout: API_TIMEOUT_MS8,
5226
4939
  cwd,
5227
4940
  stdio: ["ignore", "pipe", "pipe"]
5228
4941
  });
@@ -5508,7 +5221,7 @@ var writeIssueStateComment = async (ctx, _profile, _agentResult, args) => {
5508
5221
  };
5509
5222
 
5510
5223
  // src/scripts/writeRunSummary.ts
5511
- import * as fs20 from "fs";
5224
+ import * as fs19 from "fs";
5512
5225
  var writeRunSummary = async (ctx, profile) => {
5513
5226
  const summaryPath = process.env.GITHUB_STEP_SUMMARY;
5514
5227
  if (!summaryPath) return;
@@ -5530,7 +5243,7 @@ var writeRunSummary = async (ctx, profile) => {
5530
5243
  if (reason) lines.push(`- **Reason:** ${reason}`);
5531
5244
  lines.push("");
5532
5245
  try {
5533
- fs20.appendFileSync(summaryPath, `${lines.join("\n")}
5246
+ fs19.appendFileSync(summaryPath, `${lines.join("\n")}
5534
5247
  `);
5535
5248
  } catch {
5536
5249
  }
@@ -5545,7 +5258,6 @@ var preflightScripts = {
5545
5258
  reviewFlow,
5546
5259
  syncFlow,
5547
5260
  initFlow,
5548
- releaseFlow,
5549
5261
  watchStalePrsFlow,
5550
5262
  loadTaskState,
5551
5263
  loadIssueContext,
@@ -5559,6 +5271,7 @@ var preflightScripts = {
5559
5271
  discoverQaContext,
5560
5272
  resolvePreviewUrl,
5561
5273
  composePrompt,
5274
+ setCommentTarget,
5562
5275
  setLifecycleLabel,
5563
5276
  skipAgent,
5564
5277
  classifyByLabel,
@@ -5590,7 +5303,10 @@ var postflightScripts = {
5590
5303
  finishFlow,
5591
5304
  advanceFlow,
5592
5305
  persistFlowState,
5593
- postClassification
5306
+ postClassification,
5307
+ notifyTerminal,
5308
+ recordOutcome,
5309
+ mergeReleasePr
5594
5310
  };
5595
5311
  var allScriptNames = /* @__PURE__ */ new Set([
5596
5312
  ...Object.keys(preflightScripts),
@@ -5614,22 +5330,22 @@ function firstRequiredFailure(results, tools) {
5614
5330
  }
5615
5331
  function verifyOne(tool, cwd) {
5616
5332
  const result = { name: tool.name, present: false, verified: false };
5617
- let present = runShell2(tool.install.checkCommand, cwd);
5333
+ let present = runShell(tool.install.checkCommand, cwd);
5618
5334
  if (!present && tool.install.installCommand) {
5619
- runShell2(tool.install.installCommand, cwd, 12e4);
5620
- present = runShell2(tool.install.checkCommand, cwd);
5335
+ runShell(tool.install.installCommand, cwd, 12e4);
5336
+ present = runShell(tool.install.checkCommand, cwd);
5621
5337
  }
5622
5338
  result.present = present;
5623
5339
  if (!present) {
5624
5340
  result.error = `tool "${tool.name}" not on PATH (check: ${tool.install.checkCommand})`;
5625
5341
  return result;
5626
5342
  }
5627
- const verified = runShell2(tool.verify, cwd);
5343
+ const verified = runShell(tool.verify, cwd);
5628
5344
  result.verified = verified;
5629
5345
  if (!verified) result.error = `tool "${tool.name}" failed verify: ${tool.verify}`;
5630
5346
  return result;
5631
5347
  }
5632
- function runShell2(cmd, cwd, timeoutMs = 3e4) {
5348
+ function runShell(cmd, cwd, timeoutMs = 3e4) {
5633
5349
  try {
5634
5350
  execFileSync20("sh", ["-c", cmd], { cwd, stdio: "pipe", timeout: timeoutMs });
5635
5351
  return true;
@@ -5699,9 +5415,9 @@ async function runExecutable(profileName, input) {
5699
5415
  data: {},
5700
5416
  output: { exitCode: 0 }
5701
5417
  };
5702
- const ndjsonDir = path18.join(input.cwd, ".kody");
5418
+ const ndjsonDir = path17.join(input.cwd, ".kody");
5703
5419
  const invokeAgent = async (prompt) => {
5704
- const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path18.isAbsolute(p) ? p : path18.resolve(profile.dir, p)).filter((p) => p.length > 0);
5420
+ const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path17.isAbsolute(p) ? p : path17.resolve(profile.dir, p)).filter((p) => p.length > 0);
5705
5421
  const syntheticPath = ctx.data.syntheticPluginPath;
5706
5422
  const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
5707
5423
  return runAgent({
@@ -5777,17 +5493,17 @@ async function runExecutable(profileName, input) {
5777
5493
  }
5778
5494
  }
5779
5495
  function resolveProfilePath(profileName) {
5780
- const here = path18.dirname(new URL(import.meta.url).pathname);
5496
+ const here = path17.dirname(new URL(import.meta.url).pathname);
5781
5497
  const candidates = [
5782
- path18.join(here, "executables", profileName, "profile.json"),
5498
+ path17.join(here, "executables", profileName, "profile.json"),
5783
5499
  // same-dir sibling (dev)
5784
- path18.join(here, "..", "executables", profileName, "profile.json"),
5500
+ path17.join(here, "..", "executables", profileName, "profile.json"),
5785
5501
  // up one (prod: dist/bin → dist/executables)
5786
- path18.join(here, "..", "src", "executables", profileName, "profile.json")
5502
+ path17.join(here, "..", "src", "executables", profileName, "profile.json")
5787
5503
  // fallback
5788
5504
  ];
5789
5505
  for (const c of candidates) {
5790
- if (fs21.existsSync(c)) return c;
5506
+ if (fs20.existsSync(c)) return c;
5791
5507
  }
5792
5508
  return candidates[0];
5793
5509
  }
@@ -5880,8 +5596,8 @@ function finish(out) {
5880
5596
  var SHELL_TIMEOUT_MS = 3e5;
5881
5597
  function runShellEntry(entry, ctx, profile) {
5882
5598
  const shellName = entry.shell;
5883
- const shellPath = path18.join(profile.dir, shellName);
5884
- if (!fs21.existsSync(shellPath)) {
5599
+ const shellPath = path17.join(profile.dir, shellName);
5600
+ if (!fs20.existsSync(shellPath)) {
5885
5601
  ctx.skipAgent = true;
5886
5602
  ctx.output.exitCode = 99;
5887
5603
  ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
@@ -5891,9 +5607,12 @@ function runShellEntry(entry, ctx, profile) {
5891
5607
  const env = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
5892
5608
  for (const [k, v] of Object.entries(ctx.args)) {
5893
5609
  if (v === void 0 || v === null) continue;
5894
- env[`KODY_ARG_${k.toUpperCase().replace(/-/g, "_")}`] = String(v);
5610
+ env[`KODY_ARG_${envKey(k)}`] = String(v);
5611
+ }
5612
+ for (const [k, v] of flattenConfig(ctx.config)) {
5613
+ env[`KODY_CFG_${k}`] = v;
5895
5614
  }
5896
- const r = spawnSync2("bash", [shellPath, ...positional], {
5615
+ const r = spawnSync("bash", [shellPath, ...positional], {
5897
5616
  cwd: ctx.cwd,
5898
5617
  encoding: "utf-8",
5899
5618
  env,
@@ -5908,6 +5627,10 @@ function runShellEntry(entry, ctx, profile) {
5908
5627
  ctx.skipAgent = true;
5909
5628
  if (ctx.output.exitCode === void 0) ctx.output.exitCode = 0;
5910
5629
  }
5630
+ const prUrlMatch = stdout.match(/^KODY_PR_URL=(.+)$/m);
5631
+ if (prUrlMatch?.[1]) ctx.output.prUrl = prUrlMatch[1].trim();
5632
+ const reasonMatch = stdout.match(/^KODY_REASON=(.+)$/m);
5633
+ if (reasonMatch?.[1]) ctx.output.reason = reasonMatch[1].trim();
5911
5634
  const exit = r.status ?? -1;
5912
5635
  if (exit !== 0) {
5913
5636
  ctx.skipAgent = true;
@@ -5920,6 +5643,24 @@ function runShellEntry(entry, ctx, profile) {
5920
5643
  }
5921
5644
  }
5922
5645
  }
5646
+ function envKey(name) {
5647
+ return name.toUpperCase().replace(/-/g, "_");
5648
+ }
5649
+ function flattenConfig(obj, prefix = "") {
5650
+ const out = [];
5651
+ for (const [k, v] of Object.entries(obj)) {
5652
+ if (v === null || v === void 0) continue;
5653
+ const key = prefix ? `${prefix}_${envKey(k)}` : envKey(k);
5654
+ if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
5655
+ out.push([key, String(v)]);
5656
+ } else if (Array.isArray(v)) {
5657
+ out.push([key, JSON.stringify(v)]);
5658
+ } else if (typeof v === "object") {
5659
+ out.push(...flattenConfig(v, key));
5660
+ }
5661
+ }
5662
+ return out;
5663
+ }
5923
5664
 
5924
5665
  // src/kody-cli.ts
5925
5666
  var CI_HELP = `kody ci \u2014 minimal-YAML autonomous engineer (CI preflight + run)
@@ -6006,9 +5747,9 @@ function resolveAuthToken(env = process.env) {
6006
5747
  return token;
6007
5748
  }
6008
5749
  function detectPackageManager2(cwd) {
6009
- if (fs22.existsSync(path19.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
6010
- if (fs22.existsSync(path19.join(cwd, "yarn.lock"))) return "yarn";
6011
- if (fs22.existsSync(path19.join(cwd, "bun.lockb"))) return "bun";
5750
+ if (fs21.existsSync(path18.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
5751
+ if (fs21.existsSync(path18.join(cwd, "yarn.lock"))) return "yarn";
5752
+ if (fs21.existsSync(path18.join(cwd, "bun.lockb"))) return "bun";
6012
5753
  return "npm";
6013
5754
  }
6014
5755
  function shellOut(cmd, args, cwd, stream = true) {
@@ -6088,11 +5829,11 @@ function configureGitIdentity(cwd) {
6088
5829
  }
6089
5830
  function postFailureTail(issueNumber, cwd, reason) {
6090
5831
  if (!issueNumber) return;
6091
- const logPath = path19.join(cwd, ".kody", "last-run.jsonl");
5832
+ const logPath = path18.join(cwd, ".kody", "last-run.jsonl");
6092
5833
  let tail = "";
6093
5834
  try {
6094
- if (fs22.existsSync(logPath)) {
6095
- const content = fs22.readFileSync(logPath, "utf-8");
5835
+ if (fs21.existsSync(logPath)) {
5836
+ const content = fs21.readFileSync(logPath, "utf-8");
6096
5837
  tail = content.slice(-3e3);
6097
5838
  }
6098
5839
  } catch {
@@ -6117,7 +5858,7 @@ async function runCi(argv) {
6117
5858
  return 0;
6118
5859
  }
6119
5860
  const args = parseCiArgs(argv);
6120
- const cwd = args.cwd ? path19.resolve(args.cwd) : process.cwd();
5861
+ const cwd = args.cwd ? path18.resolve(args.cwd) : process.cwd();
6121
5862
  let earlyConfig;
6122
5863
  try {
6123
5864
  earlyConfig = loadConfig(cwd);
@@ -6255,9 +5996,9 @@ function parseChatArgs(argv, env = process.env) {
6255
5996
  return result;
6256
5997
  }
6257
5998
  function commitChatFiles(cwd, sessionId, verbose) {
6258
- const sessionFile = path20.relative(cwd, sessionFilePath(cwd, sessionId));
6259
- const eventsFile = path20.relative(cwd, eventsFilePath(cwd, sessionId));
6260
- const paths = [sessionFile, eventsFile].filter((p) => fs23.existsSync(path20.join(cwd, p)));
5999
+ const sessionFile = path19.relative(cwd, sessionFilePath(cwd, sessionId));
6000
+ const eventsFile = path19.relative(cwd, eventsFilePath(cwd, sessionId));
6001
+ const paths = [sessionFile, eventsFile].filter((p) => fs22.existsSync(path19.join(cwd, p)));
6261
6002
  if (paths.length === 0) return;
6262
6003
  const opts = { cwd, stdio: verbose ? "inherit" : "pipe" };
6263
6004
  try {
@@ -6295,7 +6036,7 @@ async function runChat(argv) {
6295
6036
  ${CHAT_HELP}`);
6296
6037
  return 64;
6297
6038
  }
6298
- const cwd = args.cwd ? path20.resolve(args.cwd) : process.cwd();
6039
+ const cwd = args.cwd ? path19.resolve(args.cwd) : process.cwd();
6299
6040
  const sessionId = args.sessionId;
6300
6041
  const unpackedSecrets = unpackAllSecrets();
6301
6042
  if (unpackedSecrets > 0) {