@kody-ade/kody-engine-lite 0.1.90 → 0.1.92

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/cli.js CHANGED
@@ -145,6 +145,22 @@ var init_agent_runner = __esm({
145
145
  });
146
146
 
147
147
  // src/definitions.ts
148
+ var definitions_exports = {};
149
+ __export(definitions_exports, {
150
+ STAGES: () => STAGES,
151
+ applyTimeoutOverrides: () => applyTimeoutOverrides,
152
+ getStage: () => getStage
153
+ });
154
+ function getStage(name) {
155
+ return STAGES.find((s) => s.name === name);
156
+ }
157
+ function applyTimeoutOverrides(overrides) {
158
+ for (const stage of STAGES) {
159
+ if (overrides[stage.name] != null) {
160
+ stage.timeout = overrides[stage.name] * 1e3;
161
+ }
162
+ }
163
+ }
148
164
  var STAGES;
149
165
  var init_definitions = __esm({
150
166
  "src/definitions.ts"() {
@@ -287,6 +303,7 @@ function getProjectConfig() {
287
303
  ...raw.agent,
288
304
  modelMap: { ...DEFAULT_CONFIG.agent.modelMap, ...raw.agent?.modelMap }
289
305
  },
306
+ timeouts: raw.timeouts ?? void 0,
290
307
  contextTiers: raw.contextTiers ? { ...DEFAULT_CONFIG.contextTiers, ...raw.contextTiers } : DEFAULT_CONFIG.contextTiers,
291
308
  mcp: raw.mcp ? { enabled: false, servers: {}, stages: ["build", "verify", "review", "review-fix"], ...raw.mcp } : void 0
292
309
  };
@@ -1661,6 +1678,9 @@ async function executeAgentStage(ctx, def) {
1661
1678
  }
1662
1679
  const prompt = buildFullPrompt(def.name, ctx.taskId, ctx.taskDir, ctx.projectDir, ctx.input.feedback);
1663
1680
  const model = resolveModel(def.modelTier, def.name);
1681
+ if (ctx.input.feedback && def.name === "build") {
1682
+ logger.info(` feedback: ${ctx.input.feedback.slice(0, 200)}${ctx.input.feedback.length > 200 ? "..." : ""}`);
1683
+ }
1664
1684
  const config = getProjectConfig();
1665
1685
  const runnerName = config.agent.stageRunners?.[def.name] ?? config.agent.defaultRunner ?? Object.keys(ctx.runners)[0] ?? "claude";
1666
1686
  logger.info(` runner=${runnerName} model=${model} timeout=${def.timeout / 1e3}s`);
@@ -2512,7 +2532,9 @@ PR #${existingPr.number}
2512
2532
  postComment(ctx.input.issueNumber, `\u{1F389} PR created: ${pr.url}`);
2513
2533
  } catch {
2514
2534
  }
2515
- closeIssue(ctx.input.issueNumber);
2535
+ if (ctx.input.issueNumber !== ctx.input.prNumber) {
2536
+ closeIssue(ctx.input.issueNumber);
2537
+ }
2516
2538
  }
