@kody-ade/kody-engine-lite 0.1.42 → 0.1.44

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 (2) hide show
  1. package/dist/bin/cli.js +135 -85
  2. package/package.json +1 -1
package/dist/bin/cli.js CHANGED
@@ -249,6 +249,72 @@ var init_logger = __esm({
249
249
  }
250
250
  });
251
251
 
252
+ // src/config.ts
253
+ import * as fs from "fs";
254
+ import * as path from "path";
255
+ function setConfigDir(dir) {
256
+ _configDir = dir;
257
+ _config = null;
258
+ }
259
+ function getProjectConfig() {
260
+ if (_config) return _config;
261
+ const configPath = path.join(_configDir ?? process.cwd(), "kody.config.json");
262
+ if (fs.existsSync(configPath)) {
263
+ try {
264
+ const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
265
+ _config = {
266
+ quality: { ...DEFAULT_CONFIG.quality, ...raw.quality },
267
+ git: { ...DEFAULT_CONFIG.git, ...raw.git },
268
+ github: { ...DEFAULT_CONFIG.github, ...raw.github },
269
+ paths: { ...DEFAULT_CONFIG.paths, ...raw.paths },
270
+ agent: { ...DEFAULT_CONFIG.agent, ...raw.agent }
271
+ };
272
+ } catch {
273
+ logger.warn("kody.config.json is invalid JSON \u2014 using defaults");
274
+ _config = { ...DEFAULT_CONFIG };
275
+ }
276
+ } else {
277
+ _config = { ...DEFAULT_CONFIG };
278
+ }
279
+ return _config;
280
+ }
281
+ var DEFAULT_CONFIG, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
282
+ var init_config = __esm({
283
+ "src/config.ts"() {
284
+ "use strict";
285
+ init_logger();
286
+ DEFAULT_CONFIG = {
287
+ quality: {
288
+ typecheck: "pnpm -s tsc --noEmit",
289
+ lint: "pnpm -s lint",
290
+ lintFix: "pnpm lint:fix",
291
+ format: "pnpm -s format:check",
292
+ formatFix: "pnpm format:fix",
293
+ testUnit: "pnpm -s test"
294
+ },
295
+ git: {
296
+ defaultBranch: "dev"
297
+ },
298
+ github: {
299
+ owner: "",
300
+ repo: ""
301
+ },
302
+ paths: {
303
+ taskDir: ".tasks"
304
+ },
305
+ agent: {
306
+ runner: "claude-code",
307
+ defaultRunner: "claude",
308
+ modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
309
+ }
310
+ };
311
+ VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
312
+ FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
313
+ _config = null;
314
+ _configDir = null;
315
+ }
316
+ });
317
+
252
318
  // src/git-utils.ts
253
319
  import { execFileSync as execFileSync2 } from "child_process";
