@kody-ade/kody-engine-lite 0.1.150 → 0.1.152

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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +183 -29
  3. package/dist/bin/cli.js +34 -14
  4. package/kody.config.schema.json +0 -10
  5. package/package.json +1 -1
  6. package/prompts/taskify.md +2 -2
  7. package/templates/kody-watch.yml +13 -1
  8. package/dist/agent-runner.d.ts +0 -4
  9. package/dist/agent-runner.js +0 -122
  10. package/dist/ci/parse-inputs.d.ts +0 -6
  11. package/dist/ci/parse-inputs.js +0 -76
  12. package/dist/ci/parse-safety.d.ts +0 -6
  13. package/dist/ci/parse-safety.js +0 -22
  14. package/dist/cli/args.d.ts +0 -13
  15. package/dist/cli/args.js +0 -42
  16. package/dist/cli/litellm.d.ts +0 -2
  17. package/dist/cli/litellm.js +0 -85
  18. package/dist/cli/task-resolution.d.ts +0 -2
  19. package/dist/cli/task-resolution.js +0 -41
  20. package/dist/config.d.ts +0 -49
  21. package/dist/config.js +0 -72
  22. package/dist/context.d.ts +0 -4
  23. package/dist/context.js +0 -83
  24. package/dist/definitions.d.ts +0 -3
  25. package/dist/definitions.js +0 -59
  26. package/dist/entry.d.ts +0 -1
  27. package/dist/entry.js +0 -236
  28. package/dist/git-utils.d.ts +0 -13
  29. package/dist/git-utils.js +0 -174
  30. package/dist/github-api.d.ts +0 -14
  31. package/dist/github-api.js +0 -114
  32. package/dist/kody-utils.d.ts +0 -1
  33. package/dist/kody-utils.js +0 -9
  34. package/dist/learning/auto-learn.d.ts +0 -2
  35. package/dist/learning/auto-learn.js +0 -169
  36. package/dist/logger.d.ts +0 -14
  37. package/dist/logger.js +0 -51
  38. package/dist/memory.d.ts +0 -1
  39. package/dist/memory.js +0 -20
  40. package/dist/observer.d.ts +0 -9
  41. package/dist/observer.js +0 -80
  42. package/dist/pipeline/complexity.d.ts +0 -3
  43. package/dist/pipeline/complexity.js +0 -12
  44. package/dist/pipeline/executor-registry.d.ts +0 -3
  45. package/dist/pipeline/executor-registry.js +0 -20
  46. package/dist/pipeline/hooks.d.ts +0 -17
  47. package/dist/pipeline/hooks.js +0 -110
  48. package/dist/pipeline/questions.d.ts +0 -2
  49. package/dist/pipeline/questions.js +0 -44
  50. package/dist/pipeline/runner-selection.d.ts +0 -2
  51. package/dist/pipeline/runner-selection.js +0 -13
  52. package/dist/pipeline/state.d.ts +0 -4
  53. package/dist/pipeline/state.js +0 -37
  54. package/dist/pipeline.d.ts +0 -3
  55. package/dist/pipeline.js +0 -213
  56. package/dist/preflight.d.ts +0 -1
  57. package/dist/preflight.js +0 -69
  58. package/dist/retrospective.d.ts +0 -26
  59. package/dist/retrospective.js +0 -211
  60. package/dist/stages/agent.d.ts +0 -2
  61. package/dist/stages/agent.js +0 -94
  62. package/dist/stages/gate.d.ts +0 -2
  63. package/dist/stages/gate.js +0 -32
  64. package/dist/stages/review.d.ts +0 -2
  65. package/dist/stages/review.js +0 -32
  66. package/dist/stages/ship.d.ts +0 -3
  67. package/dist/stages/ship.js +0 -154
  68. package/dist/stages/verify.d.ts +0 -2
  69. package/dist/stages/verify.js +0 -94
  70. package/dist/types.d.ts +0 -61
  71. package/dist/types.js +0 -1
  72. package/dist/validators.d.ts +0 -8
  73. package/dist/validators.js +0 -42
  74. package/dist/verify-runner.d.ts +0 -11
  75. package/dist/verify-runner.js +0 -110
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 CHANGED
@@ -16,30 +16,9 @@ Kody wraps Claude Code with a 7-stage autonomous pipeline — classify, plan, bu
16
16
 
