@kody-ade/kody-engine 0.4.28 → 0.4.29

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/kody.js +73 -17
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@kody-ade/kody-engine",
6
- version: "0.4.28",
6
+ version: "0.4.29",
7
7
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
8
8
  license: "MIT",
9
9
  type: "module",
@@ -4521,14 +4521,15 @@ var dispatchJobFileTicks = async (ctx, _profile, args) => {
4521
4521
  const results = [];
4522
4522
  const now = Date.now();
4523
4523
  for (const slug of slugs) {
4524
- const decision = await decideShouldFire(ctx.cwd, jobsDir, slug, backend, now);
4524
+ const frontmatter = readJobFrontmatter(ctx.cwd, jobsDir, slug);
4525
+ const decision = await decideShouldFire(frontmatter.every, slug, backend, now);
4525
4526
  if (decision.skip) {
4526
4527
  process.stdout.write(`[jobs] \u23ED skip ${slug}: ${decision.reason}
4527
4528
  `);
4528
4529
  results.push({ slug, exitCode: 0, skipped: true, reason: decision.reason });
4529
4530
  continue;
4530
4531
  }
4531
- const slugTarget = readTickScript(ctx.cwd, jobsDir, slug) ? "job-tick-scripted" : targetExecutable;
4532
+ const slugTarget = frontmatter.tickScript ? "job-tick-scripted" : targetExecutable;
4532
4533
  process.stdout.write(`[jobs] \u2192 tick ${slug} (${slugTarget})
4533
4534
  `);
4534
4535
  try {
@@ -4565,14 +4566,7 @@ var dispatchJobFileTicks = async (ctx, _profile, args) => {
4565
4566
  }
4566
4567
  }
4567
4568
  };
4568
- async function decideShouldFire(cwd, jobsDir, slug, backend, now) {
4569
- let every;
4570
- try {
4571
- const raw = fs19.readFileSync(path18.join(cwd, jobsDir, `${slug}.md`), "utf-8");
4572
- every = splitFrontmatter(raw).frontmatter.every;
4573
- } catch {
4574
- return { skip: false, reason: "frontmatter unreadable" };
4575
- }
4569
+ async function decideShouldFire(every, slug, backend, now) {
4576
4570
  if (!every) return { skip: false, reason: "no schedule (every cron tick)" };
4577
4571
  if (every === "manual") {
4578
4572
  return { skip: true, reason: "manual-only (no auto-fire; trigger via dashboard Run now)" };
@@ -4612,12 +4606,12 @@ function formatAgo(ms) {
4612
4606
  const day = Math.round(hr / 24);
4613
4607
  return `${day}d`;
4614
4608
  }
4615
- function readTickScript(cwd, jobsDir, slug) {
4609
+ function readJobFrontmatter(cwd, jobsDir, slug) {
4616
4610
  try {
4617
4611
  const raw = fs19.readFileSync(path18.join(cwd, jobsDir, `${slug}.md`), "utf-8");
4618
- return splitFrontmatter(raw).frontmatter.tickScript ?? null;
4612
+ return splitFrontmatter(raw).frontmatter;
4619
4613
  } catch {
4620
- return null;
4614
+ return {};
4621
4615
  }
4622
4616
  }
4623
4617
  function listJobSlugs(absDir) {
@@ -7267,15 +7261,29 @@ var runTickScript = async (ctx, _profile, args) => {
7267
7261
  return;
7268
7262
  }
7269
7263
  const backend = resolveBackend({ config: ctx.config, cwd: ctx.cwd, jobsDir });
7270
- const loaded = await backend.load(slug);
7264
+ let loaded;
7265
+ try {
7266
+ loaded = await backend.load(slug);
7267
+ } catch (err) {
7268
+ ctx.output.exitCode = 99;
7269
+ ctx.output.reason = `runTickScript: state load failed: ${err instanceof Error ? err.message : String(err)}`;
7270
+ return;
7271
+ }
7271
7272
  ctx.data.jobSlug = slug;
7272
7273
  ctx.data.jobState = loaded;
7274
+ const childEnv = buildChildEnv(process.env, Boolean(ctx.args.force));
7273
7275
  const result = spawnSync("bash", [scriptPath], {
7274
7276
  cwd: ctx.cwd,
7275
- env: process.env,
7277
+ env: childEnv,
7276
7278
  stdio: ["ignore", "pipe", "pipe"],
7277
7279
  encoding: "utf-8",
7278
- timeout: 5 * 60 * 1e3
7280
+ timeout: 5 * 60 * 1e3,
7281
+ // Default maxBuffer is 1MB — a chatty `gh pr list --json …` over a
7282
+ // busy repo (or an accidental `set -x`) can blow that and silently
7283
+ // truncate stdout, which is the exact "silent state drop" failure
7284
+ // mode this whole executable was written to prevent. 16MB is well
7285
+ // above any realistic tick output.
7286
+ maxBuffer: 16 * 1024 * 1024
7279
7287
  });
7280
7288
  if (result.stdout) process.stdout.write(result.stdout);
7281
7289
  if (result.stderr) process.stderr.write(result.stderr);
@@ -7284,6 +7292,11 @@ var runTickScript = async (ctx, _profile, args) => {
7284
7292
  ctx.output.reason = `runTickScript: spawn error: ${result.error.message}`;
7285
7293
  return;
7286
7294
  }
7295
+ if (result.signal) {
7296
+ ctx.output.exitCode = 124;
7297
+ ctx.output.reason = `runTickScript: ${tickScript} killed by ${result.signal} (likely 5min timeout)`;
7298
+ return;
7299
+ }
7287
7300
  if (result.status !== 0) {
7288
7301
  ctx.output.exitCode = result.status ?? 99;
7289
7302
  ctx.output.reason = `runTickScript: ${tickScript} exited ${result.status}`;
@@ -7299,6 +7312,49 @@ var runTickScript = async (ctx, _profile, args) => {
7299
7312
  }
7300
7313
  ctx.data.nextJobState = parsed.envelope;
7301
7314
  };
7315
+ function buildChildEnv(parent, force) {
7316
+ const allow = /* @__PURE__ */ new Set([
7317
+ "PATH",
7318
+ "HOME",
7319
+ "USER",
7320
+ "LOGNAME",
7321
+ "SHELL",
7322
+ "TMPDIR",
7323
+ "LANG",
7324
+ "LC_ALL",
7325
+ "TERM",
7326
+ // GitHub auth — `gh` reads these.
7327
+ "GH_TOKEN",
7328
+ "GH_PAT",
7329
+ "GITHUB_TOKEN",
7330
+ // CI metadata commonly read by tick scripts (`gh repo view`,
7331
+ // workflow run links, etc.). All public values from GitHub Actions.
7332
+ "GITHUB_ACTIONS",
7333
+ "GITHUB_ACTOR",
7334
+ "GITHUB_REPOSITORY",
7335
+ "GITHUB_REPOSITORY_OWNER",
7336
+ "GITHUB_REF",
7337
+ "GITHUB_SHA",
7338
+ "GITHUB_RUN_ID",
7339
+ "GITHUB_RUN_NUMBER",
7340
+ "GITHUB_WORKFLOW",
7341
+ "GITHUB_JOB",
7342
+ "GITHUB_SERVER_URL",
7343
+ "GITHUB_API_URL",
7344
+ "GITHUB_EVENT_NAME",
7345
+ "RUNNER_OS",
7346
+ "RUNNER_ARCH"
7347
+ ]);
7348
+ const out = {};
7349
+ for (const [key, value] of Object.entries(parent)) {
7350
+ if (value === void 0) continue;
7351
+ if (allow.has(key) || key.startsWith("KODY_PUBLIC_")) {
7352
+ out[key] = value;
7353
+ }
7354
+ }
7355
+ if (force) out.KODY_FORCE = "1";
7356
+ return out;
7357
+ }
7302
7358
 
7303
7359
  // src/scripts/saveTaskState.ts
7304
7360
  var saveTaskState = async (ctx, profile) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.28",
3
+ "version": "0.4.29",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",