@kody-ade/kody-engine 0.3.18 → 0.3.20

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/README.md CHANGED
@@ -6,73 +6,98 @@
6
6
 
7
7
  ```
8
8
  ┌─────────────────────────────────────────────┐
9
- │ Consumer repo workflow (.github/kody.yml) │ triggers on @kody comments
9
+ │ Consumer repo workflow (.github/kody.yml) │ @kody comments · schedule · release PR merge
10
10
  └─────────────────────────────────────────────┘
11
11
 
12
12
  ┌─────────────────────────────────────────────┐
13
13
  │ kody CLI (@kody-ade/kody-engine) │
14
- │ bin/kody.ts — parses argv
14
+ │ bin/kody.ts — entrypoint
15
+ │ src/dispatch.ts — profile-driven routing │
15
16
  │ src/executor.ts — runs one profile │
16
- │ src/executables/<name>/profile.json
17
- src/scripts/*.ts named hook catalog
17
+ │ src/executables/<name>/
18
+ profile.json · prompt.md · *.sh
19
+ │ src/scripts/*.ts — cross-cutting catalog │
18
20
  └─────────────────────────────────────────────┘
19
21
  ```
20
22
 
21
- Every top-level command is its own auto-discovered executable (`run`, `fix`, `fix-ci`, `resolve`, `review`, `sync`, `plan`, `plan-verify`, `orchestrator`, `release`, `watch-*`, `init`). The router has no hardcoded command switch beyond `ci`/`help`/`version` drop a new `src/executables/<name>/` directory with a `profile.json` + `prompt.md` and `kody <name>` starts working. The executor knows nothing about any specific command.
23
+ Every top-level command is its own auto-discovered executable. The router has **zero executable names hardcoded** comment dispatch resolves the first token after `@kody` through `config.aliases`, then falls back to `config.defaultExecutable` / `config.defaultPrExecutable`. Drop a new `src/executables/<name>/` directory with a `profile.json` + `prompt.md` (+ any colocated `.sh`) and `kody <name>` starts working.
22
24
 
23
- ## Install in a consumer repo
24
-
25
- 1. Copy `templates/kody.yml` to `.github/workflows/kody.yml`.
26
- 2. Add `agent.model` to `kody.config.json` (see `kody.config.schema.json`).
27
- 3. Secrets on the repo:
28
- - At least one model key (e.g. `MINIMAX_API_KEY`, `ANTHROPIC_API_KEY`)
29
- - Optional `KODY_TOKEN` PAT if you want kody's pushes to trigger downstream CI
25
+ Executable directories contain **only** three kinds of files: `profile.json` (declaration), `prompt.md` (agent instructions), and `.sh` scripts (mechanical side-effect work). Cross-cutting TypeScript lives in [src/scripts/](src/scripts/); it can't import from `src/executables/` and can't branch on `profile.name`.
30
26
 
31
- ## Commands
27
+ ## Install in a consumer repo
32
28
 
29
+ ```bash
30
+ npx -y -p @kody-ade/kody-engine@latest kody init
33
31
  ```
34
- # issue-triggered, agent writes code
35
- kody run --issue <N> # implement an issue end-to-end (branch, code, PR)
36
32
 
37
- # issue-triggered, agent read-only (no commits)
38
- kody plan --issue <N> # produce a plan artifact for run
39
- kody research --issue <N> # map repo context, surface questions/gaps
33
+ `kody init` scaffolds [kody.config.json](kody.config.schema.json), [.github/workflows/kody.yml](templates/kody.yml), per-scheduled-executable workflow files, and (if a UI is detected) `.kody/qa-guide.md` for `ui-review`. Idempotent — pass `--force` to overwrite.
40
34
 
41
- # PR-triggered, agent writes code
42
- kody fix --pr <N> [--feedback ...] # apply PR review feedback
43
- kody fix-ci --pr <N> [--run-id <ID>] # fix failing CI
44
- kody resolve --pr <N> # merge default branch in, resolve conflicts
35
+ Required repo secrets: at least one model provider key (e.g. `MINIMAX_API_KEY`, `ANTHROPIC_API_KEY`). Recommended: `KODY_TOKEN` PAT so kody's commits trigger downstream CI and can modify `.github/workflows/*`.
45
36
 
