@kody-ade/kody-engine 0.4.154 → 0.4.156

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
@@ -1061,7 +1061,7 @@ var init_loadPriorArt = __esm({
1061
1061
  // package.json
1062
1062
  var package_default = {
1063
1063
  name: "@kody-ade/kody-engine",
1064
- version: "0.4.154",
1064
+ version: "0.4.156",
1065
1065
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
1066
1066
  license: "MIT",
1067
1067
  type: "module",
@@ -82,6 +82,18 @@ open_deploy_pr() {
82
82
  local body
83
83
  body=$(build_pr_body "$new_version" "$changelog_section" "$default_branch" "$release_branch" "$issue_arg")
84
84
 
85
+ # GitHub rejects a PR body over 65536 chars (GraphQL createPullRequest).
86
+ # A large accumulated CHANGELOG section can blow past it, so clamp: drop the
87
+ # changelog to a budget and rebuild, then hard-truncate as a final guard.
88
+ local body_max=65000
89
+ if (( ${#body} > body_max )); then
90
+ echo "[deploy] PR body ${#body} chars > ${body_max} — truncating changelog" >&2
91
+ local budget=$(( body_max - 2000 ))
92
+ changelog_section="${changelog_section:0:budget}"$'\n\n_…changelog truncated; see CHANGELOG.md on the branch._'
93
+ body=$(build_pr_body "$new_version" "$changelog_section" "$default_branch" "$release_branch" "$issue_arg")
94
+ (( ${#body} > body_max )) && body="${body:0:body_max}"
95
+ fi
96
+
85
97
  # Idempotency: reuse an open PR for this branch pair if one exists.
86
98
  local existing pr_url
87
99
  existing=$(gh pr list --head "$default_branch" --base "$release_branch" --state open --json url --limit 1 2>/dev/null \
@@ -135,8 +135,22 @@ if [[ "$publish_status" == "failed" ]]; then
135
135
  fi
136
136
 
137
137
  # ── 5. Deploy PR (default → release branch) ───────────────────────────────
138
+ # Distinguish three outcomes: rc!=0 is a real failure (do NOT mask as no-op);
139
+ # rc==0 + empty URL is a genuine single-branch no-op; rc==0 + URL is success.
138
140
  current_step="deploy"
139
- deploy_pr_url=$(open_deploy_pr "$new_version" "$issue" || echo "")
141
+ set +e
142
+ deploy_pr_url=$(open_deploy_pr "$new_version" "$issue")
143
+ deploy_rc=$?
144
+ set -e
145
+ release_branch="${KODY_CFG_RELEASE_RELEASEBRANCH:-}"
146
+ if [[ "$deploy_rc" -ne 0 ]]; then
147
+ echo "[release] deploy step failed (rc=${deploy_rc}) — published v${new_version} but the ${default_branch}→${release_branch} promotion PR was not opened" >&2
148
+ echo "KODY_REASON=release v${new_version}: published, but the ${default_branch}→${release_branch} deploy PR failed"
149
+ echo "RELEASE_TAG=${tag}"
150
+ [[ -n "$release_url" ]] && echo "RELEASE_URL=${release_url}"
151
+ echo "RELEASE_FAILED=true"
152
+ exit 1
153
+ fi
140
154
  if [[ -z "$deploy_pr_url" ]]; then
141
155
  echo " (deploy: no-op — single-branch repo)"
142
156
  else
@@ -142,6 +142,18 @@ if [[ "$issue_arg" =~ ^[0-9]+$ && "$issue_arg" != "0" ]]; then
142
142
  fi
143
143
  body=$(build_pr_body "$tracking_line")
144
144
 
145
+ # GitHub rejects a PR body over 65536 chars (GraphQL createPullRequest). A
146
+ # large accumulated CHANGELOG section can blow past it, so clamp: drop the
147
+ # changelog to a budget and rebuild, then hard-truncate as a final guard.
148
+ body_max=65000
149
+ if (( ${#body} > body_max )); then
150
+ echo "[kody release-deploy] PR body ${#body} chars > ${body_max} — truncating changelog" >&2
151
+ budget=$(( body_max - 2000 ))
152
+ changelog_section="${changelog_section:0:budget}"$'\n\n_…changelog truncated; see CHANGELOG.md on the branch._'
153
+ body=$(build_pr_body "$tracking_line")
154
+ (( ${#body} > body_max )) && body="${body:0:body_max}"
155
+ fi
156
+
145
157
  if [[ -n "$existing" ]]; then
146
158
  echo " reusing existing deploy PR: ${existing}"
147
159
  pr_url="$existing"
@@ -56,44 +56,70 @@ tag="v${version}"
56
56
 
57
57
  echo "→ release publish: ${tag}"
58
58
 
59
- # Refuse if the tag already exists locally (left over from a prior failed run).
60
- if git rev-parse --verify "$tag" >/dev/null 2>&1; then
61
- fail "release publish: tag ${tag} already exists" 1
59
+ # Recovery is resume-not-overwrite: a release is three steps (push tag, run
60
+ # publishCommand, create GH release) and any of them may already be done from
61
+ # a prior partial run. We probe each step's state and perform only the missing
62
+ # parts. An already-fully-released version is therefore a no-op success, and we
63
+ # never re-point or force an existing tag (that would rewrite a shipped version).
64
+ tag_local=false
65
+ tag_remote=false
66
+ release_exists=false
67
+ if git rev-parse --verify "$tag" >/dev/null 2>&1; then tag_local=true; fi
68
+ if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1; then tag_remote=true; fi
69
+ if gh release view "$tag" >/dev/null 2>&1; then release_exists=true; fi
70
+
71
+ if [[ "$tag_local" == "true" || "$tag_remote" == "true" || "$release_exists" == "true" ]]; then
72
+ echo " resuming: tag exists (local=${tag_local} remote=${tag_remote}), gh-release=${release_exists}"
62
73
  fi
63
74
 
64
75
  if [[ "$dry_run" == "true" ]]; then
65
- echo "KODY_REASON=dry-run — would tag + publish ${tag}"
76
+ echo "KODY_REASON=dry-run — would tag + publish ${tag} (tag_remote=${tag_remote}, gh-release=${release_exists})"
66
77
  echo "KODY_SKIP_AGENT=true"
67
78
  exit 0
68
79
  fi
69
80
 
70
- # Tag + push.
71
- git tag -a "$tag" -m "Release ${tag}"
72
- git push origin "$tag"
81
+ # Tag + push (skip whichever half already exists).
82
+ if [[ "$tag_local" == "false" && "$tag_remote" == "false" ]]; then
83
+ git tag -a "$tag" -m "Release ${tag}"
84
+ fi
85
+ if [[ "$tag_remote" == "false" ]]; then
86
+ git push origin "$tag"
87
+ fi
73
88
 
74
- # publishCommand (optional). Failure here is recorded but does not abort
75
- # we still want the GH release entry so the tag is discoverable.
89
+ # publishCommand (optional). A version that's already on the registry is the
90
+ # expected recovery case, not an error: treat "already published" as done.
91
+ # Any other non-zero is a real failure (recorded, but we still create the GH
92
+ # release so the tag is discoverable).
76
93
  publish_status="skipped"
77
94
  if [[ -n "$publish_cmd" ]]; then
78
95
  cmd="${publish_cmd//\$VERSION/$version}"
79
96
  echo " publish: ${cmd}"
80
- if timeout "${timeout_s}" bash -c "$cmd"; then
97
+ publish_out=""
98
+ if publish_out=$(timeout "${timeout_s}" bash -c "$cmd" 2>&1); then
81
99
  publish_status="ok"
100
+ elif echo "$publish_out" | grep -qiE "already exists|cannot publish over|previously published|403 Forbidden"; then
101
+ publish_status="already-published"
102
+ echo "[kody release-publish] version ${version} already on registry — treating as published"
82
103
  else
83
104
  publish_status="failed"
84
105
  echo "[kody release-publish] publishCommand failed (continuing to create GH release)" >&2
85
106
  fi
107
+ echo "$publish_out"
86
108
  fi
87
109
 
88
- # GitHub release.
110
+ # GitHub release (create only if missing).
89
111
  release_url=""
90
- draft_flag=""
91
- [[ "$draft" == "true" ]] && draft_flag="--draft"
92
- if release_url=$(gh release create "$tag" --title "$tag" --notes "Release ${tag} — automated by kody." $draft_flag 2>&1); then
93
- :
112
+ if [[ "$release_exists" == "true" ]]; then
113
+ release_url=$(gh release view "$tag" --json url --jq .url 2>/dev/null || echo "")
94
114
  else
95
- echo "[kody release-publish] gh release create failed: $release_url" >&2
96
- release_url=""
115
+ draft_flag=""
116
+ [[ "$draft" == "true" ]] && draft_flag="--draft"
117
+ if release_url=$(gh release create "$tag" --title "$tag" --notes "Release ${tag} — automated by kody." $draft_flag 2>&1); then
118
+ :
119
+ else
120
+ echo "[kody release-publish] gh release create failed: $release_url" >&2
121
+ release_url=""
122
+ fi
97
123
  fi
98
124
 
99
125
  echo "RELEASE_TAG=${tag}"
@@ -108,3 +134,4 @@ fi
108
134
  [[ -n "$release_url" ]] && echo "KODY_PR_URL=${release_url}"
109
135
  echo "KODY_REASON=tagged ${tag}, published${publish_status:+ ($publish_status)}"
110
136
  echo "KODY_SKIP_AGENT=true"
137
+ exit 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.154",
3
+ "version": "0.4.156",
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",