17
17
  [Why Kody? →](docs/ABOUT.md) · [Full comparison →](docs/COMPARISON.md)
18
18
 
19
- ```
20
- @kody on issue
21
-
22
-
23
- ① TASKIFY ─── classify, scope, detect complexity, ask questions
24
-
25
-
26
- ② PLAN ────── TDD implementation plan (deep reasoning)
27
- │ 🛑 HIGH risk? Pause for human approval
28
-
29
- ③ BUILD ───── implement via Claude Code tools
30
-
31
-
32
- ④ VERIFY ──── run your quality commands (typecheck, tests, lint)
33
- │ ✗ fail → AI diagnosis → autofix → retry
34
-
35
- ⑤ REVIEW ──── AI code review (fresh session, no build bias)
36
-
37
-
38
- ⑥ REVIEW-FIX ─ fix Critical and Major findings
39
-
40
-
41
- ⑦ SHIP ────── push branch, create PR with Closes #N
42
- ```
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>
43
22
 
44
23
  ## Quick Start
45
24
 
@@ -89,10 +68,36 @@ Comment on any GitHub issue:
89
68
  @kody
90
69
  ```
91
70
 
92
- Kody picks up the issue and works through the pipeline autonomously. You'll see:
93
- - Labels updating in real-time: `kody:planning` → `kody:building` → `kody:review` → `kody:done`
94
- - Progress comments on the issue at each stage
95
- - A PR with a rich description, passing quality checks, and `Closes #N`
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>
96
101
 
97
102
  If the task is HIGH-risk, Kody pauses after planning and asks for approval before writing code.
98
103
 
@@ -110,11 +115,45 @@ ANTHROPIC_COMPATIBLE_API_KEY=your-key-here
110
115
 
111
116
  Kody auto-starts the LiteLLM proxy. [Full LiteLLM guide →](docs/LITELLM.md)
112
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
+
113
150
  ## Commands
114
151
 
115
152
  | Command | What it does |
116
153
  |---------|-------------|
117
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 |
118
157
  | `@kody review` | Review any PR — structured findings + GitHub approve/request-changes (falls back to comment if self-review blocked) |
119
158
  | `@kody fix` | Re-run from build with human PR feedback + Kody's review as context |
120
159
  | `@kody fix-ci` | Fix failing CI checks (auto-triggered with loop guard) |
@@ -133,6 +172,8 @@ kody-engine-lite review --pr-number 42 # Standalone PR review
133
172
  kody-engine-lite fix --issue-number 42 --feedback "Use middleware pattern"
134
173
  kody-engine-lite fix-ci --pr-number 42
135
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
136
177
  kody-engine-lite rerun --issue-number 42 --from verify
137
178
  kody-engine-lite watch [--dry-run] # Run health monitoring locally