46
- # PR-triggered, agent read-only
47
- kody review --pr <N> # structured diff review (fast, diff only)
48
- kody ui-review --pr <N> [--preview-url <URL>] # UI/UX review — browses preview via Playwright
37
+ The consumer workflow listens on three triggers: `issue_comment` (for `@kody …` dispatch), `workflow_dispatch` (manual runs, chat mode, mission wake), and `pull_request: [closed]` (auto-finalizes a merged `release/vX.Y.Z` PR).
49
38
 
50
- # no agent (deterministic)
51
- kody sync --pr <N> # merge default branch into PR branch
39
+ ## Commands
40
+
41
+ ```
42
+ # agent, writes code
43
+ kody run --issue <N> # implement an issue end-to-end
44
+ kody fix --pr <N> [--feedback ...] # apply PR review feedback
45
+ kody fix-ci --pr <N> [--run-id <ID>] # fix failing CI
46
+ kody resolve --pr <N> [--prefer ours|theirs] # merge default branch, resolve conflicts
47
+
48
+ # agent, read-only
49
+ kody plan --issue <N> # research + implementation plan
50
+ kody research --issue <N> # map repo context, surface gaps
51
+ kody review --pr <N> # structured diff review
52
+ kody ui-review --pr <N> [--preview-url <URL>] # UI review — browses preview via Playwright MCP
53
+ kody classify --issue <N> # pick a flow type (feature/bug/spec/chore)
54
+
55
+ # flow orchestrators (no agent of their own — transition tables)
56
+ kody feature --issue <N> # research → plan → run → review (→ fix)
57
+ kody bug --issue <N> # plan → run → review (→ fix)
58
+ kody spec --issue <N> # research → plan (no code, terminates at plan)
59
+ kody chore --issue <N> # run → review (→ fix)
60
+
61
+ # missions & watches (scheduled, coordinate work via issue state)
62
+ kody mission-scheduler # fans out to per-issue mission-tick
63
+ kody mission-tick --issue <N> # one tick of a kody:mission issue
64
+ kody watch-stale-prs # weekly stale-PR report
65
+
66
+ # deterministic (no agent)
67
+ kody sync --pr <N> # merge default into PR branch
52
68
  kody release --mode prepare|finalize [--bump patch|minor|major] [--dry-run]
53
- kody init [--force] # scaffold consumer repo
54
- kody orchestrate --issue <N> [--flow plan-build-review] # chain plan → run → review → fix
69
+ kody init [--force] # scaffold consumer repo
55
70
 
56
71
  # engine entrypoints
57
- kody ci --issue <N> # CI preflight + auto-dispatch from GHA event
58
- kody chat [--session <id>] # dashboard-driven chat session
72
+ kody ci # auto-dispatches from the GHA event
73
+ kody chat [--session <id>] # dashboard-driven chat session
59
74
  ```
60
75
 
