@kody-ade/kody-engine-lite 0.1.138 → 0.1.140

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
@@ -2973,17 +2973,17 @@ var init_parse_inputs = __esm({
2973
2973
  // src/watch/core/state.ts
2974
2974
  import * as fs15 from "fs";
2975
2975
  import * as path13 from "path";
2976
- import { execFileSync as execFileSync10 } from "child_process";
2977
- function createStateStore(repo, localFilePath) {
2978
- if (process.env.GITHUB_ACTIONS === "true") {
2979
- return new GhVariableStateStore(repo);
2976
+ function createStateStore(localFilePath, github, digestIssue) {
2977
+ if (process.env.GITHUB_ACTIONS === "true" && github && digestIssue) {
2978
+ return new IssueCommentStateStore(github, digestIssue);
2980
2979
  }
2981
2980
  return new JsonStateStore(localFilePath);
2982
2981
  }
2983
- var JsonStateStore, GH_VARIABLE_NAME, GhVariableStateStore;
2982
+ var STATE_MARKER, JsonStateStore, IssueCommentStateStore;
2984
2983
  var init_state = __esm({
2985
2984
  "src/watch/core/state.ts"() {
2986
2985
  "use strict";
2986
+ STATE_MARKER = "<!-- KODY_WATCH_STATE:";
2987
2987
  JsonStateStore = class {
2988
2988
  data = {};
2989
2989
  filePath;
@@ -3032,38 +3032,34 @@ var init_state = __esm({
3032
3032
  }
3033
3033
  }
3034
3034
  };
3035
- GH_VARIABLE_NAME = "KODY_WATCH_STATE";
3036
- GhVariableStateStore = class {
3035
+ IssueCommentStateStore = class {
3037
3036
  data = {};
3038
3037
  dirty = false;
3039
- repo;
3040
- constructor(repo) {
3041
- this.repo = repo;
3042
- this.loadFromGh();
3043
- }
3044
- loadFromGh() {
3038
+ github;
3039
+ digestIssue;
3040
+ commentId = null;
3041
+ constructor(github, digestIssue) {
3042
+ this.github = github;
3043
+ this.digestIssue = digestIssue;
3044
+ this.loadFromComment();
3045
+ }
3046
+ loadFromComment() {
3045
3047
  try {
3046
- const output = execFileSync10(
3047
- "gh",
3048
- ["variable", "get", GH_VARIABLE_NAME, "--repo", this.repo],
3049
- {
3050
- encoding: "utf-8",
3051
- stdio: ["pipe", "pipe", "pipe"],
3052
- env: { ...process.env, GH_TOKEN: process.env.GH_PAT || process.env.GH_TOKEN || "" }
3053
- }
3054
- ).trim();
3055
- if (output) {
3056
- const parsed = JSON.parse(output);
3057
- if (parsed && typeof parsed === "object") {
3058
- this.data = parsed;
3059
- return;
3048
+ const comments = this.github.getIssueComments(this.digestIssue);
3049
+ for (const comment of comments) {
3050
+ if (comment.body.includes(STATE_MARKER)) {
3051
+ this.commentId = comment.id;
3052
+ const match = comment.body.match(/<!-- KODY_WATCH_STATE:(.*?) -->/);
3053
+ if (match) {
3054
+ const parsed = JSON.parse(match[1]);
3055
+ if (parsed && typeof parsed === "object") {
3056
+ this.data = parsed;
3057
+ return;
3058
+ }
3059
+ }
3060
3060
  }
3061
3061
  }
3062
- } catch (error) {
3063
- const msg = error instanceof Error ? error.message : String(error);
3064
- if (!msg.includes("HTTP 404") && !msg.includes("variable not found")) {
3065
- console.warn(`[KodyWatch] Failed to load state: ${msg} \u2014 starting fresh`);
3066
- }
3062
+ } catch {
3067
3063
  }
3068
3064
  this.data = {};
3069
3065
  }
@@ -3077,16 +3073,16 @@ var init_state = __esm({
3077
3073
  save() {
3078
3074
  if (!this.dirty) return;
3079
3075
  const json = JSON.stringify(this.data);
3076
+ const cycle = this.data["system:cycleNumber"] ?? 0;
3077
+ const body = `${STATE_MARKER}${json} -->
3078
+
3079
+ _Kody Watch state \u2014 cycle #${cycle}, updated ${(/* @__PURE__ */ new Date()).toISOString()}_`;
3080
3080
  try {
3081
- execFileSync10(
3082
- "gh",
3083
- ["variable", "set", GH_VARIABLE_NAME, "--repo", this.repo, "--body", json],
3084
- {
3085
- encoding: "utf-8",
3086
- stdio: ["pipe", "pipe", "pipe"],
3087
- env: { ...process.env, GH_TOKEN: process.env.GH_PAT || process.env.GH_TOKEN || "" }
3088
- }
3089
- );
3081
+ if (this.commentId) {
3082
+ this.github.updateComment(this.commentId, body);
3083
+ } else {
3084
+ this.github.postComment(this.digestIssue, body);
3085
+ }
3090
3086
  this.dirty = false;
3091
3087
  } catch (error) {
3092
3088
  const msg = error instanceof Error ? error.message : String(error);
@@ -3139,11 +3135,11 @@ var init_dedup = __esm({
3139
3135
  });
3140
3136
 
3141
3137
  // src/watch/clients/github.ts
3142
- import { execFileSync as execFileSync11 } from "child_process";
3138
+ import { execFileSync as execFileSync10 } from "child_process";
3143
3139
  function createGitHubClient(repo, token) {
3144
3140
  const gh2 = (args2, input) => {
3145
3141
  try {
3146
- return execFileSync11("gh", args2, {
3142
+ return execFileSync10("gh", args2, {
3147
3143
  input,
3148
3144
  encoding: "utf-8",
3149
3145
  stdio: ["pipe", "pipe", "ignore"],
@@ -3171,6 +3167,33 @@ function createGitHubClient(repo, token) {
3171
3167
  return { body: null, title: null };
3172
3168
  }
3173
3169
  },
3170
+ getIssueComments(issueNumber) {
3171
+ const output = gh2([
3172
+ "api",
3173
+ `repos/${repo}/issues/${issueNumber}/comments`,
3174
+ "--paginate",
3175
+ "--jq",
3176
+ "[.[] | {id: .id, body: .body}]"
3177
+ ]);
3178
+ if (!output) return [];
3179
+ return output.split("\n").filter(Boolean).flatMap((line) => {
3180
+ try {
3181
+ return JSON.parse(line);
3182
+ } catch {
3183
+ return [];
3184
+ }
3185
+ });
3186
+ },
3187
+ updateComment(commentId, body) {
3188
+ gh2([
3189
+ "api",
3190
+ `repos/${repo}/issues/comments/${commentId}`,
3191
+ "--method",
3192
+ "PATCH",
3193
+ "--field",
3194
+ `body=${body}`
3195
+ ]);
3196
+ },
3174
3197
  getOpenIssues(labels) {
3175
3198
  let query = `repos/${repo}/issues`;
3176
3199
  if (labels && labels.length > 0) {
@@ -3261,11 +3284,11 @@ var init_logger2 = __esm({
3261
3284
  // src/watch/core/watch.ts
3262
3285
  async function runWatch(config) {
3263
3286
  const { repo, dryRun, stateFile, plugins } = config;
3264
- const state = createStateStore(repo, stateFile);
3265
- const cycleNumber = (state.get("system:cycleNumber") || 0) + 1;
3266
- state.set("system:cycleNumber", cycleNumber);
3267
3287
  const token = process.env.GH_TOKEN || "";
3268
3288
  const github = createGitHubClient(repo, token);
3289
+ const state = createStateStore(stateFile, github, config.digestIssue);
3290
+ const cycleNumber = (state.get("system:cycleNumber") || 0) + 1;
3291
+ state.set("system:cycleNumber", cycleNumber);
3269
3292
  const log2 = createConsoleLogger();
3270
3293
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString();
3271
3294
  const ctx = {
@@ -3579,7 +3602,7 @@ var init_rules = __esm({
3579
3602
  // src/watch/plugins/security-scan/scanner.ts
3580
3603
  import * as fs17 from "fs";
3581
3604
  import * as path15 from "path";
3582
- import { execFileSync as execFileSync12 } from "child_process";
3605
+ import { execFileSync as execFileSync11 } from "child_process";
3583
3606
  function findFiles(dir, pattern, exclude = []) {
3584
3607
  const results = [];
3585
3608
  if (!fs17.existsSync(dir)) return results;
@@ -3666,7 +3689,7 @@ function scanForCommittedEnvFiles(rootDir) {
3666
3689
  const envPath = path15.join(rootDir, envFile);
3667
3690
  if (!fs17.existsSync(envPath)) continue;
3668
3691
  try {
3669
- execFileSync12("git", ["ls-files", "--error-unmatch", envFile], {
3692
+ execFileSync11("git", ["ls-files", "--error-unmatch", envFile], {
3670
3693
  cwd: rootDir,
3671
3694
  encoding: "utf-8",
3672
3695
  stdio: ["pipe", "pipe", "pipe"]
@@ -3691,7 +3714,7 @@ function scanDependencyVulnerabilities(rootDir) {
3691
3714
  const auditCmd = hasPnpm ? "pnpm" : hasYarn ? "yarn" : hasNpm ? "npm" : null;
3692
3715
  if (!auditCmd) return findings;
3693
3716
  try {
3694
- const output = execFileSync12(auditCmd, ["audit", "--json"], {
3717
+ const output = execFileSync11(auditCmd, ["audit", "--json"], {
3695
3718
  cwd: rootDir,
3696
3719
  encoding: "utf-8",
3697
3720
  timeout: 6e4,
@@ -3931,7 +3954,7 @@ var init_security_scan = __esm({
3931
3954
  // src/watch/plugins/config-health/index.ts
3932
3955
  import * as fs18 from "fs";
3933
3956
  import * as path16 from "path";
3934
- import { execFileSync as execFileSync13 } from "child_process";
3957
+ import { execFileSync as execFileSync12 } from "child_process";
3935
3958
  function validateConfig(cwd, repo) {
3936
3959
  const findings = [];
3937
3960
  const configPath = path16.join(cwd, "kody.config.json");
@@ -4004,7 +4027,7 @@ function validateConfig(cwd, repo) {
4004
4027
  }
4005
4028
  if (repo) {
4006
4029
  try {
4007
- const output = execFileSync13("gh", ["secret", "list", "--repo", repo], {
4030
+ const output = execFileSync12("gh", ["secret", "list", "--repo", repo], {
4008
4031
  encoding: "utf-8",
4009
4032
  timeout: 1e4,
4010
4033
  stdio: ["pipe", "pipe", "pipe"]
@@ -4237,7 +4260,7 @@ var init_definitions = __esm({
4237
4260
  });
4238
4261
 
4239
4262
  // src/git-utils.ts
4240
- import { execFileSync as execFileSync14 } from "child_process";
4263
+ import { execFileSync as execFileSync13 } from "child_process";
4241
4264
  function getHookSafeEnv() {
4242
4265
  if (!_hookSafeEnv) {
4243
4266
  _hookSafeEnv = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
@@ -4245,7 +4268,7 @@ function getHookSafeEnv() {
4245
4268
  return _hookSafeEnv;
4246
4269
  }
4247
4270
  function git(args2, options) {
4248
- return execFileSync14("git", args2, {
4271
+ return execFileSync13("git", args2, {
4249
4272
  encoding: "utf-8",
4250
4273
  timeout: options?.timeout ?? 3e4,
4251
4274
  cwd: options?.cwd,
@@ -5445,7 +5468,7 @@ var init_agent = __esm({
5445
5468
  });
5446
5469
 
5447
5470
  // src/verify-runner.ts
5448
- import { execFileSync as execFileSync15 } from "child_process";
5471
+ import { execFileSync as execFileSync14 } from "child_process";
5449
5472
  function isExecError(err) {
5450
5473
  return typeof err === "object" && err !== null;
5451
5474
  }
@@ -5481,7 +5504,7 @@ function runCommand(cmd, cwd, timeout) {
5481
5504
  return { success: true, output: "", timedOut: false };
5482
5505
  }
5483
5506
  try {
5484
- const output = execFileSync15(parts[0], parts.slice(1), {
5507
+ const output = execFileSync14(parts[0], parts.slice(1), {
5485
5508
  cwd,
5486
5509
  timeout,
5487
5510
  encoding: "utf-8",
@@ -5570,7 +5593,7 @@ var init_verify_runner = __esm({
5570
5593
  });
5571
5594
 
5572
5595
  // src/observer.ts
5573
- import { execFileSync as execFileSync16 } from "child_process";
5596
+ import { execFileSync as execFileSync15 } from "child_process";
5574
5597
  async function diagnoseFailure(stageName, errorOutput, modifiedFiles, runner, model, options) {
5575
5598
  const context = [
5576
5599
  `Stage: ${stageName}`,
@@ -5653,13 +5676,13 @@ ${modifiedFiles.map((f) => `- ${f}`).join("\n")}` : "No files were modified (bui
5653
5676
  }
5654
5677
  function getModifiedFiles(projectDir) {
5655
5678
  try {
5656
- const staged = execFileSync16("git", ["diff", "--name-only", "--cached"], {
5679
+ const staged = execFileSync15("git", ["diff", "--name-only", "--cached"], {
5657
5680
  encoding: "utf-8",
5658
5681
  cwd: projectDir,
5659
5682
  timeout: 5e3,
5660
5683
  stdio: ["pipe", "pipe", "pipe"]
5661
5684
  }).trim();
5662
- const unstaged = execFileSync16("git", ["diff", "--name-only"], {
5685
+ const unstaged = execFileSync15("git", ["diff", "--name-only"], {
5663
5686
  encoding: "utf-8",
5664
5687
  cwd: projectDir,
5665
5688
  timeout: 5e3,
@@ -5763,7 +5786,7 @@ var init_gate = __esm({
5763
5786
  // src/stages/verify.ts
5764
5787
  import * as fs26 from "fs";
5765
5788
  import * as path24 from "path";
5766
- import { execFileSync as execFileSync17 } from "child_process";
5789
+ import { execFileSync as execFileSync16 } from "child_process";
5767
5790
  async function executeVerifyWithAutofix(ctx, def) {
5768
5791
  const maxAttempts = def.maxRetries ?? 2;
5769
5792
  for (let attempt = 0; attempt <= maxAttempts; attempt++) {
@@ -5817,7 +5840,7 @@ ${diagnosis.resolution}`);
5817
5840
  const parts = parseCommand(cmd);
5818
5841
  if (parts.length === 0) return;
5819
5842
  try {
5820
- execFileSync17(parts[0], parts.slice(1), {
5843
+ execFileSync16(parts[0], parts.slice(1), {
5821
5844
  stdio: "pipe",
5822
5845
  timeout: FIX_COMMAND_TIMEOUT_MS
5823
5846
  });
@@ -6038,7 +6061,7 @@ var init_review = __esm({
6038
6061
  // src/stages/ship.ts
6039
6062
  import * as fs29 from "fs";
6040
6063
  import * as path27 from "path";
6041
- import { execFileSync as execFileSync18 } from "child_process";
6064
+ import { execFileSync as execFileSync17 } from "child_process";
6042
6065
  function buildPrBody(ctx) {
6043
6066
  const sections = [];
6044
6067
  const taskJsonPath = path27.join(ctx.taskDir, "task.json");
@@ -6125,12 +6148,12 @@ function executeShipStage(ctx, _def) {
6125
6148
  const memoryDir = path27.join(ctx.projectDir, ".kody", "memory");
6126
6149
  const addPaths = [ctx.taskDir];
6127
6150
  if (fs29.existsSync(memoryDir)) addPaths.push(memoryDir);
6128
- execFileSync18("git", ["add", ...addPaths], {
6151
+ execFileSync17("git", ["add", ...addPaths], {
6129
6152
  cwd: ctx.projectDir,
6130
6153
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
6131
6154
  stdio: "pipe"
6132
6155
  });
6133
- execFileSync18("git", ["commit", "--no-gpg-sign", "-m", `chore: add kody task artifacts [skip ci]`], {
6156
+ execFileSync17("git", ["commit", "--no-gpg-sign", "-m", `chore: add kody task artifacts [skip ci]`], {
6134
6157
  cwd: ctx.projectDir,
6135
6158
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
6136
6159
  stdio: "pipe"
@@ -6144,7 +6167,7 @@ function executeShipStage(ctx, _def) {
6144
6167
  let repo = config.github?.repo;
6145
6168
  if (!owner || !repo) {
6146
6169
  try {
6147
- const remoteUrl = execFileSync18("git", ["remote", "get-url", "origin"], {
6170
+ const remoteUrl = execFileSync17("git", ["remote", "get-url", "origin"], {
6148
6171
  encoding: "utf-8",
6149
6172
  cwd: ctx.projectDir
6150
6173
  }).trim();
@@ -7185,7 +7208,7 @@ var init_pipeline = __esm({
7185
7208
  });
7186
7209
 
7187
7210
  // src/preflight.ts
7188
- import { execFileSync as execFileSync19 } from "child_process";
7211
+ import { execFileSync as execFileSync18 } from "child_process";
7189
7212
  import * as fs36 from "fs";
7190
7213
  function check(name, fn) {
7191
7214
  try {
@@ -7198,7 +7221,7 @@ function check(name, fn) {
7198
7221
  function runPreflight() {
7199
7222
  const checks = [
7200
7223
  check("claude CLI", () => {
7201
- const v = execFileSync19("claude", ["--version"], {
7224
+ const v = execFileSync18("claude", ["--version"], {
7202
7225
  encoding: "utf-8",
7203
7226
  timeout: 1e4,
7204
7227
  stdio: ["pipe", "pipe", "pipe"]
@@ -7206,14 +7229,14 @@ function runPreflight() {
7206
7229
  return v;
7207
7230
  }),
7208
7231
  check("git repo", () => {
7209
- execFileSync19("git", ["rev-parse", "--is-inside-work-tree"], {
7232
+ execFileSync18("git", ["rev-parse", "--is-inside-work-tree"], {
7210
7233
  encoding: "utf-8",
7211
7234
  timeout: 5e3,
7212
7235
  stdio: ["pipe", "pipe", "pipe"]
7213
7236
  });
7214
7237
  }),
7215
7238
  check("pnpm", () => {
7216
- const v = execFileSync19("pnpm", ["--version"], {
7239
+ const v = execFileSync18("pnpm", ["--version"], {
7217
7240
  encoding: "utf-8",
7218
7241
  timeout: 5e3,
7219
7242
  stdio: ["pipe", "pipe", "pipe"]
@@ -7221,7 +7244,7 @@ function runPreflight() {
7221
7244
  return v;
7222
7245
  }),
7223
7246
  check("node >= 18", () => {
7224
- const v = execFileSync19("node", ["--version"], {
7247
+ const v = execFileSync18("node", ["--version"], {
7225
7248
  encoding: "utf-8",
7226
7249
  timeout: 5e3,
7227
7250
  stdio: ["pipe", "pipe", "pipe"]
@@ -7231,7 +7254,7 @@ function runPreflight() {
7231
7254
  return v;
7232
7255
  }),
7233
7256
  check("gh CLI", () => {
7234
- const v = execFileSync19("gh", ["--version"], {
7257
+ const v = execFileSync18("gh", ["--version"], {
7235
7258
  encoding: "utf-8",
7236
7259
  timeout: 5e3,
7237
7260
  stdio: ["pipe", "pipe", "pipe"]
@@ -7386,12 +7409,12 @@ var resolve_exports = {};
7386
7409
  __export(resolve_exports, {
7387
7410
  runResolve: () => runResolve
7388
7411
  });
7389
- import { execFileSync as execFileSync20 } from "child_process";
7412
+ import { execFileSync as execFileSync19 } from "child_process";
7390
7413
  function getConflictContext(cwd, files) {
7391
7414
  const parts = [];
7392
7415
  for (const file of files.slice(0, 10)) {
7393
7416
  try {
7394
- const content = execFileSync20("git", ["diff", file], {
7417
+ const content = execFileSync19("git", ["diff", file], {
7395
7418
  cwd,
7396
7419
  encoding: "utf-8",
7397
7420
  stdio: ["pipe", "pipe", "pipe"]
@@ -7954,7 +7977,7 @@ ${input.feedback}`);
7954
7977
  logger.info(`Task: ${taskId}`);
7955
7978
  logger.info(`Mode: ${ctx.input.mode}${ctx.input.local ? " (local)" : " (CI)"}`);
7956
7979
  if (ctx.input.issueNumber) logger.info(`Issue: #${ctx.input.issueNumber}`);
7957
- if (ctx.input.issueNumber && !ctx.input.local && ctx.input.mode === "full") {
7980
+ if (ctx.input.issueNumber && !ctx.input.local) {
7958
7981
  const runUrl = process.env.RUN_URL ?? "";
7959
7982
  const runLink = runUrl ? ` ([logs](${runUrl}))` : "";
7960
7983
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.138",
3
+ "version": "0.1.140",
4
4
  "description": "Autonomous SDLC pipeline: Kody orchestration + Claude Code + LiteLLM",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,7 +21,6 @@ jobs:
21
21
  permissions:
22
22
  issues: write
23
23
  contents: read
24
- actions: write
25
24
  steps:
26
25
  - uses: actions/checkout@v4
27
26