138
179
  ```
@@ -148,6 +189,7 @@ kody-engine-lite watch [--dry-run] # Run health monitoring locally
148
189
  - **AI Failure Diagnosis** — classifies errors as fixable/infrastructure/pre-existing/abort before retry ([details](docs/FEATURES.md#ai-powered-failure-diagnosis))
149
190
  - **Question Gates** — asks product/architecture questions when the task is unclear ([details](docs/FEATURES.md#question-gates))
150
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))
151
193
  - **Pattern Discovery** — searches for existing patterns before proposing new ones ([details](docs/FEATURES.md#pattern-discovery))
152
194
  - **Decision Memory** — architectural decisions extracted from reviews persist across tasks ([details](docs/FEATURES.md#decision-memory))
153
195
  - **Auto-Learning** — extracts coding conventions from each successful run ([details](docs/FEATURES.md#auto-learning-memory))
@@ -155,14 +197,126 @@ kody-engine-lite watch [--dry-run] # Run health monitoring locally
155
197
  - **Kody Watch** — periodic health monitoring: pipeline health, security scanning, config validation every 30 min ([setup guide](docs/WATCH.md))
156
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))
157
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
+
158
302
  ## Documentation
159
303
 
160
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)
161
305
 
162
- **Set up & use:** [CLI](docs/CLI.md) · [Configuration](docs/CONFIGURATION.md) · [Bootstrap](docs/BOOTSTRAP.md) · [Tools](docs/TOOLS.md) · [Watch](docs/WATCH.md) · [LiteLLM](docs/LITELLM.md)
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)
163
307
 
164
308
  **Reference:** [FAQ](docs/FAQ.md) · [Model Compatibility](docs/model-compatibility.md)
165
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
+
166
320
  ## License
167
321
 
168
322
  MIT
package/dist/bin/cli.js CHANGED
@@ -5622,6 +5622,7 @@ async function executeAgentStage(ctx, def) {
5622
5622
  return { outcome: "completed", retries: 0 };
5623
5623
  }
5624
5624
  const prompt = buildFullPrompt(def.name, ctx.taskId, ctx.taskDir, ctx.projectDir, ctx.input.feedback);
5625
+ const promptTokens = estimateTokens(prompt);
5625
5626
  let currentModelTier = def.modelTier;
5626
5627
  if (ctx.input.feedback && def.name === "build") {
5627
5628
  logger.info(` feedback: ${ctx.input.feedback.slice(0, 200)}${ctx.input.feedback.length > 200 ? "..." : ""}`);
@@ -5653,14 +5654,8 @@ async function executeAgentStage(ctx, def) {
5653
5654
  if (ds && devServerStages.includes(def.name) && taskHasUI(ctx.taskDir)) {
5654
5655
  logger.info(` Starting dev server: ${ds.command}`);
5655
5656
  const envVars = {};
5656
- if (ds.env && ds.env.length > 0) {
5657
- for (const varName of ds.env) {
5658
- if (process.env[varName]) envVars[varName] = process.env[varName];
5659
- }
5660
- } else {
5661
- for (const [k, v] of Object.entries(process.env)) {
5662
- if (v !== void 0) envVars[k] = v;
5663
- }
5657
+ for (const [k, v] of Object.entries(process.env)) {
5658
+ if (v !== void 0) envVars[k] = v;
5664
5659
  }
5665
5660
  devServerHandle = await startDevServer({
5666
5661
  command: ds.command,
@@ -5710,7 +5705,7 @@ async function executeAgentStage(ctx, def) {
5710
5705
  logger.info(` Dev server stopped`);
5711
5706
  }
5712
5707
  if (lastResult.outcome !== "completed") {
5713
- return { outcome: lastResult.outcome, error: lastResult.error, retries };
5708
+ return { outcome: lastResult.outcome, error: lastResult.error, retries, promptTokens };
5714
5709
  }
5715
5710
  const result2 = lastResult;
5716
5711
  if (def.outputFile && result2.output) {
@@ -5772,7 +5767,7 @@ async function executeAgentStage(ctx, def) {
5772
5767
  }
5773
5768
  }
5774
5769
  appendStageContext(ctx.taskDir, def.name, result2.output);
5775
- return { outcome: "completed", outputFile: def.outputFile, retries };
5770
+ return { outcome: "completed", outputFile: def.outputFile, retries, promptTokens };
5776
5771
  }
5777
5772
  function appendStageContext(taskDir, stageName, output) {
5778
5773
  const contextPath = path23.join(taskDir, "context.md");
@@ -5795,6 +5790,7 @@ var init_agent = __esm({
5795
5790
  "src/stages/agent.ts"() {
5796
5791
  "use strict";
5797
5792
  init_context();
5793
+ init_context_tiers();
5798
5794
  init_validators();
5799
5795
  init_config();
5800
5796
  init_mcp_config();
@@ -6968,8 +6964,9 @@ function collectRunContext(ctx, state, pipelineStartTime) {
6968
6964
  const s = state.stages[def.name];
6969
6965
  const duration = computeStageDuration(s);
6970
6966
  const durationStr = duration != null ? `, ${duration}ms` : "";
6967
+ const tokenStr = s.promptTokens != null ? `, ~${s.promptTokens} prompt tokens` : "";
6971
6968
  const errorStr = s.error ? ` \u2014 ${s.error}` : "";
6972
- lines.push(`${def.name}: ${s.state} (${s.retries} retries${durationStr})${errorStr}`);
6969
+ lines.push(`${def.name}: ${s.state} (${s.retries} retries${durationStr}${tokenStr})${errorStr}`);
6973
6970
  if (s.state === "failed" || s.state === "timeout") {
6974
6971
  failedStage = def.name;
6975
6972
  }
@@ -7034,6 +7031,23 @@ function appendRetrospectiveEntry(projectDir, entry) {
7034
7031
  }
7035
7032
  fs34.appendFileSync(logPath, JSON.stringify(entry) + "\n");
7036
7033
  }
7034
+ function computeTokenStats(state, projectDir) {
7035
+ const perStage = {};
7036
+ let totalPromptTokens = 0;
7037
+ let hasAny = false;
7038
+ for (const def of STAGES) {
7039
+ const s = state.stages[def.name];
7040
+ if (s.promptTokens != null) {
7041
+ perStage[def.name] = s.promptTokens;
7042
+ totalPromptTokens += s.promptTokens;
7043
+ hasAny = true;
7044
+ }
7045
+ }
7046
+ if (!hasAny) return void 0;
7047
+ const memory = readProjectMemory(projectDir);
7048
+ const memoryTokens = memory ? estimateTokens(memory) : 0;
7049
+ return { totalPromptTokens, memoryTokens, perStage };
7050
+ }
7037
7051
  async function runRetrospective(ctx, state, pipelineStartTime) {
7038
7052
  if (ctx.input.dryRun) return;
7039
7053
  try {
@@ -7094,6 +7108,7 @@ ${previousText}
7094
7108
  failedStage = def.name;
7095
7109
  }
7096
7110
  }
7111
+ const tokenStats = computeTokenStats(state, ctx.projectDir);
7097
7112
  const entry = {
7098
7113
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7099
7114
  taskId: state.taskId,
@@ -7104,7 +7119,8 @@ ${previousText}
7104
7119
  observation,
7105
7120
  patternMatch,
7106
7121
  suggestion,
7107
- pipelineFlaw
7122
+ pipelineFlaw,
7123
+ tokenStats
7108
7124
  };
7109
7125
  appendRetrospectiveEntry(ctx.projectDir, entry);
7110
7126
  logger.info(`Retrospective: ${observation.slice(0, 120)}`);
@@ -7120,6 +7136,8 @@ var init_retrospective = __esm({
7120
7136
  init_context();
7121
7137
  init_config();
7122
7138
  init_runner_selection();
7139
+ init_memory();
7140
+ init_context_tiers();
7123
7141
  init_logger();
7124
7142
  RETROSPECTIVE_PROMPT = `You are a pipeline retrospective analyst. You observe automated software development pipeline runs and identify flaws, patterns, and improvement opportunities.
