@kody-ade/kody-engine 0.2.17 → 0.2.19

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 (2) hide show
  1. package/dist/bin/kody2.js +62 -32
  2. package/package.json +1 -1
package/dist/bin/kody2.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.2.17",
6
+ version: "0.2.19",
7
7
  description: "kody2 \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
8
8
  license: "MIT",
9
9
  type: "module",
@@ -1619,15 +1619,15 @@ function gh2(args, cwd) {
1619
1619
  stdio: ["ignore", "pipe", "pipe"]
1620
1620
  }).trim();
1621
1621
  }
1622
- function getLatestFailedRunForPr(prNumber, cwd) {
1622
+ function getRecentFailedRunsForPr(prNumber, limit, cwd) {
1623
1623
  let headBranch;
1624
1624
  try {
1625
1625
  const out = gh2(["pr", "view", String(prNumber), "--json", "headRefName"], cwd);
1626
1626
  headBranch = JSON.parse(out).headRefName;
1627
1627
  } catch {
1628
- return null;
1628
+ return [];
1629
1629
  }
1630
- if (!headBranch) return null;
1630
+ if (!headBranch) return [];
1631
1631
  try {
1632
1632
  const out = gh2(
1633
1633
  [
@@ -1638,25 +1638,24 @@ function getLatestFailedRunForPr(prNumber, cwd) {
1638
1638
  "--status",
1639
1639
  "failure",
1640
1640
  "--limit",
1641
- "1",
1641
+ String(Math.max(1, limit)),
1642
1642
  "--json",
1643
1643
  "databaseId,workflowName,headBranch,conclusion,url,createdAt"
1644
1644
  ],
1645
1645
  cwd
1646
1646
  );
1647
1647
  const parsed = JSON.parse(out);
1648
- if (!Array.isArray(parsed) || parsed.length === 0) return null;
1649
- const r = parsed[0];
1650
- return {
1648
+ if (!Array.isArray(parsed)) return [];
1649
+ return parsed.map((r) => ({
1651
1650
  id: String(r.databaseId ?? ""),
1652
1651
  workflowName: r.workflowName ?? "",
1653
1652
  headBranch: r.headBranch ?? headBranch,
1654
1653
  conclusion: r.conclusion ?? "failure",
1655
1654
  url: r.url ?? "",
1656
1655
  createdAt: r.createdAt ?? ""
1657
- };
1656
+ }));
1658
1657
  } catch {
1659
- return null;
1658
+ return [];
1660
1659
  }
1661
1660
  }
1662
1661
  function getFailedRunLogTail(runId, maxBytes, cwd) {
@@ -1668,16 +1667,27 @@ function getFailedRunLogTail(runId, maxBytes, cwd) {
1668
1667
  return "";
1669
1668
  }
1670
1669
  }
1670
+ function isKody2DispatchWorkflow(workflowName) {
1671
+ return workflowName.trim().toLowerCase() === "kody2";
1672
+ }
1673
+ function pickFailedRunForFixCi(prNumber, maxBytes, limit, cwd) {
1674
+ const runs = getRecentFailedRunsForPr(prNumber, limit, cwd);
1675
+ for (const run of runs) {
1676
+ if (isKody2DispatchWorkflow(run.workflowName)) continue;
1677
+ const logTail = getFailedRunLogTail(run.id, maxBytes, cwd);
1678
+ if (logTail) return { run, logTail };
1679
+ }
1680
+ return null;
1681
+ }
1671
1682
 
1672
1683
  // src/scripts/fixCiFlow.ts
1673
1684
  var LOG_MAX_BYTES = 3e4;
1685
+ var RUN_LOOKBACK = 20;
1674
1686
  var fixCiFlow = async (ctx) => {
1675
1687
  const prNumber = ctx.args.pr;
1676
1688
  const pr = getPr(prNumber, ctx.cwd);
1677
1689
  if (pr.state !== "OPEN") {
1678
- ctx.output.exitCode = 1;
1679
- ctx.output.reason = `PR #${prNumber} is not OPEN (state: ${pr.state})`;
1680
- ctx.skipAgent = true;
1690
+ bail(ctx, prNumber, `PR #${prNumber} is not OPEN (state: ${pr.state})`);
1681
1691
  return;
1682
1692
  }
1683
1693
  ctx.data.pr = pr;
@@ -1685,27 +1695,36 @@ var fixCiFlow = async (ctx) => {
1685
1695
  ctx.data.commentTargetNumber = prNumber;
1686
1696
  checkoutPrBranch(prNumber, ctx.cwd);
1687
1697
  ctx.data.branch = getCurrentBranch(ctx.cwd);
1688
- let runId = ctx.args.runId;
1698
+ const explicitRunId = ctx.args.runId;
1699
+ let runId;
1689
1700
  let workflowName = "";
1690
1701
  let failedRunUrl = "";
1691
- if (!runId) {
1692
- const run = getLatestFailedRunForPr(prNumber, ctx.cwd);
1693
- if (!run) {
1694
- ctx.output.exitCode = 1;
1695
- ctx.output.reason = `no failed workflow run found on PR #${prNumber}'s branch`;
1696
- ctx.skipAgent = true;
1702
+ let logTail = "";
1703
+ if (explicitRunId) {
1704
+ runId = explicitRunId;
1705
+ logTail = getFailedRunLogTail(runId, LOG_MAX_BYTES, ctx.cwd);
1706
+ if (!logTail) {
1707
+ bail(
1708
+ ctx,
1709
+ prNumber,
1710
+ `failed to fetch log tail for run ${runId} (logs may be expired, the run may have no failed steps, or the run belongs to a workflow whose logs aren't accessible)`
1711
+ );
1697
1712
  return;
1698
1713
  }
1699
- runId = run.id;
1700
- workflowName = run.workflowName;
1701
- failedRunUrl = run.url;
1702
- }
1703
- const logTail = getFailedRunLogTail(runId, LOG_MAX_BYTES, ctx.cwd);
1704
- if (!logTail) {
1705
- ctx.output.exitCode = 1;
1706
- ctx.output.reason = `failed to fetch log tail for run ${runId}`;
1707
- ctx.skipAgent = true;
1708
- return;
1714
+ } else {
1715
+ const picked = pickFailedRunForFixCi(prNumber, LOG_MAX_BYTES, RUN_LOOKBACK, ctx.cwd);
1716
+ if (!picked) {
1717
+ bail(
1718
+ ctx,
1719
+ prNumber,
1720
+ `no actionable failed workflow run found on PR #${prNumber}'s branch (looked at last ${RUN_LOOKBACK} failed runs \u2014 all were either kody2's own dispatch workflow or had no fetchable logs; pass --run-id to target a specific run)`
1721
+ );
1722
+ return;
1723
+ }
1724
+ runId = picked.run.id;
1725
+ workflowName = picked.run.workflowName;
1726
+ failedRunUrl = picked.run.url;
1727
+ logTail = picked.logTail;
1709
1728
  }
1710
1729
  ctx.data.failedRunId = runId;
1711
1730
  ctx.data.failedWorkflowName = workflowName;
@@ -1720,6 +1739,14 @@ var fixCiFlow = async (ctx) => {
1720
1739
  ctx.cwd
1721
1740
  );
1722
1741
  };
1742
+ function bail(ctx, prNumber, reason) {
1743
+ ctx.output.exitCode = 1;
1744
+ ctx.output.reason = reason;
1745
+ ctx.skipAgent = true;
1746
+ const runUrl = getRunUrl();
1747
+ const runSuffix = runUrl ? ` ([logs](${runUrl}))` : "";
1748
+ tryPostPr(prNumber, `\u274C kody2 fix-ci could not run${runSuffix}: ${reason}`, ctx.cwd);
1749
+ }
1723
1750
  function tryPostPr(prNumber, body, cwd) {
1724
1751
  try {
1725
1752
  postPrReviewComment(prNumber, body, cwd);
@@ -3621,11 +3648,14 @@ function configureGitIdentity(cwd) {
3621
3648
  } catch {
3622
3649
  }
3623
3650
  try {
3624
- execFileSync14("git", ["config", "user.name", "kody2-bot"], { cwd, stdio: "pipe" });
3651
+ execFileSync14("git", ["config", "user.name", "github-actions[bot]"], { cwd, stdio: "pipe" });
3625
3652
  } catch {
3626
3653
  }
3627
3654
  try {
3628
- execFileSync14("git", ["config", "user.email", "kody2-bot@users.noreply.github.com"], { cwd, stdio: "pipe" });
3655
+ execFileSync14("git", ["config", "user.email", "41898282+github-actions[bot]@users.noreply.github.com"], {
3656
+ cwd,
3657
+ stdio: "pipe"
3658
+ });
3629
3659
  } catch {
3630
3660
  }
3631
3661
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "kody2 — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",