@kody-ade/kody-engine 0.4.132 → 0.4.133
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 +132 -3
- package/dist/executables/merge/profile.json +54 -0
- package/package.json +1 -1
package/dist/bin/kody.js
CHANGED
|
@@ -880,7 +880,7 @@ var init_loadPriorArt = __esm({
|
|
|
880
880
|
// package.json
|
|
881
881
|
var package_default = {
|
|
882
882
|
name: "@kody-ade/kody-engine",
|
|
883
|
-
version: "0.4.
|
|
883
|
+
version: "0.4.133",
|
|
884
884
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
885
885
|
license: "MIT",
|
|
886
886
|
type: "module",
|
|
@@ -5736,6 +5736,14 @@ function closePr(prNumber, comment, cwd) {
|
|
|
5736
5736
|
return fail(err);
|
|
5737
5737
|
}
|
|
5738
5738
|
}
|
|
5739
|
+
function mergePrSquash(prNumber, cwd) {
|
|
5740
|
+
try {
|
|
5741
|
+
gh(["pr", "merge", String(prNumber), "--squash", "--delete-branch"], { cwd });
|
|
5742
|
+
return { ok: true };
|
|
5743
|
+
} catch (err) {
|
|
5744
|
+
return fail(err);
|
|
5745
|
+
}
|
|
5746
|
+
}
|
|
5739
5747
|
function editPrBase(prNumber, baseBranch, cwd) {
|
|
5740
5748
|
try {
|
|
5741
5749
|
gh(
|
|
@@ -8831,6 +8839,122 @@ var markFlowSuccess = async (ctx) => {
|
|
|
8831
8839
|
}
|
|
8832
8840
|
};
|
|
8833
8841
|
|
|
8842
|
+
// src/scripts/mergeFlow.ts
|
|
8843
|
+
init_issue();
|
|
8844
|
+
function readPr(prNumber, cwd) {
|
|
8845
|
+
const out = gh(
|
|
8846
|
+
[
|
|
8847
|
+
"pr",
|
|
8848
|
+
"view",
|
|
8849
|
+
String(prNumber),
|
|
8850
|
+
"--json",
|
|
8851
|
+
"state,isDraft,mergeable,mergeStateStatus,title,url"
|
|
8852
|
+
],
|
|
8853
|
+
{ cwd }
|
|
8854
|
+
);
|
|
8855
|
+
const p = JSON.parse(out);
|
|
8856
|
+
return {
|
|
8857
|
+
state: p.state ?? "UNKNOWN",
|
|
8858
|
+
isDraft: p.isDraft ?? false,
|
|
8859
|
+
mergeable: p.mergeable ?? "UNKNOWN",
|
|
8860
|
+
mergeStateStatus: p.mergeStateStatus ?? "UNKNOWN",
|
|
8861
|
+
title: p.title ?? "",
|
|
8862
|
+
url: p.url ?? ""
|
|
8863
|
+
};
|
|
8864
|
+
}
|
|
8865
|
+
function evaluateMergeGate(pr) {
|
|
8866
|
+
if (pr.state !== "OPEN") {
|
|
8867
|
+
return {
|
|
8868
|
+
ok: false,
|
|
8869
|
+
action: "MERGE_SKIPPED",
|
|
8870
|
+
reason: `PR is ${pr.state.toLowerCase()}, not open \u2014 nothing to merge.`
|
|
8871
|
+
};
|
|
8872
|
+
}
|
|
8873
|
+
if (pr.isDraft) {
|
|
8874
|
+
return { ok: false, action: "MERGE_BLOCKED", reason: "PR is still a draft." };
|
|
8875
|
+
}
|
|
8876
|
+
if (pr.mergeable === "CONFLICTING" || pr.mergeStateStatus === "DIRTY") {
|
|
8877
|
+
return {
|
|
8878
|
+
ok: false,
|
|
8879
|
+
action: "MERGE_BLOCKED",
|
|
8880
|
+
reason: "PR has conflicts with its base branch \u2014 resolve them first."
|
|
8881
|
+
};
|
|
8882
|
+
}
|
|
8883
|
+
if (pr.mergeable === "UNKNOWN" || pr.mergeStateStatus === "UNKNOWN") {
|
|
8884
|
+
return {
|
|
8885
|
+
ok: false,
|
|
8886
|
+
action: "MERGE_BLOCKED",
|
|
8887
|
+
reason: "GitHub is still computing mergeability \u2014 will retry next tick."
|
|
8888
|
+
};
|
|
8889
|
+
}
|
|
8890
|
+
if (pr.mergeStateStatus === "BEHIND") {
|
|
8891
|
+
return {
|
|
8892
|
+
ok: false,
|
|
8893
|
+
action: "MERGE_BLOCKED",
|
|
8894
|
+
reason: "PR branch is behind its base \u2014 update it before merging."
|
|
8895
|
+
};
|
|
8896
|
+
}
|
|
8897
|
+
if (pr.mergeStateStatus !== "CLEAN") {
|
|
8898
|
+
return {
|
|
8899
|
+
ok: false,
|
|
8900
|
+
action: "MERGE_BLOCKED",
|
|
8901
|
+
reason: `PR is not green (status: ${pr.mergeStateStatus}) \u2014 required checks or reviews are not satisfied.`
|
|
8902
|
+
};
|
|
8903
|
+
}
|
|
8904
|
+
return { ok: true };
|
|
8905
|
+
}
|
|
8906
|
+
var mergeFlow = async (ctx) => {
|
|
8907
|
+
ctx.skipAgent = true;
|
|
8908
|
+
const prNumber = Number(ctx.args.pr);
|
|
8909
|
+
if (!Number.isInteger(prNumber) || prNumber <= 0) {
|
|
8910
|
+
process.stderr.write(`[merge] invalid --pr value: ${String(ctx.args.pr)}
|
|
8911
|
+
`);
|
|
8912
|
+
ctx.data.mergeAction = "MERGE_BLOCKED";
|
|
8913
|
+
return;
|
|
8914
|
+
}
|
|
8915
|
+
let pr;
|
|
8916
|
+
try {
|
|
8917
|
+
pr = readPr(prNumber, ctx.cwd);
|
|
8918
|
+
} catch (err) {
|
|
8919
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8920
|
+
process.stderr.write(`[merge] could not read PR #${prNumber}: ${msg}
|
|
8921
|
+
`);
|
|
8922
|
+
ctx.data.mergeAction = "MERGE_BLOCKED";
|
|
8923
|
+
return;
|
|
8924
|
+
}
|
|
8925
|
+
const verdict = evaluateMergeGate(pr);
|
|
8926
|
+
if (!verdict.ok) {
|
|
8927
|
+
process.stdout.write(`[merge] PR #${prNumber} not merged \u2014 ${verdict.reason}
|
|
8928
|
+
`);
|
|
8929
|
+
ctx.data.mergeAction = verdict.action;
|
|
8930
|
+
if (verdict.action === "MERGE_BLOCKED") {
|
|
8931
|
+
commentOnIssue(
|
|
8932
|
+
prNumber,
|
|
8933
|
+
`\u{1F6A6} _Auto-merge held: ${verdict.reason} Kody will retry once the PR is CLEAN._`,
|
|
8934
|
+
ctx.cwd
|
|
8935
|
+
);
|
|
8936
|
+
}
|
|
8937
|
+
return;
|
|
8938
|
+
}
|
|
8939
|
+
process.stdout.write(`[merge] PR #${prNumber} is CLEAN \u2014 squash-merging
|
|
8940
|
+
`);
|
|
8941
|
+
const merged = mergePrSquash(prNumber, ctx.cwd);
|
|
8942
|
+
if (!merged.ok) {
|
|
8943
|
+
process.stderr.write(`[merge] squash-merge of PR #${prNumber} failed: ${merged.error}
|
|
8944
|
+
`);
|
|
8945
|
+
ctx.data.mergeAction = "MERGE_BLOCKED";
|
|
8946
|
+
commentOnIssue(
|
|
8947
|
+
prNumber,
|
|
8948
|
+
`\u{1F6A6} _Auto-merge attempted but failed: ${merged.error}. Kody will retry next tick._`,
|
|
8949
|
+
ctx.cwd
|
|
8950
|
+
);
|
|
8951
|
+
return;
|
|
8952
|
+
}
|
|
8953
|
+
process.stdout.write(`[merge] PR #${prNumber} merged \u2705
|
|
8954
|
+
`);
|
|
8955
|
+
ctx.data.mergeAction = "MERGE_COMPLETED";
|
|
8956
|
+
};
|
|
8957
|
+
|
|
8834
8958
|
// src/scripts/mergeReleasePr.ts
|
|
8835
8959
|
import { execFileSync as execFileSync20 } from "child_process";
|
|
8836
8960
|
var API_TIMEOUT_MS7 = 6e4;
|
|
@@ -11950,7 +12074,7 @@ function appendLine(owner, repo, cwd, record) {
|
|
|
11950
12074
|
let existing = "";
|
|
11951
12075
|
let sha;
|
|
11952
12076
|
try {
|
|
11953
|
-
const out = gh(["api", `/repos/${owner}/${repo}/contents/${filePath}`], { cwd });
|
|
12077
|
+
const out = gh(["api", `/repos/${owner}/${repo}/contents/${filePath}?ref=${STATE_BRANCH}`], { cwd });
|
|
11954
12078
|
const json = JSON.parse(out);
|
|
11955
12079
|
if (json.sha) sha = json.sha;
|
|
11956
12080
|
if (json.content) existing = Buffer.from(json.content, "base64").toString("utf-8");
|
|
@@ -11960,9 +12084,12 @@ function appendLine(owner, repo, cwd, record) {
|
|
|
11960
12084
|
`;
|
|
11961
12085
|
const payload = {
|
|
11962
12086
|
message: `chore(activity): ${record.action}`,
|
|
11963
|
-
content: Buffer.from(body, "utf-8").toString("base64")
|
|
12087
|
+
content: Buffer.from(body, "utf-8").toString("base64"),
|
|
12088
|
+
// Keep this high-frequency feed off the default branch.
|
|
12089
|
+
branch: STATE_BRANCH
|
|
11964
12090
|
};
|
|
11965
12091
|
if (sha) payload.sha = sha;
|
|
12092
|
+
ensureStateBranch(owner, repo, cwd);
|
|
11966
12093
|
gh(
|
|
11967
12094
|
["api", "--method", "PUT", `/repos/${owner}/${repo}/contents/${filePath}`, "--input", "-"],
|
|
11968
12095
|
{ cwd, input: JSON.stringify(payload) }
|
|
@@ -12252,6 +12379,7 @@ var preflightScripts = {
|
|
|
12252
12379
|
revertFlow,
|
|
12253
12380
|
reviewFlow,
|
|
12254
12381
|
syncFlow,
|
|
12382
|
+
mergeFlow,
|
|
12255
12383
|
initFlow,
|
|
12256
12384
|
loadTaskState,
|
|
12257
12385
|
loadTaskContext,
|
|
@@ -14028,6 +14156,7 @@ Usage:
|
|
|
14028
14156
|
kody-engine fix --pr <N> [--feedback "..."] [--cwd <path>] [--verbose|--quiet]
|
|
14029
14157
|
kody-engine fix-ci --pr <N> [--run-id <ID>] [--cwd <path>] [--verbose|--quiet]
|
|
14030
14158
|
kody-engine resolve --pr <N> [--cwd <path>] [--verbose|--quiet]
|
|
14159
|
+
kody-engine merge --pr <N> [--cwd <path>] [--verbose|--quiet]
|
|
14031
14160
|
kody-engine review --pr <N> [--cwd <path>] [--verbose|--quiet]
|
|
14032
14161
|
kody-engine <other> [--cwd <path>] [--verbose|--quiet]
|
|
14033
14162
|
kody-engine ci --issue <N> [preflight flags \u2014 see: kody-engine ci --help]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "merge",
|
|
3
|
+
"role": "primitive",
|
|
4
|
+
"kind": "oneshot",
|
|
5
|
+
"describe": "Self-gating squash-merge of an open PR into its base. Deterministic, no agent: merges only when GitHub reports the PR CLEAN (mergeable + required checks/reviews satisfied); otherwise refuses and comments why. Used by the CTO qa-merge duty once a QA-goal PR has graduated.",
|
|
6
|
+
"inputs": [
|
|
7
|
+
{
|
|
8
|
+
"name": "pr",
|
|
9
|
+
"flag": "--pr",
|
|
10
|
+
"type": "int",
|
|
11
|
+
"required": true,
|
|
12
|
+
"describe": "GitHub PR number to merge. No-op (MERGE_SKIPPED) if already closed/merged; refuses (MERGE_BLOCKED) if draft, conflicting, or not yet CLEAN."
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"claudeCode": {
|
|
16
|
+
"model": "inherit",
|
|
17
|
+
"permissionMode": "default",
|
|
18
|
+
"maxTurns": null,
|
|
19
|
+
"maxThinkingTokens": null,
|
|
20
|
+
"systemPromptAppend": null,
|
|
21
|
+
"tools": [],
|
|
22
|
+
"hooks": [],
|
|
23
|
+
"skills": [],
|
|
24
|
+
"commands": [],
|
|
25
|
+
"subagents": [],
|
|
26
|
+
"plugins": [],
|
|
27
|
+
"mcpServers": []
|
|
28
|
+
},
|
|
29
|
+
"cliTools": [
|
|
30
|
+
{
|
|
31
|
+
"name": "gh",
|
|
32
|
+
"install": {
|
|
33
|
+
"required": true,
|
|
34
|
+
"checkCommand": "command -v gh"
|
|
35
|
+
},
|
|
36
|
+
"verify": "gh auth status",
|
|
37
|
+
"usage": "Reads PR mergeability (`gh pr view --json`) and merges (`gh pr merge --squash --delete-branch`).",
|
|
38
|
+
"allowedUses": ["pr", "api"]
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"inputArtifacts": [],
|
|
42
|
+
"outputArtifacts": [],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"preflight": [
|
|
45
|
+
{
|
|
46
|
+
"script": "mergeFlow"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"postflight": []
|
|
50
|
+
},
|
|
51
|
+
"output": {
|
|
52
|
+
"actionTypes": ["MERGE_COMPLETED", "MERGE_BLOCKED", "MERGE_SKIPPED"]
|
|
53
|
+
}
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.133",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|