7125
7143
 
@@ -7449,7 +7467,8 @@ async function runPipelineInner(ctx) {
7449
7467
  state: "completed",
7450
7468
  completedAt: (/* @__PURE__ */ new Date()).toISOString(),
7451
7469
  retries: result2.retries,
7452
- outputFile: result2.outputFile
7470
+ outputFile: result2.outputFile,
7471
+ promptTokens: result2.promptTokens
7453
7472
  };
7454
7473
  logger.info(`[${def.name}] \u2713 completed`);
7455
7474
  const detected = autoDetectComplexity(ctx, def);
@@ -7467,7 +7486,8 @@ async function runPipelineInner(ctx) {
7467
7486
  state.stages[def.name] = {
7468
7487
  state: isTimeout ? "timeout" : "failed",
7469
7488
  retries: result2.retries,
7470
- error: isTimeout ? "Stage timed out" : result2.error ?? "Stage failed"
7489
+ error: isTimeout ? "Stage timed out" : result2.error ?? "Stage failed",
7490
+ promptTokens: result2.promptTokens
7471
7491
  };
7472
7492
  state.state = "failed";
7473
7493
  state.sessions = ctx.sessions;
@@ -263,11 +263,6 @@
263
263
  "readyTimeout": {
264
264
  "type": "number",
265
265
  "description": "Seconds to wait for the server to be ready. Default: 180"
266
- },
267
- "env": {
268
- "type": "array",
269
- "items": { "type": "string" },
270
- "description": "List of GitHub secret names to forward as environment variables for the dev server process (e.g., ['BLOB_READ_WRITE_TOKEN', 'DATABASE_URL']). These are injected into the workflow env block during 'kody init'."
271
266
  }
272
267
  },