2517
2539
  fs12.writeFileSync(shipPath, `# Ship
2518
2540
 
@@ -2651,7 +2673,18 @@ function checkQuestionsAfterStage(ctx, def, state) {
2651
2673
  }
2652
2674
  function autoDetectComplexity(ctx, def) {
2653
2675
  if (def.name !== "taskify") return null;
2654
- if (ctx.input.complexity) return null;
2676
+ if (ctx.input.complexity) {
2677
+ const complexity = ctx.input.complexity;
2678
+ const activeStages = filterByComplexity(STAGES, complexity);
2679
+ logger.info(` Complexity override: ${complexity} (${activeStages.map((s) => s.name).join(" \u2192 ")})`);
2680
+ if (ctx.input.issueNumber && !ctx.input.local) {
2681
+ try {
2682
+ setLifecycleLabel(ctx.input.issueNumber, complexity);
2683
+ } catch {
2684
+ }
2685
+ }
2686
+ return { complexity, activeStages };
2687
+ }
2655
2688
  try {
2656
2689
  const taskJsonPath = path14.join(ctx.taskDir, "task.json");
2657
2690
  if (!fs14.existsSync(taskJsonPath)) return null;
@@ -3177,6 +3210,25 @@ async function runPipeline(ctx) {
3177
3210
  acquireLock(ctx.taskDir);
3178
3211
  try {
3179
3212
  return await runPipelineInner(ctx);
3213
+ } catch (err) {
3214
+ try {
3215
+ const state = loadState(ctx.taskId, ctx.taskDir);
3216
+ if (state && state.state === "running") {
3217
+ state.state = "failed";
3218
+ for (const stage of STAGES) {
3219
+ if (state.stages[stage.name]?.state === "running") {
3220
+ state.stages[stage.name] = {
3221
+ ...state.stages[stage.name],
3222
+ state: "failed",
3223
+ error: "Pipeline crashed unexpectedly"
3224
+ };
3225
+ }
3226
+ }
3227
+ writeState(state, ctx.taskDir);
3228
+ }
3229
+ } catch {
3230
+ }
3231
+ throw err;
3180
3232
  } finally {
3181
3233
  releaseLock(ctx.taskDir);
3182
3234
  }
@@ -4113,6 +4165,10 @@ ${input.feedback}`);
4113
4165
  }
4114
4166
  }
4115
4167
  const config = getProjectConfig();
4168
+ if (config.timeouts) {
4169
+ const { applyTimeoutOverrides: applyTimeoutOverrides2 } = await Promise.resolve().then(() => (init_definitions(), definitions_exports));
4170
+ applyTimeoutOverrides2(config.timeouts);
4171
+ }
4116
4172
  let litellmProcess = await ensureLitellmProxy(config, projectDir);
4117
4173
  await runModelHealthCheck(config);
4118
4174
  const cleanupLitellm = () => {
@@ -63,6 +63,20 @@
63
63
  },
64
64
  "additionalProperties": false
65
65
  },
66
+ "timeouts": {
67
+ "type": "object",
68
+ "description": "Per-stage timeout overrides in seconds. Defaults: taskify=600, plan=600, build=2400, verify=300, review=600, review-fix=1200, ship=240",
69
+ "properties": {
70
+ "taskify": { "type": "number", "description": "Taskify stage timeout in seconds", "default": 600 },
71
+ "plan": { "type": "number", "description": "Plan stage timeout in seconds", "default": 600 },
72
+ "build": { "type": "number", "description": "Build stage timeout in seconds", "default": 2400 },
73
+ "verify": { "type": "number", "description": "Verify stage timeout in seconds", "default": 300 },
74
+ "review": { "type": "number", "description": "Review stage timeout in seconds", "default": 600 },
75
+ "review-fix": { "type": "number", "description": "Review-fix stage timeout in seconds", "default": 1200 },
76
+ "ship": { "type": "number", "description": "Ship stage timeout in seconds", "default": 240 }
77
+ },
78
+ "additionalProperties": false
79
+ },
66
80
  "agent": {
67
81
  "type": "object",
68
82
  "description": "Agent execution configuration",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.90",
3
+ "version": "0.1.92",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -42,6 +42,14 @@ Questions rules:
42
42
  Good questions: "Should the search be case-sensitive?", "Which users should have access?", "Should this work offline?"
43
43
  Bad questions: "What framework should I use?", "Where should I put the file?", "What's the project structure?"
44
44
 
45
+ If the task is already implemented (files exist, tests pass):
46
+ - Still output valid JSON — never output plain text
47
+ - Set task_type to "chore"
48
+ - Set risk_level to "low"
49
+ - Set title to "Verify existing implementation of <feature>"
50
+ - Set description to explain that the work already exists and what was verified
51
+ - Set scope to the existing file paths
52
+
45
53
  Guidelines:
46
54
  - scope must contain exact file paths (use Glob to discover them)
47
55
  - title must be actionable ("Add X", "Fix Y", "Refactor Z")