76
+ ### Flow orchestrators
77
+
78
+ Each flow (`feature`, `bug`, `spec`, `chore`) is a declarative transition table: postflight entries dispatch the next executable based on `data.taskState.core.lastOutcome.type` via `runWhen`. No engine changes to add a new flow — drop a new `src/executables/<flow-name>/` with a different table. `classify` picks the flow for an unlabeled issue.
79
+
80
+ ### Missions
81
+
82
+ A **mission** is a stateful, bounded goal expressed as a labeled GitHub issue (`kody:mission`). A **watch** is a stateless repeating loop. A **manager** is a mission whose job happens to be overseeing other missions. All three run on the same scheduled-executable substrate.
83
+
84
+ `mission-scheduler` wakes on cron (default `*/5 * * * *`) or empty `workflow_dispatch`, finds every open `kody:mission` issue, and calls `mission-tick` once per issue. The tick agent reads the issue body (human-owned prose) and a dedicated state comment (bot-owned JSON), decides the next step, and emits a fenced `kody-mission-next-state` block the postflight persists. Children are spawned via `gh workflow run kody.yml` (not `@kody` comments — the default `GITHUB_TOKEN` can dispatch workflows but can't post auto-triggering comments).
85
+
61
86
  ### `ui-review`
62
87
 
63
- `ui-review` adds UI/UX verification to the review surface. It runs the usual diff-based review AND drives the running preview deployment via the Playwright CLI writing a throwaway spec under `.kody/ui-review/`, running it, capturing screenshots, and folding the observed behavior into the review verdict.
88
+ Drives the running preview deployment via the Playwright MCP server alongside the usual diff review.
89
+
90
+ - Preview URL: `--preview-url` → `$PREVIEW_URL` → `http://localhost:3000`. Unreachable → falls back to diff-only.
91
+ - Credentials: `.kody/qa-guide.md` (committed, scaffolded by `kody init` with `CHANGE_ME` placeholders).
92
+ - Auto-discovery: routes, roles, login/admin paths, Payload CMS collections, API routes, env vars — fed to the agent as context.
64
93
 
65
- - Preview URL resolution: `--preview-url` flag → `$PREVIEW_URL` → `http://localhost:3000`.
66
- - Credentials: committed in `.kody/qa-guide.md` (scaffolded by `kody init` when a UI is detected, with `CHANGE_ME` placeholders). The agent reads the guide and uses any credentials it finds.
67
- - Auto-discovery: routes, roles, login page, admin path, Payload CMS collections, API routes, env vars — fed to the agent so it knows *what* to browse without you spelling it out.
68
- - Falls back to a diff-only review when the preview URL is unreachable.
94
+ ### `release`
69
95
 
70
- `kody chat` reads `.kody/sessions/<id>.jsonl`, runs one agent turn, appends
71
- the reply, and writes `chat.message` + `chat.done` events to
72
- `.kody/events/<id>.jsonl` (plus optional HTTP push to a dashboard ingest URL).
73
- Inputs can come from flags or env (`SESSION_ID`, `INIT_MESSAGE`, `MODEL`,
74
- `DASHBOARD_URL`) — the yaml template passes the latter.
96
+ - `--mode prepare` — bumps `package.json`, updates `CHANGELOG.md`, opens a `release/vX.Y.Z` PR. `--bump patch|minor|major` (default `patch`).
97
+ - `--mode finalize` — tags, pushes, runs `prepublishOnly` + `npm publish`, creates a GH release. Runs **automatically** when a `release/vX.Y.Z` PR is merged (via `pull_request: [closed]` in the consumer workflow); manual trigger still works.
75
98
 
76
99
  ## Profiles
77
100
 
78
- A profile is declarative JSON + an adjacent `prompt.md`. See any directory under `src/executables/` for examples. Adding a new command = new directory + profile + prompt + registering any new scripts under `src/scripts/`. No executor, entry, or dispatch changes.
101
+ A profile is declarative JSON + an adjacent `prompt.md`. See any directory under [src/executables/](src/executables/) for examples. Adding a new command = new directory + profile + prompt + any `.sh` scripts + registering any new shared TS utilities under [src/scripts/](src/scripts/). No executor, entry, or dispatch changes.
102
+
103
+ See [AGENTS.md](AGENTS.md) for the full architectural contract.
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.18",
6
+ version: "0.3.20",
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",
@@ -680,8 +680,26 @@ function autoDispatch(opts) {
680
680
  if (eventName === "schedule") {
681
681
  return { executable: "mission-scheduler", cliArgs: {}, target: 0 };
682
682
  }
683
+ if (eventName === "pull_request") {
684
+ const merged = event.pull_request?.merged === true;
685
+ const headRef = String(event.pull_request?.head?.ref ?? "");
686
+ const prNumber = Number(event.pull_request?.number ?? 0);
687
+ if (merged && /^release\/v\d+\.\d+\.\d+/.test(headRef) && prNumber > 0) {
688
+ return {
689
+ executable: "release",
690
+ cliArgs: { mode: "finalize", issue: prNumber },
691
+ target: prNumber
692
+ };
693
+ }
694
+ return null;
695
+ }
683
696
  if (eventName !== "issue_comment") return null;
684
- const body = String(event.comment?.body ?? "").toLowerCase();
697
+ const rawBody = String(event.comment?.body ?? "");
698
+ const authorLogin = String(event.comment?.user?.login ?? "");
699
+ const authorType = String(event.comment?.user?.type ?? "");
700
+ if (!rawBody.toLowerCase().includes("@kody")) return null;
701
+ if (authorLogin === "kody-bot" || authorType === "Bot") return null;
702
+ const body = rawBody.toLowerCase();
685
703
  const targetNum = Number(event.issue?.number ?? 0);
686
704
  const isPr = !!event.issue?.pull_request;
687
705
  if (!targetNum) return null;
@@ -6105,6 +6123,11 @@ async function runCi(argv) {
6105
6123
  } catch {
6106
6124
  }
6107
6125
  const autoFallback = !args.issueNumber ? autoDispatch({ config: earlyConfig }) : null;
6126
+ if (!args.issueNumber && !autoFallback && process.env.GITHUB_EVENT_NAME) {
6127
+ process.stdout.write(`\u2192 kody: no action for event ${process.env.GITHUB_EVENT_NAME} \u2014 exiting cleanly
6128
+ `);
6129
+ return 0;
6130
+ }
6108
6131
  if (!args.issueNumber && !autoFallback) {
6109
6132
  } else {
6110
6133
  args.errors = args.errors.filter((e) => !e.includes("--issue"));
@@ -6367,7 +6390,11 @@ Exit codes:
6367
6390
  `;
6368
6391
  function parseArgs(argv) {
6369
6392
  const result = { command: "help", errors: [] };
6370
- if (argv.length === 0) return result;
6393
+ if (argv.length === 0) {
6394
+ if (process.env.SESSION_ID) return { ...result, command: "chat", chatArgv: [] };
6395
+ if (process.env.GITHUB_EVENT_NAME) return { ...result, command: "ci", ciArgv: [] };
6396
+ return result;
6397
+ }
6371
6398
  const cmd = argv[0];
6372
6399
  if (cmd === "help" || cmd === "--help" || cmd === "-h") return { ...result, command: "help" };
6373
6400
  if (cmd === "version" || cmd === "--version" || cmd === "-v") return { ...result, command: "version" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.3.18",
3
+ "version": "0.3.20",
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",
@@ -1,13 +1,9 @@
1
1
  # Drop this file at .github/workflows/kody.yml in your repo.
2
2
  #
3
- # Two triggers, two modes:
4
- # - issue_comment / workflow_dispatch with issue_number `kody ci`
5
- # (the @kody issue/PR automation flow)
6
- # - workflow_dispatch with sessionId → `kody chat`
7
- # (dashboard-driven Gemini chat session)
8
- #
9
- # All orchestration lives in the kody npm package; future capabilities ship
10
- # via `npm publish`, not by editing this file.
3
+ # Triggers forward every relevant event to `kody`; the engine decides what
4
+ # (if anything) to do. The job runs `npx kody` — no shell branching, no
5
+ # routing logic in YAML. All orchestration lives in the kody npm package;
6
+ # future capabilities ship via `npm publish`, not by editing this file.
11
7
  #
12
8
  # Required repo secrets: at least one model provider key (e.g. MINIMAX_API_KEY,
13
9
  # ANTHROPIC_API_KEY). kody reads any *_API_KEY secret automatically via
@@ -49,15 +45,12 @@ on:
49
45
  default: ""
50
46
  issue_comment:
51
47
  types: [created]
48
+ pull_request:
49
+ types: [closed]
52
50
 
53
51
  jobs:
54
52
  run:
55
- if: >-
56
- ${{ github.event_name == 'workflow_dispatch' ||
57
- (github.event_name == 'issue_comment' &&
58
- contains(github.event.comment.body, '@kody') &&
59
- github.event.comment.user.login != 'kody-bot' &&
60
- github.event.comment.user.type != 'Bot') }}
53
+ if: ${{ github.event_name != 'pull_request' || github.event.pull_request.merged == true }}
61
54
  runs-on: ubuntu-latest
62
55
  timeout-minutes: 360
63
56
  concurrency:
@@ -71,6 +64,7 @@ jobs:
71
64
  - uses: actions/checkout@v4
72
65
  with:
73
66
  fetch-depth: 0
67
+ ref: ${{ github.event.pull_request.base.ref || github.ref }}
74
68
  token: ${{ secrets.KODY_TOKEN || github.token }}
75
69
 
76
70
  - uses: actions/setup-node@v4
@@ -92,9 +86,4 @@ jobs:
92
86
  INIT_MESSAGE: ${{ inputs.message }}
93
87
  MODEL: ${{ inputs.model }}
94
88
  DASHBOARD_URL: ${{ inputs.dashboardUrl }}
95
- run: |
96
- if [ -n "$SESSION_ID" ]; then
97
- npx -y -p @kody-ade/kody-engine@latest kody chat
98
- else
99
- npx -y -p @kody-ade/kody-engine@latest kody ci
100
- fi
89
+ run: npx -y -p @kody-ade/kody-engine@latest kody