@kody-ade/kody-engine 0.3.64 → 0.3.66
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 +11 -10
- package/dist/executables/release-deploy/deploy.sh +73 -10
- package/dist/executables/release-prepare/prepare.sh +0 -0
- package/dist/executables/release-publish/publish.sh +0 -0
- package/dist/executables/resolve/apply-prefer.sh +0 -0
- package/dist/executables/revert/revert.sh +0 -0
- package/dist/executables/run/prompt.md +1 -0
- package/package.json +15 -14
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.
|
|
6
|
+
version: "0.3.66",
|
|
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",
|
|
@@ -858,7 +858,14 @@ function autoDispatch(opts) {
|
|
|
858
858
|
if (!executable) {
|
|
859
859
|
executable = isPr ? opts?.config?.defaultPrExecutable ?? "fix" : opts?.config?.defaultExecutable ?? null;
|
|
860
860
|
}
|
|
861
|
-
if (!executable)
|
|
861
|
+
if (!executable) {
|
|
862
|
+
const profileMissing = aliased ? getProfileInputs(aliased) === null : true;
|
|
863
|
+
process.stderr.write(
|
|
864
|
+
`[kody] dispatch: no executable resolved for issue_comment (firstToken=${firstToken ?? "<none>"}, aliased=${aliased ?? "<none>"}, profileFound=${!profileMissing}, defaultExecutable=${opts?.config?.defaultExecutable ?? "<unset>"})
|
|
865
|
+
`
|
|
866
|
+
);
|
|
867
|
+
return null;
|
|
868
|
+
}
|
|
862
869
|
const inputs = getProfileInputs(executable);
|
|
863
870
|
const effectiveInputs = inputs ?? [];
|
|
864
871
|
const unknownProfile = inputs === null;
|
|
@@ -5891,10 +5898,7 @@ function tryPostPr3(prNumber, body, cwd) {
|
|
|
5891
5898
|
function findPreviewDeploymentUrl(prNumber, cwd) {
|
|
5892
5899
|
const sha = getPrHeadSha(prNumber, cwd);
|
|
5893
5900
|
if (!sha) return null;
|
|
5894
|
-
const raw = safeGh2(
|
|
5895
|
-
["api", `repos/{owner}/{repo}/deployments?sha=${sha}&environment=Preview&per_page=10`],
|
|
5896
|
-
cwd
|
|
5897
|
-
);
|
|
5901
|
+
const raw = safeGh2(["api", `repos/{owner}/{repo}/deployments?sha=${sha}&environment=Preview&per_page=10`], cwd);
|
|
5898
5902
|
if (!raw) return null;
|
|
5899
5903
|
let deployments;
|
|
5900
5904
|
try {
|
|
@@ -5916,10 +5920,7 @@ function getPrHeadSha(prNumber, cwd) {
|
|
|
5916
5920
|
return trimmed.length > 0 ? trimmed : null;
|
|
5917
5921
|
}
|
|
5918
5922
|
function latestSuccessUrl(deploymentId, cwd) {
|
|
5919
|
-
const raw = safeGh2(
|
|
5920
|
-
["api", `repos/{owner}/{repo}/deployments/${deploymentId}/statuses?per_page=10`],
|
|
5921
|
-
cwd
|
|
5922
|
-
);
|
|
5923
|
+
const raw = safeGh2(["api", `repos/{owner}/{repo}/deployments/${deploymentId}/statuses?per_page=10`], cwd);
|
|
5923
5924
|
if (!raw) return null;
|
|
5924
5925
|
let statuses;
|
|
5925
5926
|
try {
|
|
@@ -54,6 +54,57 @@ read_version() {
|
|
|
54
54
|
version=$(read_version "$default_branch")
|
|
55
55
|
echo "→ release deploy: v${version}"
|
|
56
56
|
|
|
57
|
+
# Read the CHANGELOG section for $version from the integration branch
|
|
58
|
+
# (where release-prepare just committed it). Handles both header shapes
|
|
59
|
+
# observed in the wild: `## [0.25.0] - 2026-04-15` and `## 0.22.0 (...)`.
|
|
60
|
+
# Prints the body lines (without the matched header). Empty stdout =
|
|
61
|
+
# fall back to the minimal PR body — never break the release.
|
|
62
|
+
read_changelog_section() {
|
|
63
|
+
local branch="$1" ver="$2" raw=""
|
|
64
|
+
if ! raw=$(git show "origin/${branch}:CHANGELOG.md" 2>/dev/null); then
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
67
|
+
printf '%s' "$raw" | awk -v ver="$ver" '
|
|
68
|
+
BEGIN { capture = 0 }
|
|
69
|
+
# Match: "## [VER] ..." or "## VER ..." (VER as the first word/bracket).
|
|
70
|
+
/^##[[:space:]]/ {
|
|
71
|
+
if (capture) { exit }
|
|
72
|
+
header = $0
|
|
73
|
+
sub(/^##[[:space:]]+/, "", header)
|
|
74
|
+
sub(/^\[/, "", header); sub(/\].*/, "", header)
|
|
75
|
+
sub(/[[:space:]].*/, "", header)
|
|
76
|
+
sub(/[(].*/, "", header)
|
|
77
|
+
if (header == ver) { capture = 1; next }
|
|
78
|
+
}
|
|
79
|
+
capture { print }
|
|
80
|
+
' | awk '
|
|
81
|
+
# Trim leading and trailing blank lines from the captured block.
|
|
82
|
+
NF { if (!started) started = 1; out[++n] = $0; last = n; next }
|
|
83
|
+
started { out[++n] = $0 }
|
|
84
|
+
END { for (i = 1; i <= last; i++) print out[i] }
|
|
85
|
+
'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
changelog_section=$(read_changelog_section "$default_branch" "$version" || true)
|
|
89
|
+
if [[ -z "$changelog_section" ]]; then
|
|
90
|
+
echo " no CHANGELOG section for v${version} on origin/${default_branch} — using minimal PR body"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Build the kody-managed body block. A marker pair lets us update the
|
|
94
|
+
# section idempotently on re-runs without clobbering anything a human
|
|
95
|
+
# pasted outside the markers.
|
|
96
|
+
build_pr_body() {
|
|
97
|
+
local tracking_line="$1"
|
|
98
|
+
printf 'Automated deploy PR opened by kody — promotes `%s` to `%s` for release **v%s**.\n\n' \
|
|
99
|
+
"$default_branch" "$release_branch" "$version"
|
|
100
|
+
if [[ -n "$changelog_section" ]]; then
|
|
101
|
+
printf '<!-- kody-changelog-start -->\n## What'\''s changing in v%s\n\n%s\n<!-- kody-changelog-end -->\n\n' \
|
|
102
|
+
"$version" "$changelog_section"
|
|
103
|
+
fi
|
|
104
|
+
printf 'Merge this PR to deploy v%s to `%s`.%s\n' \
|
|
105
|
+
"$version" "$release_branch" "$tracking_line"
|
|
106
|
+
}
|
|
107
|
+
|
|
57
108
|
# Single-branch repos: nothing to deploy.
|
|
58
109
|
if [[ -z "$release_branch" || "$release_branch" == "$default_branch" ]]; then
|
|
59
110
|
echo "KODY_REASON=no releaseBranch configured (or equals defaultBranch) — nothing to deploy"
|
|
@@ -78,20 +129,25 @@ existing=$(gh pr list --head "$default_branch" --base "$release_branch" --state
|
|
|
78
129
|
# reuse-existing-PR path.
|
|
79
130
|
issue_arg="${KODY_ARG_ISSUE:-}"
|
|
80
131
|
|
|
132
|
+
# Same Tracking-Issue marker as release-prepare — non-closing reference
|
|
133
|
+
# so the originating release issue stays open through the deploy step
|
|
134
|
+
# while the Kody Dashboard can still link this PR to the task for preview.
|
|
135
|
+
tracking_line=""
|
|
136
|
+
if [[ "$issue_arg" =~ ^[0-9]+$ && "$issue_arg" != "0" ]]; then
|
|
137
|
+
tracking_line=$'\n\nTracking-Issue: #'"${issue_arg}"
|
|
138
|
+
fi
|
|
139
|
+
body=$(build_pr_body "$tracking_line")
|
|
140
|
+
|
|
81
141
|
if [[ -n "$existing" ]]; then
|
|
82
142
|
echo " reusing existing deploy PR: ${existing}"
|
|
83
143
|
pr_url="$existing"
|
|
84
|
-
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if [[ "$issue_arg" =~ ^[0-9]+$ && "$issue_arg" != "0" ]]; then
|
|
90
|
-
tracking_line=$'\n\nTracking-Issue: #'"${issue_arg}"
|
|
144
|
+
# Refresh the body so re-runs converge on the current changelog. Best-
|
|
145
|
+
# effort: a failed edit (e.g. permission-denied) shouldn't fail the
|
|
146
|
+
# release — the PR already exists and its title/branch are unchanged.
|
|
147
|
+
if ! printf '%s' "$body" | gh pr edit "$pr_url" --body-file - >/dev/null 2>&1; then
|
|
148
|
+
echo "[kody release-deploy] WARN: failed to refresh deploy PR body" >&2
|
|
91
149
|
fi
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Merge this PR to deploy v${version} to \`${release_branch}\`.${tracking_line}"
|
|
150
|
+
else
|
|
95
151
|
if ! pr_url=$(printf '%s' "$body" | gh pr create --head "$default_branch" --base "$release_branch" --title "deploy: ${default_branch} → ${release_branch} (v${version})" --body-file -); then
|
|
96
152
|
echo "KODY_REASON=release deploy: gh pr create failed"
|
|
97
153
|
echo "KODY_SKIP_AGENT=true"
|
|
@@ -127,9 +183,16 @@ echo "RELEASE_DEPLOY_PR=${pr_url}"
|
|
|
127
183
|
echo "KODY_PR_URL=${pr_url}"
|
|
128
184
|
|
|
129
185
|
# Optional post-deploy notification (e.g. Slack ping that a deploy PR is up).
|
|
186
|
+
# Substituted placeholders in the configured command:
|
|
187
|
+
# $VERSION — release version (e.g. 0.25.4)
|
|
188
|
+
# $DEPLOY_PR_URL — URL of the deploy PR just opened/reused
|
|
189
|
+
# The notifyCommand can use $DEPLOY_PR_URL to pull real content (e.g.
|
|
190
|
+
# `gh pr view $DEPLOY_PR_URL --json body --jq .body`) instead of
|
|
191
|
+
# rendering a hardcoded one-liner.
|
|
130
192
|
notify_status="skipped"
|
|
131
193
|
if [[ -n "$notify_cmd" ]]; then
|
|
132
194
|
cmd="${notify_cmd//\$VERSION/$version}"
|
|
195
|
+
cmd="${cmd//\$DEPLOY_PR_URL/$pr_url}"
|
|
133
196
|
echo " notify: ${cmd}"
|
|
134
197
|
if timeout "${timeout_s}" bash -c "$cmd"; then
|
|
135
198
|
notify_status="ok"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -27,6 +27,7 @@ If a prior-art block is present above, READ THE DIFFS — those are failed or su
|
|
|
27
27
|
- Read the tests for each of those files, if tests exist for the module.
|
|
28
28
|
- Read at least one sibling module that already implements the same pattern you're about to follow — your edits should mirror an existing convention unless you can name why a new one is needed.
|
|
29
29
|
- If your change requires writing or modifying a test, also check for repo-level testing guidance: `tests/README.md`, `TESTING.md`, or a "Testing"/"Tests" section in `AGENTS.md`/`CLAUDE.md`. If one exists, treat its patterns (auth setup, fixture creation, what NOT to do) as authoritative — they override anything you might infer from grepping individual files.
|
|
30
|
+
- **Removal/rename refactors** (deleting a call like `console.error`, renaming a function, dropping a method, replacing one API with another): before editing, grep the test directories for assertions tied to the OLD symbol — spies (`vi.spyOn(console`, `jest.spyOn(console`, `consoleErrorSpy`, `mockFn.mock.calls`), the literal function name, and any string the call produced. Enumerate every hit in your plan (step 2) and update those tests in step 4 in the same session. Skipping this grep is a hard failure even if your local test runs pass — the wrapper runs the full suite and you cannot fix breakages after DONE.
|
|
30
31
|
- If a file you need to read does not exist, say so explicitly in your plan (step 2). Do not guess at its contents.
|
|
31
32
|
2. **Plan** — before any Edit/Write, output a short plan (5–10 lines): what files you'll change, the approach, what could go wrong. No fluff.
|
|
32
33
|
3. **Build** — Edit/Write to implement the change. Stay within the plan; if you discover the plan was wrong, briefly say so and adjust.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.66",
|
|
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",
|
|
@@ -12,6 +12,18 @@
|
|
|
12
12
|
"templates",
|
|
13
13
|
"kody.config.schema.json"
|
|
14
14
|
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"kody": "tsx bin/kody.ts",
|
|
17
|
+
"build": "tsup && node scripts/copy-assets.cjs",
|
|
18
|
+
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
19
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
20
|
+
"test:all": "vitest run tests --no-coverage",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"lint": "biome check",
|
|
23
|
+
"lint:fix": "biome check --write",
|
|
24
|
+
"format": "biome format --write",
|
|
25
|
+
"prepublishOnly": "pnpm build"
|
|
26
|
+
},
|
|
15
27
|
"dependencies": {
|
|
16
28
|
"@actions/cache": "^6.0.0",
|
|
17
29
|
"@anthropic-ai/claude-agent-sdk": "0.2.119"
|
|
@@ -32,16 +44,5 @@
|
|
|
32
44
|
"url": "git+https://github.com/aharonyaircohen/kody-engine.git"
|
|
33
45
|
},
|
|
34
46
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
35
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
36
|
-
|
|
37
|
-
"kody": "tsx bin/kody.ts",
|
|
38
|
-
"build": "tsup && node scripts/copy-assets.cjs",
|
|
39
|
-
"test": "vitest run tests/unit tests/int --no-coverage",
|
|
40
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
41
|
-
"test:all": "vitest run tests --no-coverage",
|
|
42
|
-
"typecheck": "tsc --noEmit",
|
|
43
|
-
"lint": "biome check",
|
|
44
|
-
"lint:fix": "biome check --write",
|
|
45
|
-
"format": "biome format --write"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
47
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
48
|
+
}
|