@kody-ade/kody-engine 0.3.26 → 0.3.28

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.26",
6
+ version: "0.3.28",
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",
@@ -167,6 +167,7 @@ function loadConfig(projectDir = process.cwd()) {
167
167
  quality: {
168
168
  typecheck: typeof quality.typecheck === "string" ? quality.typecheck : "",
169
169
  lint: typeof quality.lint === "string" ? quality.lint : "",
170
+ format: typeof quality.format === "string" ? quality.format : "",
170
171
  testUnit: typeof quality.testUnit === "string" ? quality.testUnit : ""
171
172
  },
172
173
  git: {
@@ -223,11 +224,9 @@ function parseReleaseConfig(raw) {
223
224
  if (Array.isArray(r.versionFiles)) out.versionFiles = r.versionFiles.filter((f) => typeof f === "string");
224
225
  if (typeof r.publishCommand === "string") out.publishCommand = r.publishCommand;
225
226
  if (typeof r.notifyCommand === "string") out.notifyCommand = r.notifyCommand;
226
- if (typeof r.deployCommand === "string") out.deployCommand = r.deployCommand;
227
227
  if (typeof r.e2eCommand === "string") out.e2eCommand = r.e2eCommand;
228
228
  if (typeof r.draftRelease === "boolean") out.draftRelease = r.draftRelease;
229
229
  if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
230
- if (typeof r.devBranch === "string" && r.devBranch.length > 0) out.devBranch = r.devBranch;
231
230
  if (typeof r.timeoutMs === "number" && r.timeoutMs > 0) out.timeoutMs = Math.floor(r.timeoutMs);
232
231
  return Object.keys(out).length > 0 ? out : void 0;
233
232
  }
@@ -5079,6 +5078,7 @@ async function verifyAll(config, cwd) {
5079
5078
  if (config.quality.typecheck) commands.push({ name: "typecheck", cmd: config.quality.typecheck });
5080
5079
  if (config.quality.testUnit) commands.push({ name: "test", cmd: config.quality.testUnit });
5081
5080
  if (config.quality.lint) commands.push({ name: "lint", cmd: config.quality.lint });
5081
+ if (config.quality.format) commands.push({ name: "format", cmd: config.quality.format });
5082
5082
  const failed = [];
5083
5083
  const details = {};
5084
5084
  for (const { name, cmd } of commands) {
@@ -5114,6 +5114,17 @@ var verify = async (ctx) => {
5114
5114
  ctx.data.verifyOk = false;
5115
5115
  ctx.data.verifyReason = `verify crashed: ${err instanceof Error ? err.message : String(err)}`;
5116
5116
  }
5117
+ if (ctx.data.verifyOk === false) {
5118
+ const action = ctx.data.action;
5119
+ if (action && action.type.endsWith("_COMPLETED")) {
5120
+ const reason = ctx.data.verifyReason || "verify failed";
5121
+ ctx.data.action = {
5122
+ type: action.type.replace(/_COMPLETED$/, "_FAILED"),
5123
+ payload: { reason, downgradedFrom: action.type },
5124
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
5125
+ };
5126
+ }
5127
+ }
5117
5128
  };
5118
5129
 
5119
5130
  // src/scripts/watchStalePrsFlow.ts
@@ -5379,7 +5390,7 @@ async function runExecutable(profileName, input) {
5379
5390
  config = input.config;
5380
5391
  } else if (input.skipConfig) {
5381
5392
  config = {
5382
- quality: { typecheck: "", lint: "", testUnit: "" },
5393
+ quality: { typecheck: "", lint: "", testUnit: "", format: "" },
5383
5394
  git: { defaultBranch: "main" },
5384
5395
  github: { owner: "", repo: "" },
5385
5396
  agent: { model: "claude/claude-haiku-4-5-20251001" }
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env bash
2
2
  #
3
- # release-deploy: open a PR from the integration branch (dev) into the
4
- # default branch (main) — the human gate for production deploy. The
5
- # orchestrator's chain ENDS with this PR opened; merging it is a manual
6
- # step. No agent.
3
+ # release-deploy: open a PR from the integration branch (git.defaultBranch)
4
+ # into the production target (release.releaseBranch) — the human gate for
5
+ # production deploy. The orchestrator's chain ENDS with this PR opened;
6
+ # merging it is a manual step. No agent.
7
7
  #
8
8
  # Behavior:
9
- # - If release.devBranch is unset OR equals git.defaultBranch:
9
+ # - If release.releaseBranch is unset OR equals git.defaultBranch:
10
10
  # no-op success (single-branch repos have nothing to deploy).
11
- # - Else: idempotently open PR `devBranch` → `defaultBranch`. If an
12
- # open PR already exists for that pair, reuse its URL.
11
+ # - Else: idempotently open PR `defaultBranch` → `releaseBranch`. If an
12
+ # open PR for that pair already exists, reuse its URL.
13
13
  #
14
14
  # After the PR is opened, runs `release.notifyCommand` (if set) as a
15
15
  # best-effort post-deploy hook.
@@ -19,8 +19,8 @@
19
19
  # KODY_ARG_ISSUE triggering issue/PR number (optional)
20
20
  #
21
21
  # Config (env):
22
- # KODY_CFG_GIT_DEFAULTBRANCH e.g. main
23
- # KODY_CFG_RELEASE_DEVBRANCH e.g. dev (unset → no-op)
22
+ # KODY_CFG_GIT_DEFAULTBRANCH e.g. dev
23
+ # KODY_CFG_RELEASE_RELEASEBRANCH e.g. main (unset → no-op)
24
24
  # KODY_CFG_RELEASE_NOTIFYCOMMAND optional; $VERSION substituted
25
25
  # KODY_CFG_RELEASE_TIMEOUTMS per-command timeout in ms (default 600000)
26
26
  #
@@ -33,27 +33,36 @@ set -euo pipefail
33
33
 
34
34
  dry_run="${KODY_ARG_DRY_RUN:-false}"
35
35
  default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
36
- dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
36
+ release_branch="${KODY_CFG_RELEASE_RELEASEBRANCH:-}"
37
37
  notify_cmd="${KODY_CFG_RELEASE_NOTIFYCOMMAND:-}"
38
38
  timeout_ms="${KODY_CFG_RELEASE_TIMEOUTMS:-600000}"
39
39
  timeout_s=$((timeout_ms / 1000))
40
40
 
41
- read_pkg_version() {
41
+ # Read version from the integration branch tip (where the bump commit lives),
42
+ # not from the local working tree (the workflow may have checked out another
43
+ # branch). Falls back to local package.json if the fetch fails.
44
+ read_version() {
45
+ local branch="$1"
46
+ if git fetch origin "$branch" --quiet 2>/dev/null; then
47
+ if pkg=$(git show "origin/${branch}:package.json" 2>/dev/null); then
48
+ echo "$pkg" | python3 -c "import json,sys; print(json.load(sys.stdin)['version'])" 2>/dev/null && return
49
+ fi
50
+ fi
42
51
  python3 -c "import json; print(json.load(open('package.json'))['version'])" 2>/dev/null || echo "unknown"
43
52
  }
44
53
 
45
- version=$(read_pkg_version)
54
+ version=$(read_version "$default_branch")
46
55
  echo "→ release deploy: v${version}"
47
56
 
48
57
  # Single-branch repos: nothing to deploy.
49
- if [[ -z "$dev_branch" || "$dev_branch" == "$default_branch" ]]; then
50
- echo "KODY_REASON=no devBranch configured (or equals defaultBranch) — nothing to deploy"
58
+ if [[ -z "$release_branch" || "$release_branch" == "$default_branch" ]]; then
59
+ echo "KODY_REASON=no releaseBranch configured (or equals defaultBranch) — nothing to deploy"
51
60
  echo "KODY_SKIP_AGENT=true"
52
61
  exit 0
53
62
  fi
54
63
 
55
64
  if [[ "$dry_run" == "true" ]]; then
56
- echo "KODY_REASON=dry-run — would open PR ${dev_branch} → ${default_branch}"
65
+ echo "KODY_REASON=dry-run — would open PR ${default_branch} → ${release_branch}"
57
66
  echo "KODY_SKIP_AGENT=true"
58
67
  exit 0
59
68
  fi
@@ -61,7 +70,7 @@ fi
61
70
  export HUSKY=0 SKIP_HOOKS=1 CI="${CI:-1}"
62
71
 
63
72
  # Idempotency: reuse an open PR for this branch pair if one exists.
64
- existing=$(gh pr list --head "$dev_branch" --base "$default_branch" --state open --json url --limit 1 2>/dev/null \
73
+ existing=$(gh pr list --head "$default_branch" --base "$release_branch" --state open --json url --limit 1 2>/dev/null \
65
74
  | python3 -c 'import json,sys; data=json.load(sys.stdin); print(data[0]["url"] if data else "")' 2>/dev/null \
66
75
  || echo "")
67
76
 
@@ -69,10 +78,10 @@ if [[ -n "$existing" ]]; then
69
78
  echo " reusing existing deploy PR: ${existing}"
70
79
  pr_url="$existing"
71
80
  else
72
- body="Automated deploy PR opened by kody — promotes \`${dev_branch}\` to \`${default_branch}\` for release **v${version}**.
81
+ body="Automated deploy PR opened by kody — promotes \`${default_branch}\` to \`${release_branch}\` for release **v${version}**.
73
82
 
74
- Merge this PR to deploy v${version} to \`${default_branch}\`."
75
- if ! pr_url=$(printf '%s' "$body" | gh pr create --head "$dev_branch" --base "$default_branch" --title "deploy: ${dev_branch} → ${default_branch} (v${version})" --body-file -); then
83
+ Merge this PR to deploy v${version} to \`${release_branch}\`."
84
+ 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
76
85
  echo "KODY_REASON=release deploy: gh pr create failed"
77
86
  echo "KODY_SKIP_AGENT=true"
78
87
  exit 1
@@ -101,5 +110,5 @@ if [[ -n "$notify_cmd" ]]; then
101
110
  fi
102
111
  fi
103
112
 
104
- echo "KODY_REASON=opened deploy PR ${dev_branch} → ${default_branch} (notify=${notify_status})"
113
+ echo "KODY_REASON=opened deploy PR ${default_branch} → ${release_branch} (notify=${notify_status})"
105
114
  echo "KODY_SKIP_AGENT=true"
@@ -26,10 +26,6 @@ bump="${KODY_ARG_BUMP:-patch}"
26
26
  dry_run="${KODY_ARG_DRY_RUN:-false}"
27
27
  prefer="${KODY_ARG_PREFER:-}"
28
28
  default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
29
- dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
30
- # PR target: dev branch when configured (and different from default), else default.
31
- pr_base="${dev_branch:-$default_branch}"
32
- [[ "$pr_base" == "$default_branch" ]] && pr_base="$default_branch"
33
29
  version_files_json="${KODY_CFG_RELEASE_VERSIONFILES:-}"
34
30
 
35
31
  fail() {
@@ -317,8 +313,8 @@ _… truncated; see CHANGELOG.md_"
317
313
  else
318
314
  body_entry="$entry"
319
315
  fi
320
- body=$'Automated release PR opened by kody.\n\n'"$body_entry"$'\n\nThe release orchestrator will merge this into `'"${pr_base}"$'` and continue to publish + deploy.'
321
- pr_url=$(printf '%s' "$body" | gh pr create --head "$release_branch" --base "$pr_base" --title "chore: release ${tag}" --body-file -)
316
+ body=$'Automated release PR opened by kody.\n\n'"$body_entry"$'\n\nThe release orchestrator will merge this into `'"${default_branch}"$'` and continue to publish + deploy.'
317
+ pr_url=$(printf '%s' "$body" | gh pr create --head "$release_branch" --base "$default_branch" --title "chore: release ${tag}" --body-file -)
322
318
  fi
323
319
 
324
320
  if [[ -z "$pr_url" ]]; then
@@ -24,13 +24,6 @@ set -euo pipefail
24
24
 
25
25
  dry_run="${KODY_ARG_DRY_RUN:-false}"
26
26
  default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
27
- dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
28
- # Tag the branch where the release-prepare PR was merged: devBranch when set
29
- # (and different from default), else defaultBranch.
30
- target_branch="$default_branch"
31
- if [[ -n "$dev_branch" && "$dev_branch" != "$default_branch" ]]; then
32
- target_branch="$dev_branch"
33
- fi
34
27
  publish_cmd="${KODY_CFG_RELEASE_PUBLISHCOMMAND:-}"
35
28
  draft="${KODY_CFG_RELEASE_DRAFTRELEASE:-false}"
36
29
  timeout_ms="${KODY_CFG_RELEASE_TIMEOUTMS:-600000}"
@@ -53,10 +46,10 @@ fi
53
46
  export HUSKY=0 SKIP_HOOKS=1 CI="${CI:-1}"
54
47
 
55
48
  # Make sure we're on the merged commit. The orchestrator merged the release
56
- # PR into target_branch; pull so the local tree has the bump commit.
57
- git fetch origin "$target_branch" --tags
58
- git checkout "$target_branch"
59
- git reset --hard "origin/$target_branch"
49
+ # PR into default_branch; pull so the local tree has the bump commit.
50
+ git fetch origin "$default_branch" --tags
51
+ git checkout "$default_branch"
52
+ git reset --hard "origin/$default_branch"
60
53
 
61
54
  version=$(read_pkg_version)
62
55
  tag="v${version}"
@@ -23,6 +23,11 @@
23
23
  "description": "Auto-fix lint command, run when verify fails (e.g., 'pnpm lint:fix')",
24
24
  "default": ""
25
25
  },
26
+ "format": {
27
+ "type": "string",
28
+ "description": "Format check command (e.g., 'pnpm format:check', 'prettier --check .'). Empty to skip.",
29
+ "default": ""
30
+ },
26
31
  "formatFix": {
27
32
  "type": "string",
28
33
  "description": "Auto-fix format command, run when verify fails (e.g., 'pnpm format')",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
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",