@kody-ade/kody-engine-lite 0.1.66 → 0.1.67

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 +49 -9
  2. package/package.json +1 -1
package/dist/bin/cli.js CHANGED
@@ -4201,7 +4201,7 @@ function ghComment(issueNumber, body, cwd) {
4201
4201
  } catch {
4202
4202
  }
4203
4203
  }
4204
- function bootstrapCommand() {
4204
+ function bootstrapCommand(opts = { force: false }) {
4205
4205
  const cwd = process.cwd();
4206
4206
  const issueNumber = parseInt(process.env.ISSUE_NUMBER ?? "", 10) || 0;
4207
4207
  console.log(`
@@ -4275,6 +4275,23 @@ ${existingFiles.join(", ")}
4275
4275
  fs22.mkdirSync(memoryDir, { recursive: true });
4276
4276
  const archPath = path21.join(memoryDir, "architecture.md");
4277
4277
  const conventionsPath = path21.join(memoryDir, "conventions.md");
4278
+ const existingArch = fs22.existsSync(archPath) ? fs22.readFileSync(archPath, "utf-8") : "";
4279
+ const existingConv = fs22.existsSync(conventionsPath) ? fs22.readFileSync(conventionsPath, "utf-8") : "";
4280
+ const hasExisting = !!(existingArch || existingConv);
4281
+ const extendInstruction = hasExisting && !opts.force ? `
4282
+ ## Existing Documentation (EXTEND, do not replace)
4283
+ You are UPDATING existing documentation. Follow these rules strictly:
4284
+ - PRESERVE all existing sections and content that are still accurate
4285
+ - REMOVE only lines that reference files, patterns, or dependencies that no longer exist in the project
4286
+ - APPEND new sections or lines for newly discovered patterns, files, or conventions
4287
+ - Do NOT rewrite sections that are still correct \u2014 keep them verbatim
4288
+
4289
+ ### Existing architecture.md:
4290
+ ${existingArch}
4291
+
4292
+ ### Existing conventions.md:
4293
+ ${existingConv}
4294
+ ` : "";
4278
4295
  const memoryPrompt = `You are analyzing a project to generate documentation for an autonomous SDLC pipeline.
4279
4296
 
4280
4297
  Given this project context, output ONLY a JSON object with EXACTLY this structure:
@@ -4294,7 +4311,7 @@ Rules for conventions (markdown string):
4294
4311
  - Extract actual patterns from the project
4295
4312
  - If CLAUDE.md exists, reference it
4296
4313
  - Keep under 30 lines
4297
-
4314
+ ${extendInstruction}
4298
4315
  Output ONLY valid JSON. No markdown fences. No explanation.
4299
4316
 
4300
4317
  ${repoContext}`;
@@ -4352,11 +4369,16 @@ ${detected.join("\n")}
4352
4369
  console.log(` \u2717 ${stage}.md \u2014 template not found in engine`);
4353
4370
  continue;
4354
4371
  }
4372
+ const stepOutputPath = path21.join(stepsDir, `${stage}.md`);
4373
+ if (fs22.existsSync(stepOutputPath) && !opts.force) {
4374
+ console.log(` \u25CB ${stage}.md \u2014 already exists (use --force to regenerate)`);
4375
+ continue;
4376
+ }
4355
4377
  const defaultPrompt = fs22.readFileSync(templatePath, "utf-8");
4356
4378
  const contextPlaceholder = "{{TASK_CONTEXT}}";
4357
4379
  const placeholderIdx = defaultPrompt.indexOf(contextPlaceholder);
4358
4380
  if (placeholderIdx === -1) {
4359
- fs22.copyFileSync(templatePath, path21.join(stepsDir, `${stage}.md`));
4381
+ fs22.copyFileSync(templatePath, stepOutputPath);
4360
4382
  stepCount++;
4361
4383
  console.log(` \u2713 ${stage}.md`);
4362
4384
  continue;
@@ -4413,12 +4435,12 @@ REMINDER: Output the full prompt template first (unchanged), then your three app
4413
4435
  let cleaned = output.replace(/^```(?:markdown|md)?\s*\n?/, "").replace(/\n?```\s*$/, "");
4414
4436
  cleaned = cleaned.replace(/\n*\{\{TASK_CONTEXT\}\}\s*$/, "").trimEnd();
4415
4437
  const finalPrompt = cleaned + "\n\n" + afterPlaceholder;
4416
- fs22.writeFileSync(path21.join(stepsDir, `${stage}.md`), finalPrompt);
4438
+ fs22.writeFileSync(stepOutputPath, finalPrompt);
4417
4439
  stepCount++;
4418
4440
  console.log(` \u2713 ${stage}.md`);
4419
4441
  } catch {
4420
4442
  console.log(` \u26A0 ${stage}.md \u2014 customization failed, using default template`);
4421
- fs22.copyFileSync(templatePath, path21.join(stepsDir, `${stage}.md`));
4443
+ fs22.copyFileSync(templatePath, stepOutputPath);
4422
4444
  stepCount++;
4423
4445
  }
4424
4446
  }
@@ -4685,8 +4707,26 @@ function installSkillsForProject(cwd) {
4685
4707
  console.log(" \u25CB No skills to install (no frontend framework detected)");
4686
4708
  return [];
4687
4709
  }
4710
+ let installedSkills = {};
4711
+ const lockPath = path21.join(cwd, "skills-lock.json");
4712
+ if (fs22.existsSync(lockPath)) {
4713
+ try {
4714
+ const lock = JSON.parse(fs22.readFileSync(lockPath, "utf-8"));
4715
+ installedSkills = lock.skills ?? {};
4716
+ } catch {
4717
+ }
4718
+ }
4688
4719
  const installedPaths = [];
4689
4720
  for (const skill of skills) {
4721
+ const skillName = skill.package.split("@").pop() ?? "";
4722
+ if (skillName in installedSkills) {
4723
+ console.log(` \u25CB ${skill.label} \u2014 already installed`);
4724
+ const agentPath = `.agents/skills/${skillName}`;
4725
+ const claudePath = `.claude/skills/${skillName}`;
4726
+ if (fs22.existsSync(path21.join(cwd, agentPath))) installedPaths.push(agentPath);
4727
+ if (fs22.existsSync(path21.join(cwd, claudePath))) installedPaths.push(claudePath);
4728
+ continue;
4729
+ }
4690
4730
  try {
4691
4731
  console.log(` Installing: ${skill.label} (${skill.package})`);
4692
4732
  execFileSync11("npx", ["skills", "add", skill.package, "--yes"], {
@@ -4695,9 +4735,9 @@ function installSkillsForProject(cwd) {
4695
4735
  timeout: 6e4,
4696
4736
  stdio: ["pipe", "pipe", "pipe"]
4697
4737
  });
4698
- const skillName = skill.package.split("@").pop() ?? "";
4699
- const agentPath = `.agents/skills/${skillName}`;
4700
- const claudePath = `.claude/skills/${skillName}`;
4738
+ const skillName2 = skill.package.split("@").pop() ?? "";
4739
+ const agentPath = `.agents/skills/${skillName2}`;
4740
+ const claudePath = `.claude/skills/${skillName2}`;
4701
4741
  if (fs22.existsSync(path21.join(cwd, agentPath))) installedPaths.push(agentPath);
4702
4742
  if (fs22.existsSync(path21.join(cwd, claudePath))) installedPaths.push(claudePath);
4703
4743
  console.log(` \u2713 ${skill.label}`);
@@ -4712,7 +4752,7 @@ var command = args[0];
4712
4752
  if (command === "init") {
4713
4753
  initCommand({ force: args.includes("--force") });
4714
4754
  } else if (command === "bootstrap") {
4715
- bootstrapCommand();
4755
+ bootstrapCommand({ force: args.includes("--force") });
4716
4756
  } else if (command === "version" || command === "--version" || command === "-v") {
4717
4757
  console.log(getVersion());
4718
4758
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.66",
3
+ "version": "0.1.67",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",