254
320
  function getHookSafeEnv() {
@@ -271,6 +337,13 @@ function deriveBranchName(issueNumber, title) {
271
337
  return `${issueNumber}-${slug}`;
272
338
  }
273
339
  function getDefaultBranch(cwd) {
340
+ try {
341
+ const config = getProjectConfig();
342
+ if (config.git?.defaultBranch) {
343
+ return config.git.defaultBranch;
344
+ }
345
+ } catch {
346
+ }
274
347
  try {
275
348
  const ref = git(["symbolic-ref", "refs/remotes/origin/HEAD"], { cwd });
276
349
  return ref.replace("refs/remotes/origin/", "");
@@ -374,6 +447,7 @@ var init_git_utils = __esm({
374
447
  "src/git-utils.ts"() {
375
448
  "use strict";
376
449
  init_logger();
450
+ init_config();
377
451
  BASE_BRANCHES = ["dev", "main", "master"];
378
452
  _hookSafeEnv = null;
379
453
  }
@@ -441,6 +515,32 @@ function postComment(issueNumber, body) {
441
515
  logger.warn(` Failed to post comment: ${err}`);
442
516
  }
443
517
  }
518
+ function getPRForBranch(branch) {
519
+ try {
520
+ const output = gh([
521
+ "pr",
522
+ "view",
523
+ branch,
524
+ "--json",
525
+ "number,url"
526
+ ]);
527
+ const data = JSON.parse(output);
528
+ return { number: data.number, url: data.url };
529
+ } catch {
530
+ return null;
531
+ }
532
+ }
533
+ function updatePR(prNumber, body) {
534
+ try {
535
+ gh(
536
+ ["pr", "edit", String(prNumber), "--body-file", "-"],
537
+ { input: body }
538
+ );
539
+ logger.info(` PR #${prNumber} body updated`);
540
+ } catch (err) {
541
+ logger.warn(` Failed to update PR #${prNumber}: ${err}`);
542
+ }
543
+ }
444
544
  function createPR(head, base, title, body) {
445
545
  try {
446
546
  const output = gh(
@@ -493,13 +593,13 @@ var init_github_api = __esm({
493
593
  });
494
594
 
495
595
  // src/pipeline/state.ts
496
- import * as fs from "fs";
497
- import * as path from "path";
596
+ import * as fs2 from "fs";
597
+ import * as path2 from "path";
498
598
  function loadState(taskId, taskDir) {
499
- const p = path.join(taskDir, "status.json");
500
- if (!fs.existsSync(p)) return null;
599
+ const p = path2.join(taskDir, "status.json");
600
+ if (!fs2.existsSync(p)) return null;
501
601
  try {
502
- const raw = JSON.parse(fs.readFileSync(p, "utf-8"));
602
+ const raw = JSON.parse(fs2.readFileSync(p, "utf-8"));
503
603
  if (raw.taskId === taskId) return raw;
504
604
  return null;
505
605
  } catch {
@@ -511,10 +611,10 @@ function writeState(state, taskDir) {
511
611
  ...state,
512
612
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
513
613
  };
514
- const target = path.join(taskDir, "status.json");
614
+ const target = path2.join(taskDir, "status.json");
515
615
  const tmp = target + ".tmp";
516
- fs.writeFileSync(tmp, JSON.stringify(updated, null, 2));
517
- fs.renameSync(tmp, target);
616
+ fs2.writeFileSync(tmp, JSON.stringify(updated, null, 2));
617
+ fs2.renameSync(tmp, target);
518
618
  state.updatedAt = updated.updatedAt;
519
619
  }
520
620
  function initState(taskId) {
@@ -553,16 +653,16 @@ var init_complexity = __esm({
553
653
  });
554
654
 
555
655
  // src/memory.ts
556
- import * as fs2 from "fs";
557
- import * as path2 from "path";
656
+ import * as fs3 from "fs";
657
+ import * as path3 from "path";
558
658
  function readProjectMemory(projectDir) {
559
- const memoryDir = path2.join(projectDir, ".kody", "memory");
560
- if (!fs2.existsSync(memoryDir)) return "";
561
- const files = fs2.readdirSync(memoryDir).filter((f) => f.endsWith(".md")).sort();
659
+ const memoryDir = path3.join(projectDir, ".kody", "memory");
660
+ if (!fs3.existsSync(memoryDir)) return "";
661
+ const files = fs3.readdirSync(memoryDir).filter((f) => f.endsWith(".md")).sort();
562
662
  if (files.length === 0) return "";
563
663
  const sections = [];
564
664
  for (const file of files) {
565
- const content = fs2.readFileSync(path2.join(memoryDir, file), "utf-8").trim();
665
+ const content = fs3.readFileSync(path3.join(memoryDir, file), "utf-8").trim();
566
666
  if (content) {
567
667
  sections.push(`## ${file.replace(".md", "")}
568
668
  ${content}`);
@@ -580,72 +680,6 @@ var init_memory = __esm({
580
680
  }
581
681
  });
582
682
 
583
- // src/config.ts
584
- import * as fs3 from "fs";
585
- import * as path3 from "path";
586
- function setConfigDir(dir) {
587
- _configDir = dir;
588
- _config = null;
589
- }
590
- function getProjectConfig() {
591
- if (_config) return _config;
592
- const configPath = path3.join(_configDir ?? process.cwd(), "kody.config.json");
593
- if (fs3.existsSync(configPath)) {
594
- try {
595
- const raw = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
596
- _config = {
597
- quality: { ...DEFAULT_CONFIG.quality, ...raw.quality },
598
- git: { ...DEFAULT_CONFIG.git, ...raw.git },
599
- github: { ...DEFAULT_CONFIG.github, ...raw.github },
600
- paths: { ...DEFAULT_CONFIG.paths, ...raw.paths },
601
- agent: { ...DEFAULT_CONFIG.agent, ...raw.agent }
602
- };
603
- } catch {
604
- logger.warn("kody.config.json is invalid JSON \u2014 using defaults");
605
- _config = { ...DEFAULT_CONFIG };
606
- }
607
- } else {
608
- _config = { ...DEFAULT_CONFIG };
609
- }
610
- return _config;
611
- }
612
- var DEFAULT_CONFIG, VERIFY_COMMAND_TIMEOUT_MS, FIX_COMMAND_TIMEOUT_MS, _config, _configDir;
613
- var init_config = __esm({
614
- "src/config.ts"() {
615
- "use strict";
616
- init_logger();
617
- DEFAULT_CONFIG = {
618
- quality: {
619
- typecheck: "pnpm -s tsc --noEmit",
620
- lint: "pnpm -s lint",
621
- lintFix: "pnpm lint:fix",
622
- format: "pnpm -s format:check",
623
- formatFix: "pnpm format:fix",
624
- testUnit: "pnpm -s test"
625
- },
626
- git: {
627
- defaultBranch: "dev"
628
- },
629
- github: {
630
- owner: "",
631
- repo: ""
632
- },
633
- paths: {
634
- taskDir: ".tasks"
635
- },
636
- agent: {
637
- runner: "claude-code",
638
- defaultRunner: "claude",
639
- modelMap: { cheap: "haiku", mid: "sonnet", strong: "opus" }
640
- }
641
- };
642
- VERIFY_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
643
- FIX_COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
644
- _config = null;
645
- _configDir = null;
646
- }
647
- });
648
-
649
683
  // src/context.ts
650
684
  import * as fs4 from "fs";
651
685
  import * as path4 from "path";
@@ -1512,21 +1546,37 @@ function executeShipStage(ctx, _def) {
1512
1546
  }
1513
1547
  }
1514
1548
  const body = buildPrBody(ctx);
1515
- const pr = createPR(head, base, title, body);
1516
- if (pr) {
1549
+ const existingPr = getPRForBranch(head);
1550
+ if (existingPr) {
1551
+ updatePR(existingPr.number, body);
1517
1552
  if (ctx.input.issueNumber && !ctx.input.local) {
1518
1553
  try {
1519
- postComment(ctx.input.issueNumber, `\u{1F389} PR created: ${pr.url}`);
1554
+ postComment(ctx.input.issueNumber, `\u2705 Fix pushed to existing PR: ${existingPr.url}`);
1520
1555
  } catch {
1521
1556
  }
1522
1557
  }
1523
1558
  fs9.writeFileSync(shipPath, `# Ship
1524
1559
 
1560
+ Updated existing PR: ${existingPr.url}
1561
+ PR #${existingPr.number}
1562
+ `);
1563
+ } else {
1564
+ const pr = createPR(head, base, title, body);
1565
+ if (pr) {
1566
+ if (ctx.input.issueNumber && !ctx.input.local) {
1567
+ try {
1568
+ postComment(ctx.input.issueNumber, `\u{1F389} PR created: ${pr.url}`);
1569
+ } catch {
1570
+ }
1571
+ }
1572
+ fs9.writeFileSync(shipPath, `# Ship
1573
+
1525
1574
  PR created: ${pr.url}
1526
1575
  PR #${pr.number}
1527
1576
  `);
1528
- } else {
1529
- fs9.writeFileSync(shipPath, "# Ship\n\nPushed branch but failed to create PR.\n");
1577
+ } else {
1578
+ fs9.writeFileSync(shipPath, "# Ship\n\nPushed branch but failed to create PR.\n");
1579
+ }
1530
1580
  }
1531
1581
  return { outcome: "completed", outputFile: "ship.md", retries: 0 };
1532
1582
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.42",
3
+ "version": "0.1.44",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",