273
268
  "required": ["command", "url"]
@@ -295,11 +290,6 @@
295
290
  "readyTimeout": {
296
291
  "type": "number",
297
292
  "description": "Seconds to wait for the server to be ready. Default: 180"
298
- },
299
- "env": {
300
- "type": "array",
301
- "items": { "type": "string" },
302
- "description": "List of GitHub secret names to forward as environment variables for the dev server process (e.g., ['BLOB_READ_WRITE_TOKEN', 'DATABASE_URL']). These are injected into the workflow env block during 'kody init'."
303
293
  }
304
294
  },
305
295
  "required": ["command", "url"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.150",
3
+ "version": "0.1.152",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -32,8 +32,8 @@ Required JSON format:
32
32
 
33
33
  Risk level heuristics:
34
34
  - low: single file change, no breaking changes, docs, config, isolated scripts, test additions, style changes
35
- - medium: multiple files, possible side effects, API changes, new dependencies, refactoring existing logic
36
- - high: core business logic, data migrations, security, authentication, payment processing, database schema changes
35
+ - medium: 2-3 files, possible side effects, API changes, new dependencies, refactoring existing logic, adding a new utility/middleware with tests
36
+ - high: 4+ files across multiple directories, core business logic, data migrations, security, authentication, payment processing, database schema changes, cross-cutting concerns, system redesigns
37
37
 
38
38
  existing_patterns rules:
39
39
  - List patterns found in the codebase that are relevant to this task
@@ -35,11 +35,23 @@ jobs:
35
35
  - name: Install Kody Engine
36
36
  run: npm install -g @kody-ade/kody-engine-lite
37
37
 
38
+ - name: Export project secrets
39
+ env:
40
+ ALL_SECRETS: ${{ toJSON(secrets) }}
41
+ run: |
42
+ echo "$ALL_SECRETS" | jq -r 'to_entries[] | select(.key | test("^(GITHUB_TOKEN)$") | not) | @json' | while IFS= read -r entry; do
43
+ KEY=$(echo "$entry" | jq -r '.key')
44
+ VALUE=$(echo "$entry" | jq -r '.value')
45
+ DELIM="KODY_EOF_${KEY}"
46
+ echo "${KEY}<<${DELIM}" >> $GITHUB_ENV
47
+ echo "${VALUE}" >> $GITHUB_ENV
48
+ echo "${DELIM}" >> $GITHUB_ENV
49
+ done
50
+
38
51
  - name: Run Kody Watch
39
52
  env:
40
53
  GH_TOKEN: ${{ github.token }}
41
54
  REPO: ${{ github.repository }}
42
55
  WATCH_DIGEST_ISSUE: ${{ vars.WATCH_DIGEST_ISSUE }}
43
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
44
56
  DRY_RUN: ${{ inputs.dry_run || 'false' }}
45
57
  run: npx kody-engine-lite watch ${{ inputs.dry_run == 'true' && '--dry-run' || '' }}
@@ -1,4 +0,0 @@
1
- import type { AgentRunner } from "./types.js";
2
- import type { KodyConfig } from "./config.js";
3
- export declare function createClaudeCodeRunner(): AgentRunner;
4
- export declare function createRunners(config: KodyConfig): Record<string, AgentRunner>;
@@ -1,122 +0,0 @@
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
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Parses @kody / /kody comment body into structured inputs.
3
- * Run by the parse job in GitHub Actions.
4
- * Reads from env, writes to $GITHUB_OUTPUT.
5
- */
6
- export {};