@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 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.64",
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) return null;
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
- else
85
- # Same Tracking-Issue marker as release-prepare non-closing reference
86
- # so the originating release issue stays open through the deploy step
87
- # while the Kody Dashboard can still link this PR to the task for preview.
88
- tracking_line=""
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
- body="Automated deploy PR opened by kody — promotes \`${default_branch}\` to \`${release_branch}\` for release **v${version}**.
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.64",
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
- "scripts": {
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
+ }