@kody-ade/engine 0.1.0
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/LICENSE +21 -0
- package/README.md +322 -0
- package/dist/agent-runner.d.ts +4 -0
- package/dist/agent-runner.js +122 -0
- package/dist/bin/cli.js +11276 -0
- package/dist/ci/parse-inputs.d.ts +6 -0
- package/dist/ci/parse-inputs.js +76 -0
- package/dist/ci/parse-safety.d.ts +6 -0
- package/dist/ci/parse-safety.js +22 -0
- package/dist/cli/args.d.ts +13 -0
- package/dist/cli/args.js +42 -0
- package/dist/cli/litellm.d.ts +2 -0
- package/dist/cli/litellm.js +85 -0
- package/dist/cli/task-resolution.d.ts +2 -0
- package/dist/cli/task-resolution.js +41 -0
- package/dist/config.d.ts +49 -0
- package/dist/config.js +72 -0
- package/dist/context.d.ts +4 -0
- package/dist/context.js +83 -0
- package/dist/definitions.d.ts +3 -0
- package/dist/definitions.js +59 -0
- package/dist/entry.d.ts +1 -0
- package/dist/entry.js +236 -0
- package/dist/git-utils.d.ts +13 -0
- package/dist/git-utils.js +174 -0
- package/dist/github-api.d.ts +14 -0
- package/dist/github-api.js +114 -0
- package/dist/kody-utils.d.ts +1 -0
- package/dist/kody-utils.js +9 -0
- package/dist/learning/auto-learn.d.ts +2 -0
- package/dist/learning/auto-learn.js +169 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.js +51 -0
- package/dist/memory.d.ts +1 -0
- package/dist/memory.js +20 -0
- package/dist/observer.d.ts +9 -0
- package/dist/observer.js +80 -0
- package/dist/pipeline/complexity.d.ts +3 -0
- package/dist/pipeline/complexity.js +12 -0
- package/dist/pipeline/executor-registry.d.ts +3 -0
- package/dist/pipeline/executor-registry.js +20 -0
- package/dist/pipeline/hooks.d.ts +17 -0
- package/dist/pipeline/hooks.js +110 -0
- package/dist/pipeline/questions.d.ts +2 -0
- package/dist/pipeline/questions.js +44 -0
- package/dist/pipeline/runner-selection.d.ts +2 -0
- package/dist/pipeline/runner-selection.js +13 -0
- package/dist/pipeline/state.d.ts +4 -0
- package/dist/pipeline/state.js +37 -0
- package/dist/pipeline.d.ts +3 -0
- package/dist/pipeline.js +213 -0
- package/dist/preflight.d.ts +1 -0
- package/dist/preflight.js +69 -0
- package/dist/retrospective.d.ts +26 -0
- package/dist/retrospective.js +211 -0
- package/dist/stages/agent.d.ts +2 -0
- package/dist/stages/agent.js +94 -0
- package/dist/stages/gate.d.ts +2 -0
- package/dist/stages/gate.js +32 -0
- package/dist/stages/review.d.ts +2 -0
- package/dist/stages/review.js +32 -0
- package/dist/stages/ship.d.ts +3 -0
- package/dist/stages/ship.js +154 -0
- package/dist/stages/verify.d.ts +2 -0
- package/dist/stages/verify.js +94 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.js +1 -0
- package/dist/validators.d.ts +8 -0
- package/dist/validators.js +42 -0
- package/dist/verify-runner.d.ts +11 -0
- package/dist/verify-runner.js +110 -0
- package/kody.config.schema.json +299 -0
- package/package.json +39 -0
- package/prompts/autofix.md +52 -0
- package/prompts/build.md +26 -0
- package/prompts/decompose.md +77 -0
- package/prompts/plan.md +65 -0
- package/prompts/review-fix.md +27 -0
- package/prompts/review.md +115 -0
- package/prompts/taskify-ticket.md +122 -0
- package/prompts/taskify.md +70 -0
- package/templates/kody-watch.yml +57 -0
- package/templates/kody.yml +450 -0
- package/templates/watch-agents/branch-cleanup/agent.json +7 -0
- package/templates/watch-agents/branch-cleanup/agent.md +13 -0
- package/templates/watch-agents/dependency-checker/agent.json +7 -0
- package/templates/watch-agents/dependency-checker/agent.md +14 -0
- package/templates/watch-agents/readme-health/agent.json +7 -0
- package/templates/watch-agents/readme-health/agent.md +17 -0
- package/templates/watch-agents/stale-pr-reviewer/agent.json +7 -0
- package/templates/watch-agents/stale-pr-reviewer/agent.md +13 -0
- package/templates/watch-agents/todo-scanner/agent.json +7 -0
- package/templates/watch-agents/todo-scanner/agent.md +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aharon Yair Cohen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# Kody ADE Engine
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@kody-ade/kody-engine-lite)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
**Comment `@kody` on a GitHub issue. Get back a tested, reviewed PR. Free and open source.**
|
|
7
|
+
|
|
8
|
+
Kody wraps Claude Code with a 7-stage autonomous pipeline — classify, plan, build, verify, review, fix, ship — with quality gates between every stage. If verify catches a bug, it gets fixed before review ever sees it. No blind retries, no context drift, no babysitting.
|
|
9
|
+
|
|
10
|
+
- **Repo-aware prompts** — `bootstrap` analyzes your codebase and generates customized instructions for every stage, not generic "write clean code" prompts
|
|
11
|
+
- **Quality gates** — runs your repo's typecheck, tests, and lint between stages + AI code review in a fresh session
|
|
12
|
+
- **AI failure diagnosis** — classifies errors as fixable/infrastructure/pre-existing before retrying
|
|
13
|
+
- **Self-improving** — learns conventions, remembers architectural decisions, discovers existing patterns
|
|
14
|
+
- **Runs anywhere** — locally from your terminal or via GitHub Actions
|
|
15
|
+
- **Anthropic-compatible models** — Anthropic natively, or other providers (MiniMax, Gemini, etc.) via LiteLLM proxy
|
|
16
|
+
|
|
17
|
+
[Why Kody? →](docs/ABOUT.md) · [Full comparison →](docs/COMPARISON.md)
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="assets/pipeline.svg" alt="Kody 7-stage pipeline: Taskify → Plan → Build → Verify → Review → Review-Fix → Ship" width="600">
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
**Prerequisites:** A GitHub repo + an Anthropic API key (or [compatible provider](docs/LITELLM.md) key).
|
|
26
|
+
|
|
27
|
+
For local CLI usage, you also need: Node.js >= 22, [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code), [GitHub CLI](https://cli.github.com/), git.
|
|
28
|
+
|
|
29
|
+
### 1. Set up GitHub
|
|
30
|
+
|
|
31
|
+
Add your API key as a secret — via [GitHub web UI](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository) or CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gh secret set ANTHROPIC_API_KEY --repo owner/repo
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then in GitHub: **Settings → Actions → General → "Allow GitHub Actions to create and approve pull requests"**
|
|
38
|
+
|
|
39
|
+
### 2. Initialize
|
|
40
|
+
|
|
41
|
+
Copy the [workflow template](templates/kody.yml) to `.github/workflows/kody.yml` and add a `kody.config.json` to your repo root. Or use the CLI to auto-generate both:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install -g @kody-ade/kody-engine-lite
|
|
45
|
+
cd your-project
|
|
46
|
+
kody-engine-lite init
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 3. Bootstrap
|
|
50
|
+
|
|
51
|
+
Create a new GitHub issue (e.g., "Setup Kody") and comment:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
@kody bootstrap
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This analyzes your codebase with an LLM and generates:
|
|
58
|
+
- **Project memory** (`.kody/memory/` — architecture and conventions)
|
|
59
|
+
- **Customized step files** (`.kody/steps/` — repo-aware prompts for every stage)
|
|
60
|
+
- **Tools template** (`.kody/tools.yml` — configure external tools like Playwright, see [Tools](docs/TOOLS.md))
|
|
61
|
+
- **GitHub labels** for lifecycle tracking (14 labels)
|
|
62
|
+
|
|
63
|
+
### 4. Use
|
|
64
|
+
|
|
65
|
+
Comment on any GitHub issue:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
@kody
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Kody picks up the issue and works through the pipeline autonomously:
|
|
72
|
+
|
|
73
|
+
<div align="center">
|
|
74
|
+
<picture>
|
|
75
|
+
<img src="assets/screenshots/kody-trigger.png" alt="GitHub issue showing @kody trigger, pipeline started comment, and complexity detection" width="680">
|
|
76
|
+
</picture>
|
|
77
|
+
<br><sub>▲ Comment <code>@kody</code> on an issue — pipeline starts automatically</sub>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<br>
|
|
81
|
+
|
|
82
|
+
You'll see labels updating in real-time, progress comments at each stage, and a pipeline summary when done:
|
|
83
|
+
|
|
84
|
+
<div align="center">
|
|
85
|
+
<picture>
|
|
86
|
+
<img src="assets/screenshots/kody-summary.png" alt="Pipeline summary table showing all stages completed with duration and retries" width="680">
|
|
87
|
+
</picture>
|
|
88
|
+
<br><sub>▲ Pipeline summary — all stages completed with duration and retries</sub>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<br>
|
|
92
|
+
|
|
93
|
+
The result is a PR with a rich description, passing quality checks, and `Closes #N`:
|
|
94
|
+
|
|
95
|
+
<div align="center">
|
|
96
|
+
<picture>
|
|
97
|
+
<img src="assets/screenshots/kody-pr.png" alt="Pull request created by Kody with description, scope, verify status, and Closes link" width="680">
|
|
98
|
+
</picture>
|
|
99
|
+
<br><sub>▲ PR created by Kody — description, scope, verify status, Closes #N</sub>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
If the task is HIGH-risk, Kody pauses after planning and asks for approval before writing code.
|
|
103
|
+
|
|
104
|
+
### Switch to a different model (optional)
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
// kody.config.json
|
|
108
|
+
{ "agent": { "provider": "minimax" } }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
# .env
|
|
113
|
+
ANTHROPIC_COMPATIBLE_API_KEY=your-key-here
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Kody auto-starts the LiteLLM proxy. [Full LiteLLM guide →](docs/LITELLM.md)
|
|
117
|
+
|
|
118
|
+
## Which command should I use?
|
|
119
|
+
|
|
120
|
+
```mermaid
|
|
121
|
+
flowchart TD
|
|
122
|
+
Start(("What do you\nneed to do?")):::start
|
|
123
|
+
|
|
124
|
+
Start --> NewIssue{"New issue\n→ PR?"}
|
|
125
|
+
Start --> ExistingPR{"Existing\nPR?"}
|
|
126
|
+
Start --> Setup{"Setup /\nOnboarding?"}
|
|
127
|
+
|
|
128
|
+
NewIssue -->|"Simple/medium"| Kody["**@kody**\nFull pipeline: taskify → plan →\nbuild → verify → review → ship"]:::cmd
|
|
129
|
+
NewIssue -->|"Complex multi-area"| Decompose["**@kody decompose**\nParallel sub-tasks: analyze →\nsplit → parallel build → merge → ship"]:::cmd
|
|
130
|
+
|
|
131
|
+
ExistingPR --> PRWhat{"What's wrong?"}
|
|
132
|
+
|
|
133
|
+
PRWhat -->|"Need a code review"| Review["**@kody review**\nStandalone PR review with\nstructured findings + verdict"]:::cmd
|
|
134
|
+
PRWhat -->|"Human gave feedback"| Fix["**@kody fix**\nRe-run from build with\nPR feedback as context"]:::cmd
|
|
135
|
+
PRWhat -->|"CI is failing"| FixCI["**@kody fix-ci**\nFetch CI logs, diagnose,\nand push a fix"]:::cmd
|
|
136
|
+
PRWhat -->|"Merge conflicts"| Resolve["**@kody resolve**\nMerge default branch,\nAI-resolve conflicts, verify"]:::cmd
|
|
137
|
+
PRWhat -->|"Previous run failed\nor was paused"| Rerun["**@kody rerun**\nResume from failed/paused stage\n*--from stage* to pick stage"]:::cmd
|
|
138
|
+
|
|
139
|
+
Setup -->|"First time"| Init["**kody-engine-lite init**\nGenerate workflow + config"]:::setup
|
|
140
|
+
Init --> Bootstrap
|
|
141
|
+
Setup -->|"After major refactor"| Bootstrap["**@kody bootstrap**\nRegenerate memory +\nstep files + labels"]:::setup
|
|
142
|
+
|
|
143
|
+
Kody -.->|"Paused with\nquestions or\nrisk gate?"| Approve["**@kody approve**\nResume after pause"]:::cmd
|
|
144
|
+
|
|
145
|
+
classDef start fill:#1a1a2e,stroke:#e94560,color:#fff,stroke-width:2px
|
|
146
|
+
classDef cmd fill:#0f3460,stroke:#53d8fb,color:#fff,stroke-width:1px
|
|
147
|
+
classDef setup fill:#1a1a2e,stroke:#e9b44c,color:#fff,stroke-width:1px
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Commands
|
|
151
|
+
|
|
152
|
+
| Command | What it does |
|
|
153
|
+
|---------|-------------|
|
|
154
|
+
| `@kody` | Run full pipeline on an issue |
|
|
155
|
+
| `@kody decompose` | Parallel sub-tasks for complex issues — analyze, split, build in parallel, merge, verify, review, ship ([details](docs/DECOMPOSE.md)) |
|
|
156
|
+
| `@kody compose` | Retry merge + verify + review + ship after a decompose build succeeded |
|
|
157
|
+
| `@kody review` | Review any PR — structured findings + GitHub approve/request-changes (falls back to comment if self-review blocked) |
|
|
158
|
+
| `@kody fix` | Re-run from build with human PR feedback + Kody's review as context |
|
|
159
|
+
| `@kody fix-ci` | Fix failing CI checks (auto-triggered with loop guard) |
|
|
160
|
+
| `@kody resolve` | Merge default branch into PR, AI-resolve conflicts, verify, push |
|
|
161
|
+
| `@kody rerun` | Resume from failed or paused stage |
|
|
162
|
+
| `@kody rerun --from <stage>` | Resume from a specific stage |
|
|
163
|
+
| `@kody approve` | Resume after questions or risk gate |
|
|
164
|
+
| `@kody bootstrap` | Regenerate project memory and step files |
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
kody-engine-lite init [--force] # Setup repo: workflow + config + watch
|
|
168
|
+
kody-engine-lite bootstrap [--force] # Generate memory + step files + labels + digest issue
|
|
169
|
+
kody-engine-lite run --issue-number 42 --local --cwd ./project
|
|
170
|
+
kody-engine-lite run --task "Add retry utility" --local
|
|
171
|
+
kody-engine-lite review --pr-number 42 # Standalone PR review
|
|
172
|
+
kody-engine-lite fix --issue-number 42 --feedback "Use middleware pattern"
|
|
173
|
+
kody-engine-lite fix-ci --pr-number 42
|
|
174
|
+
kody-engine-lite resolve --pr-number 42 # Merge + resolve conflicts
|
|
175
|
+
kody-engine-lite decompose --issue-number 42 # Parallel sub-tasks for complex issues
|
|
176
|
+
kody-engine-lite compose --task-id <id> # Retry compose after decompose
|
|
177
|
+
kody-engine-lite rerun --issue-number 42 --from verify
|
|
178
|
+
kody-engine-lite watch [--dry-run] # Run health monitoring locally
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
[Full CLI reference with all flags and options →](docs/CLI.md)
|
|
182
|
+
|
|
183
|
+
## Key Features
|
|
184
|
+
|
|
185
|
+
- **Repo-Aware Step Files** — auto-generated prompts with your repo's patterns, gaps, and acceptance criteria ([details](docs/FEATURES.md#repo-aware-step-files-kodysteps))
|
|
186
|
+
- **Standalone PR Review** — `@kody review` on any PR for structured code review with GitHub approve/request-changes ([details](docs/FEATURES.md#standalone-pr-review))
|
|
187
|
+
- **Shared Sessions** — stages share Claude Code sessions, no cold-start re-exploration ([details](docs/FEATURES.md#shared-sessions))
|
|
188
|
+
- **Risk Gate** — HIGH-risk tasks pause for human approval before building ([details](docs/FEATURES.md#risk-gate))
|
|
189
|
+
- **AI Failure Diagnosis** — classifies errors as fixable/infrastructure/pre-existing/abort before retry ([details](docs/FEATURES.md#ai-powered-failure-diagnosis))
|
|
190
|
+
- **Question Gates** — asks product/architecture questions when the task is unclear ([details](docs/FEATURES.md#question-gates))
|
|
191
|
+
- **Auto Fix-CI** — CI fails on a PR? Kody fetches logs, diagnoses, and pushes a fix ([details](docs/FEATURES.md#auto-fix-ci))
|
|
192
|
+
- **Parallel Decomposition** — complex tasks auto-split into independent sub-tasks that build in parallel, then merge and verify ([details](docs/DECOMPOSE.md))
|
|
193
|
+
- **Pattern Discovery** — searches for existing patterns before proposing new ones ([details](docs/FEATURES.md#pattern-discovery))
|
|
194
|
+
- **Decision Memory** — architectural decisions extracted from reviews persist across tasks ([details](docs/FEATURES.md#decision-memory))
|
|
195
|
+
- **Auto-Learning** — extracts coding conventions from each successful run ([details](docs/FEATURES.md#auto-learning-memory))
|
|
196
|
+
- **Retrospective** — analyzes each run, identifies patterns, suggests improvements ([details](docs/FEATURES.md#retrospective-system))
|
|
197
|
+
- **Kody Watch** — periodic health monitoring: pipeline health, security scanning, config validation every 30 min ([setup guide](docs/WATCH.md))
|
|
198
|
+
- **Anthropic-Compatible Models** — route through LiteLLM to use other providers like MiniMax, Gemini, etc. ([setup guide](docs/LITELLM.md) · [model test results](docs/model-compatibility.md))
|
|
199
|
+
|
|
200
|
+
## Architecture
|
|
201
|
+
|
|
202
|
+
<details>
|
|
203
|
+
<summary>System overview (click to expand)</summary>
|
|
204
|
+
|
|
205
|
+
```mermaid
|
|
206
|
+
flowchart TB
|
|
207
|
+
subgraph trigger ["Trigger"]
|
|
208
|
+
direction LR
|
|
209
|
+
Comment["@kody comment\non GitHub issue"]
|
|
210
|
+
Dispatch["workflow_dispatch\n(manual)"]
|
|
211
|
+
CLI["kody-engine-lite run\n(local CLI)"]
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
subgraph ci ["GitHub Actions"]
|
|
215
|
+
direction LR
|
|
216
|
+
Parse["**parse**\nValidate author\nExtract mode + task ID"]
|
|
217
|
+
Orchestrate["**orchestrate**\nCheckout, install deps,\nstart LiteLLM proxy"]
|
|
218
|
+
Parse --> Orchestrate
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
Entry["**entry.ts**\nPreflight checks → fetch issue →\ncreate runners → build context"]
|
|
222
|
+
|
|
223
|
+
subgraph pipeline ["Pipeline (pipeline.ts)"]
|
|
224
|
+
direction TB
|
|
225
|
+
|
|
226
|
+
subgraph explore ["Session: explore"]
|
|
227
|
+
direction LR
|
|
228
|
+
Taskify["**1 Taskify**\nClassify, scope,\ndetect complexity\n*→ task.json*"]
|
|
229
|
+
Plan["**2 Plan**\nTDD plan with\ndeep reasoning\n*→ plan.md*"]
|
|
230
|
+
Taskify --> Plan
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
subgraph build_session ["Session: build"]
|
|
234
|
+
direction LR
|
|
235
|
+
Build["**3 Build**\nImplement via\nClaude Code tools"]
|
|
236
|
+
Autofix["**Autofix**\nAI-diagnosed\nerror fixes"]
|
|
237
|
+
ReviewFix["**6 Review-Fix**\nFix Critical +\nMajor findings"]
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
subgraph verify_loop ["Quality Gate"]
|
|
241
|
+
Verify["**4 Verify**\ntypecheck + tests + lint"]
|
|
242
|
+
Diagnose{"Fail?"}
|
|
243
|
+
Verify --> Diagnose
|
|
244
|
+
Diagnose -->|"fixable"| Autofix
|
|
245
|
+
Autofix --> Verify
|
|
246
|
+
Diagnose -->|"infra/pre-existing"| Skip["Skip\n(mark passed)"]
|
|
247
|
+
Diagnose -->|"abort"| Abort["Stop pipeline"]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
subgraph review_session ["Session: review (fresh — no build bias)"]
|
|
251
|
+
Review["**5 Review**\nPASS/FAIL verdict\n+ findings\n*→ review.md*"]
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
Ship["**7 Ship**\nPush branch → create PR\n→ comment on issue"]
|
|
255
|
+
|
|
256
|
+
explore --> build_session
|
|
257
|
+
Build --> verify_loop
|
|
258
|
+
Skip --> review_session
|
|
259
|
+
Diagnose -->|"pass"| review_session
|
|
260
|
+
review_session -->|"FAIL"| ReviewFix
|
|
261
|
+
ReviewFix -->|"retry review\n(max 2)"| review_session
|
|
262
|
+
review_session -->|"PASS"| Ship
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
subgraph support ["Support Systems"]
|
|
266
|
+
direction LR
|
|
267
|
+
Memory["**.kody/memory/**\narchitecture.md\nconventions.md\nobserver-log.jsonl"]
|
|
268
|
+
Steps["**.kody/steps/**\nRepo-customized\nprompts per stage"]
|
|
269
|
+
State["**status.json**\nStage states +\nsession IDs"]
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
subgraph outputs ["Outputs"]
|
|
273
|
+
direction LR
|
|
274
|
+
PR["Pull Request\nwith Closes #N"]
|
|
275
|
+
Labels["GitHub Labels\nkody:planning → kody:done"]
|
|
276
|
+
Artifacts["Task Artifacts\n.kody/tasks/id/"]
|
|
277
|
+
Learn["Auto-Learn\n+ Retrospective"]
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
QuestionGate{"Questions?\nPause for\nhuman input"}
|
|
281
|
+
RiskGate{"HIGH risk?\nPause for\napproval"}
|
|
282
|
+
|
|
283
|
+
Comment --> ci
|
|
284
|
+
Dispatch --> Orchestrate
|
|
285
|
+
CLI --> Entry
|
|
286
|
+
Orchestrate --> Entry
|
|
287
|
+
Entry --> pipeline
|
|
288
|
+
|
|
289
|
+
Taskify -.-> QuestionGate
|
|
290
|
+
Plan -.-> RiskGate
|
|
291
|
+
QuestionGate -.->|"@kody approve"| Plan
|
|
292
|
+
RiskGate -.->|"@kody approve"| Build
|
|
293
|
+
|
|
294
|
+
pipeline <-..-> support
|
|
295
|
+
Ship --> outputs
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
</details>
|
|
299
|
+
|
|
300
|
+
[Full architecture docs →](docs/ARCHITECTURE.md)
|
|
301
|
+
|
|
302
|
+
## Documentation
|
|
303
|
+
|
|
304
|
+
**Understand Kody:** [About](docs/ABOUT.md) · [Architecture](docs/ARCHITECTURE.md) · [Tech Stack](docs/TECH-STACK.md) · [Features](docs/FEATURES.md) · [Pipeline](docs/PIPELINE.md) · [Comparison](docs/COMPARISON.md)
|
|
305
|
+
|
|
306
|
+
**Set up & use:** [CLI](docs/CLI.md) · [Configuration](docs/CONFIGURATION.md) · [Bootstrap](docs/BOOTSTRAP.md) · [Decompose](docs/DECOMPOSE.md) · [Tools](docs/TOOLS.md) · [Watch](docs/WATCH.md) · [LiteLLM](docs/LITELLM.md)
|
|
307
|
+
|
|
308
|
+
**Reference:** [FAQ](docs/FAQ.md) · [Model Compatibility](docs/model-compatibility.md)
|
|
309
|
+
|
|
310
|
+
## Generating Demo GIFs
|
|
311
|
+
|
|
312
|
+
Demo GIFs can be generated using [VHS](https://github.com/charmbracelet/vhs). Tape files are in `assets/tapes/`:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
brew install vhs # install VHS
|
|
316
|
+
vhs assets/tapes/init.tape # → assets/demo-init.gif
|
|
317
|
+
vhs assets/tapes/run-local.tape # → assets/demo-run.gif (runs a real pipeline)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## License
|
|
321
|
+
|
|
322
|
+
MIT
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { spawn, execFileSync } from "child_process";
|
|
2
|
+
const SIGKILL_GRACE_MS = 5000;
|
|
3
|
+
const STDERR_TAIL_CHARS = 500;
|
|
4
|
+
function writeStdin(child, prompt) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
if (!child.stdin) {
|
|
7
|
+
resolve();
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
child.stdin.write(prompt, (err) => {
|
|
11
|
+
if (err)
|
|
12
|
+
reject(err);
|
|
13
|
+
else {
|
|
14
|
+
child.stdin.end();
|
|
15
|
+
resolve();
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function waitForProcess(child, timeout) {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const stdoutChunks = [];
|
|
23
|
+
const stderrChunks = [];
|
|
24
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
25
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
child.kill("SIGTERM");
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
if (!child.killed)
|
|
30
|
+
child.kill("SIGKILL");
|
|
31
|
+
}, SIGKILL_GRACE_MS);
|
|
32
|
+
}, timeout);
|
|
33
|
+
child.on("exit", (code) => {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
resolve({
|
|
36
|
+
code,
|
|
37
|
+
stdout: Buffer.concat(stdoutChunks).toString(),
|
|
38
|
+
stderr: Buffer.concat(stderrChunks).toString(),
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
child.on("error", (err) => {
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
resolve({ code: -1, stdout: "", stderr: err.message });
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async function runSubprocess(command, args, prompt, timeout, options) {
|
|
48
|
+
const child = spawn(command, args, {
|
|
49
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
50
|
+
env: {
|
|
51
|
+
...process.env,
|
|
52
|
+
SKIP_BUILD: "1",
|
|
53
|
+
SKIP_HOOKS: "1",
|
|
54
|
+
...options?.env,
|
|
55
|
+
},
|
|
56
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
await writeStdin(child, prompt);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return {
|
|
63
|
+
outcome: "failed",
|
|
64
|
+
error: `Failed to send prompt: ${err instanceof Error ? err.message : String(err)}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const { code, stdout, stderr } = await waitForProcess(child, timeout);
|
|
68
|
+
if (code === 0) {
|
|
69
|
+
return { outcome: "completed", output: stdout };
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
outcome: code === null ? "timed_out" : "failed",
|
|
73
|
+
error: `Exit code ${code}\n${stderr.slice(-STDERR_TAIL_CHARS)}`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function checkCommand(command, args) {
|
|
77
|
+
try {
|
|
78
|
+
execFileSync(command, args, { timeout: 10_000, stdio: "pipe" });
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// ─── Claude Code Runner ──────────────────────────────────────────────────────
|
|
86
|
+
export function createClaudeCodeRunner() {
|
|
87
|
+
return {
|
|
88
|
+
async run(_stageName, prompt, model, timeout, _taskDir, options) {
|
|
89
|
+
return runSubprocess("claude", [
|
|
90
|
+
"--print",
|
|
91
|
+
"--model", model,
|
|
92
|
+
"--dangerously-skip-permissions",
|
|
93
|
+
"--allowedTools", "Bash,Edit,Read,Write,Glob,Grep",
|
|
94
|
+
], prompt, timeout, options);
|
|
95
|
+
},
|
|
96
|
+
async healthCheck() {
|
|
97
|
+
return checkCommand("claude", ["--version"]);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// ─── Runner Factory ──────────────────────────────────────────────────────────
|
|
102
|
+
const RUNNER_FACTORIES = {
|
|
103
|
+
"claude-code": createClaudeCodeRunner,
|
|
104
|
+
};
|
|
105
|
+
export function createRunners(config) {
|
|
106
|
+
// New multi-runner config
|
|
107
|
+
if (config.agent.runners && Object.keys(config.agent.runners).length > 0) {
|
|
108
|
+
const runners = {};
|
|
109
|
+
for (const [name, runnerConfig] of Object.entries(config.agent.runners)) {
|
|
110
|
+
const factory = RUNNER_FACTORIES[runnerConfig.type];
|
|
111
|
+
if (factory) {
|
|
112
|
+
runners[name] = factory();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return runners;
|
|
116
|
+
}
|
|
117
|
+
// Legacy single-runner fallback
|
|
118
|
+
const runnerType = config.agent.runner ?? "claude-code";
|
|
119
|
+
const factory = RUNNER_FACTORIES[runnerType];
|
|
120
|
+
const defaultName = config.agent.defaultRunner ?? "claude";
|
|
121
|
+
return { [defaultName]: factory ? factory() : createClaudeCodeRunner() };
|
|
122
|
+
}
|