@kody-ade/kody-engine-lite 0.1.137 → 0.1.139

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 = {
@@ -3552,6 +3575,7 @@ var init_rules = __esm({
3552
3575
  "dist/",
3553
3576
  "build/",
3554
3577
  "tests/",
3578
+ "watch/",
3555
3579
  ".env",
3556
3580
  "pnpm-lock.yaml",
3557
3581
  "package-lock.json",
@@ -3578,7 +3602,7 @@ var init_rules = __esm({
3578
3602
  // src/watch/plugins/security-scan/scanner.ts
3579
3603
  import * as fs17 from "fs";
3580
3604
  import * as path15 from "path";
3581
- import { execFileSync as execFileSync12 } from "child_process";
3605
+ import { execFileSync as execFileSync11 } from "child_process";
3582
3606
  function findFiles(dir, pattern, exclude = []) {
3583
3607
  const results = [];
3584
3608
  if (!fs17.existsSync(dir)) return results;
@@ -3665,7 +3689,7 @@ function scanForCommittedEnvFiles(rootDir) {
3665
3689
  const envPath = path15.join(rootDir, envFile);
3666
3690
  if (!fs17.existsSync(envPath)) continue;
3667
3691
  try {
3668
- execFileSync12("git", ["ls-files", "--error-unmatch", envFile], {
3692
+ execFileSync11("git", ["ls-files", "--error-unmatch", envFile], {
3669
3693
  cwd: rootDir,
3670
3694
  encoding: "utf-8",
3671
3695
  stdio: ["pipe", "pipe", "pipe"]
@@ -3690,7 +3714,7 @@ function scanDependencyVulnerabilities(rootDir) {
3690
3714
  const auditCmd = hasPnpm ? "pnpm" : hasYarn ? "yarn" : hasNpm ? "npm" : null;
3691
3715
  if (!auditCmd) return findings;
3692
3716
  try {
3693
- const output = execFileSync12(auditCmd, ["audit", "--json"], {
3717
+ const output = execFileSync11(auditCmd, ["audit", "--json"], {
3694
3718
  cwd: rootDir,
3695
3719
  encoding: "utf-8",
3696
3720
  timeout: 6e4,
@@ -3930,7 +3954,7 @@ var init_security_scan = __esm({
3930
3954
  // src/watch/plugins/config-health/index.ts
3931
3955
  import * as fs18 from "fs";
3932
3956
  import * as path16 from "path";
3933
- import { execFileSync as execFileSync13 } from "child_process";
3957
+ import { execFileSync as execFileSync12 } from "child_process";
3934
3958
  function validateConfig(cwd, repo) {
3935
3959
  const findings = [];
3936
3960
  const configPath = path16.join(cwd, "kody.config.json");
@@ -4003,7 +4027,7 @@ function validateConfig(cwd, repo) {
4003
4027
  }
4004
4028
  if (repo) {
4005
4029
  try {
4006
- const output = execFileSync13("gh", ["secret", "list", "--repo", repo], {
4030
+ const output = execFileSync12("gh", ["secret", "list", "--repo", repo], {
4007
4031
  encoding: "utf-8",
4008
4032
  timeout: 1e4,
4009
4033
  stdio: ["pipe", "pipe", "pipe"]
@@ -4236,7 +4260,7 @@ var init_definitions = __esm({
4236
4260
  });
4237
4261
 
4238
4262
  // src/git-utils.ts
4239
- import { execFileSync as execFileSync14 } from "child_process";
4263
+ import { execFileSync as execFileSync13 } from "child_process";
4240
4264
  function getHookSafeEnv() {
4241
4265
  if (!_hookSafeEnv) {
4242
4266
  _hookSafeEnv = { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" };
@@ -4244,7 +4268,7 @@ function getHookSafeEnv() {
4244
4268
  return _hookSafeEnv;
4245
4269
  }
4246
4270
  function git(args2, options) {
4247
- return execFileSync14("git", args2, {
4271
+ return execFileSync13("git", args2, {
4248
4272
  encoding: "utf-8",
4249
4273
  timeout: options?.timeout ?? 3e4,
4250
4274
  cwd: options?.cwd,
@@ -5444,7 +5468,7 @@ var init_agent = __esm({
5444
5468
  });
5445
5469
 
5446
5470
  // src/verify-runner.ts
5447
- import { execFileSync as execFileSync15 } from "child_process";
5471
+ import { execFileSync as execFileSync14 } from "child_process";
5448
5472
  function isExecError(err) {
5449
5473
  return typeof err === "object" && err !== null;
5450
5474
  }
@@ -5480,7 +5504,7 @@ function runCommand(cmd, cwd, timeout) {
5480
5504
  return { success: true, output: "", timedOut: false };
5481
5505
  }
5482
5506
  try {
5483
- const output = execFileSync15(parts[0], parts.slice(1), {
5507
+ const output = execFileSync14(parts[0], parts.slice(1), {
5484
5508
  cwd,
5485
5509
  timeout,
5486
5510
  encoding: "utf-8",
@@ -5569,7 +5593,7 @@ var init_verify_runner = __esm({
5569
5593
  });
5570
5594
 
5571
5595
  // src/observer.ts
5572
- import { execFileSync as execFileSync16 } from "child_process";
5596
+ import { execFileSync as execFileSync15 } from "child_process";
5573
5597
  async function diagnoseFailure(stageName, errorOutput, modifiedFiles, runner, model, options) {
5574
5598
  const context = [
5575
5599
  `Stage: ${stageName}`,
@@ -5652,13 +5676,13 @@ ${modifiedFiles.map((f) => `- ${f}`).join("\n")}` : "No files were modified (bui
5652
5676
  }
5653
5677
  function getModifiedFiles(projectDir) {
5654
5678
  try {
5655
- const staged = execFileSync16("git", ["diff", "--name-only", "--cached"], {
5679
+ const staged = execFileSync15("git", ["diff", "--name-only", "--cached"], {
5656
5680
  encoding: "utf-8",
5657
5681
  cwd: projectDir,
5658
5682
  timeout: 5e3,
5659
5683
  stdio: ["pipe", "pipe", "pipe"]
5660
5684
  }).trim();
5661
- const unstaged = execFileSync16("git", ["diff", "--name-only"], {
5685
+ const unstaged = execFileSync15("git", ["diff", "--name-only"], {
5662
5686
  encoding: "utf-8",
5663
5687
  cwd: projectDir,
5664
5688
  timeout: 5e3,
@@ -5762,7 +5786,7 @@ var init_gate = __esm({
5762
5786
  // src/stages/verify.ts
5763
5787
  import * as fs26 from "fs";
5764
5788
  import * as path24 from "path";
5765
- import { execFileSync as execFileSync17 } from "child_process";
5789
+ import { execFileSync as execFileSync16 } from "child_process";
5766
5790
  async function executeVerifyWithAutofix(ctx, def) {
5767
5791
  const maxAttempts = def.maxRetries ?? 2;
5768
5792
  for (let attempt = 0; attempt <= maxAttempts; attempt++) {
@@ -5816,7 +5840,7 @@ ${diagnosis.resolution}`);
5816
5840
  const parts = parseCommand(cmd);
5817
5841
  if (parts.length === 0) return;
5818
5842
  try {
5819
- execFileSync17(parts[0], parts.slice(1), {
5843
+ execFileSync16(parts[0], parts.slice(1), {
5820
5844
  stdio: "pipe",
5821
5845
  timeout: FIX_COMMAND_TIMEOUT_MS
5822
5846
  });
@@ -6037,7 +6061,7 @@ var init_review = __esm({
6037
6061
  // src/stages/ship.ts
6038
6062
  import * as fs29 from "fs";
6039
6063
  import * as path27 from "path";
6040
- import { execFileSync as execFileSync18 } from "child_process";
6064
+ import { execFileSync as execFileSync17 } from "child_process";
6041
6065
  function buildPrBody(ctx) {
6042
6066
  const sections = [];
6043
6067
  const taskJsonPath = path27.join(ctx.taskDir, "task.json");
@@ -6124,12 +6148,12 @@ function executeShipStage(ctx, _def) {
6124
6148
  const memoryDir = path27.join(ctx.projectDir, ".kody", "memory");
6125
6149
  const addPaths = [ctx.taskDir];
6126
6150
  if (fs29.existsSync(memoryDir)) addPaths.push(memoryDir);
6127
- execFileSync18("git", ["add", ...addPaths], {
6151
+ execFileSync17("git", ["add", ...addPaths], {
6128
6152
  cwd: ctx.projectDir,
6129
6153
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
6130
6154
  stdio: "pipe"
6131
6155
  });
6132
- 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]`], {
6133
6157
  cwd: ctx.projectDir,
6134
6158
  env: { ...process.env, HUSKY: "0", SKIP_HOOKS: "1" },
6135
6159
  stdio: "pipe"
@@ -6143,7 +6167,7 @@ function executeShipStage(ctx, _def) {
6143
6167
  let repo = config.github?.repo;
6144
6168
  if (!owner || !repo) {
6145
6169
  try {
6146
- const remoteUrl = execFileSync18("git", ["remote", "get-url", "origin"], {
6170
+ const remoteUrl = execFileSync17("git", ["remote", "get-url", "origin"], {
6147
6171
  encoding: "utf-8",
6148
6172
  cwd: ctx.projectDir
6149
6173
  }).trim();
@@ -7184,7 +7208,7 @@ var init_pipeline = __esm({
7184
7208
  });
7185
7209
 
7186
7210
  // src/preflight.ts
7187
- import { execFileSync as execFileSync19 } from "child_process";
7211
+ import { execFileSync as execFileSync18 } from "child_process";
7188
7212
  import * as fs36 from "fs";
7189
7213
  function check(name, fn) {
7190
7214
  try {
@@ -7197,7 +7221,7 @@ function check(name, fn) {
7197
7221
  function runPreflight() {
7198
7222
  const checks = [
7199
7223
  check("claude CLI", () => {
7200
- const v = execFileSync19("claude", ["--version"], {
7224
+ const v = execFileSync18("claude", ["--version"], {
7201
7225
  encoding: "utf-8",
7202
7226
  timeout: 1e4,
7203
7227
  stdio: ["pipe", "pipe", "pipe"]
@@ -7205,14 +7229,14 @@ function runPreflight() {
7205
7229
  return v;
7206
7230
  }),
7207
7231
  check("git repo", () => {
7208
- execFileSync19("git", ["rev-parse", "--is-inside-work-tree"], {
7232
+ execFileSync18("git", ["rev-parse", "--is-inside-work-tree"], {
7209
7233
  encoding: "utf-8",
7210
7234
  timeout: 5e3,
7211
7235
  stdio: ["pipe", "pipe", "pipe"]
7212
7236
  });
7213
7237
  }),
7214
7238
  check("pnpm", () => {
7215
- const v = execFileSync19("pnpm", ["--version"], {
7239
+ const v = execFileSync18("pnpm", ["--version"], {
7216
7240
  encoding: "utf-8",
7217
7241
  timeout: 5e3,
7218
7242
  stdio: ["pipe", "pipe", "pipe"]
@@ -7220,7 +7244,7 @@ function runPreflight() {
7220
7244
  return v;
7221
7245
  }),
7222
7246
  check("node >= 18", () => {
7223
- const v = execFileSync19("node", ["--version"], {
7247
+ const v = execFileSync18("node", ["--version"], {
7224
7248
  encoding: "utf-8",
7225
7249
  timeout: 5e3,
7226
7250
  stdio: ["pipe", "pipe", "pipe"]
@@ -7230,7 +7254,7 @@ function runPreflight() {
7230
7254
  return v;
7231
7255
  }),
7232
7256
  check("gh CLI", () => {
7233
- const v = execFileSync19("gh", ["--version"], {
7257
+ const v = execFileSync18("gh", ["--version"], {
7234
7258
  encoding: "utf-8",
7235
7259
  timeout: 5e3,
7236
7260
  stdio: ["pipe", "pipe", "pipe"]
@@ -7385,12 +7409,12 @@ var resolve_exports = {};
7385
7409
  __export(resolve_exports, {
7386
7410
  runResolve: () => runResolve
7387
7411
  });
7388
- import { execFileSync as execFileSync20 } from "child_process";
7412
+ import { execFileSync as execFileSync19 } from "child_process";
7389
7413
  function getConflictContext(cwd, files) {
7390
7414
  const parts = [];
7391
7415
  for (const file of files.slice(0, 10)) {
7392
7416
  try {
7393
- const content = execFileSync20("git", ["diff", file], {
7417
+ const content = execFileSync19("git", ["diff", file], {
7394
7418
  cwd,
7395
7419
  encoding: "utf-8",
7396
7420
  stdio: ["pipe", "pipe", "pipe"]
@@ -7953,7 +7977,7 @@ ${input.feedback}`);
7953
7977
  logger.info(`Task: ${taskId}`);
7954
7978
  logger.info(`Mode: ${ctx.input.mode}${ctx.input.local ? " (local)" : " (CI)"}`);
7955
7979
  if (ctx.input.issueNumber) logger.info(`Issue: #${ctx.input.issueNumber}`);
7956
- if (ctx.input.issueNumber && !ctx.input.local && ctx.input.mode === "full") {
7980
+ if (ctx.input.issueNumber && !ctx.input.local) {
7957
7981
  const runUrl = process.env.RUN_URL ?? "";
7958
7982
  const runLink = runUrl ? ` ([logs](${runUrl}))` : "";
7959
7983
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine-lite",
3
- "version": "0.1.137",
3
+ "version": "0.1.139",
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