@kody-ade/kody-engine 0.4.284 → 0.4.286

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 +39 -11
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.284",
18
+ version: "0.4.286",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -6985,7 +6985,7 @@ function linkContext(stateRepo) {
6985
6985
  function githubBlobUrl(repo, filePath) {
6986
6986
  try {
6987
6987
  const parsed = parseStateRepoSlug(repo);
6988
- return `https://github.com/${parsed.owner}/${parsed.repo}/blob/main/${filePath}`;
6988
+ return `https://github.com/${parsed.owner}/${parsed.repo}/blob/${STATE_BRANCH}/${filePath}`;
6989
6989
  } catch {
6990
6990
  return void 0;
6991
6991
  }
@@ -7068,6 +7068,7 @@ var LOGS_KEY, LOG_RUN_KEY, LOG_STARTED_KEY;
7068
7068
  var init_runLog = __esm({
7069
7069
  "src/goal/runLog.ts"() {
7070
7070
  "use strict";
7071
+ init_stateBranch();
7071
7072
  init_stateRepo();
7072
7073
  init_state2();
7073
7074
  LOGS_KEY = "__goalRunLogs";
@@ -7269,12 +7270,10 @@ var init_stateStore = __esm({
7269
7270
  // src/goal/targetLoopResolution.ts
7270
7271
  import * as fs26 from "fs";
7271
7272
  import * as path24 from "path";
7272
- function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
7273
+ function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
7273
7274
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
7274
7275
  assertSafeGoalId(targetId, "loop target");
7275
- if (!hasExplicitStateRepo(config)) {
7276
- return { targetId, templateId: targetId, reason: "literal target; state repo not configured" };
7277
- }
7276
+ if (!hasExplicitStateRepo(config)) return null;
7278
7277
  const activeInstance = findActiveTargetInstance(config, cwd, loopGoalId, targetId);
7279
7278
  if (activeInstance) {
7280
7279
  return {
@@ -7287,6 +7286,17 @@ function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
7287
7286
  if (directTarget?.state === "active") {
7288
7287
  return { targetId, templateId: targetId, reason: "active target goal" };
7289
7288
  }
7289
+ return null;
7290
+ }
7291
+ function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
7292
+ const targetId = loopGoal.loopTarget?.id.trim() ?? "";
7293
+ assertSafeGoalId(targetId, "loop target");
7294
+ if (!hasExplicitStateRepo(config)) {
7295
+ return { targetId, templateId: targetId, reason: "literal target; state repo not configured" };
7296
+ }
7297
+ const activeTarget = resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal);
7298
+ if (activeTarget) return activeTarget;
7299
+ const directTarget = fetchGoalState(config, targetId, cwd);
7290
7300
  const template = loadGoalTemplate(cwd, targetId);
7291
7301
  if (!template) {
7292
7302
  if (directTarget) {
@@ -7960,7 +7970,9 @@ function planTargetLoopSchedule(opts) {
7960
7970
  }
7961
7971
  const preferred = opts.goal.preferredRunTime;
7962
7972
  if (preferred) {
7963
- const gate = preferredRunTimeGate(preferred, now, opts.previousScheduleState);
7973
+ const gate = preferredRunTimeGate(preferred, now, opts.previousScheduleState, {
7974
+ allowRepeatAfterCompletedTarget: opts.allowRepeatAfterCompletedTarget === true
7975
+ });
7964
7976
  if (!gate.ok) return targetLoopDecision("idle", gate.reason, at);
7965
7977
  }
7966
7978
  const dispatchTargetId = target.type === "goal" && opts.resolvedGoalTargetId?.trim() ? opts.resolvedGoalTargetId.trim() : targetId;
@@ -8122,7 +8134,7 @@ function targetLoopDecision(kind, reason, at) {
8122
8134
  }
8123
8135
  };
8124
8136
  }
8125
- function preferredRunTimeGate(preferred, now, previous) {
8137
+ function preferredRunTimeGate(preferred, now, previous, opts) {
8126
8138
  const current = zonedTimeParts(now, preferred.timezone);
8127
8139
  if (!current) return { ok: false, reason: `invalid preferred timezone: ${preferred.timezone}` };
8128
8140
  const preferredMinute = preferredTimeToMinute(preferred.time);
@@ -8134,7 +8146,7 @@ function preferredRunTimeGate(preferred, now, previous) {
8134
8146
  const lastDispatchAt = previous?.lastDecision.kind === "dispatch" ? previous.lastDecision.at : void 0;
8135
8147
  if (lastDispatchAt) {
8136
8148
  const last = zonedTimeParts(new Date(lastDispatchAt), preferred.timezone);
8137
- if (last?.date === current.date) {
8149
+ if (last?.date === current.date && opts?.allowRepeatAfterCompletedTarget !== true) {
8138
8150
  return { ok: false, reason: `already dispatched today at preferred time ${preferred.time} ${preferred.timezone}` };
8139
8151
  }
8140
8152
  }
@@ -8268,6 +8280,14 @@ function readSimpleGoalTaskSummary(goalId, cwd) {
8268
8280
  const open = issues.filter((issue) => String(issue.state ?? "").toLowerCase() === "open").length;
8269
8281
  return { total, open };
8270
8282
  }
8283
+ function previousDispatchWasTargetInstance(managed, previousScheduleState) {
8284
+ const targetId = managed.loopTarget?.id.trim();
8285
+ const previous = previousScheduleState?.lastDecision;
8286
+ if (!targetId || previous?.kind !== "dispatch" || !("targetType" in previous) || previous.targetType !== "goal") {
8287
+ return false;
8288
+ }
8289
+ return previous.targetId === targetId || previous.targetId.startsWith(`${targetId}-`);
8290
+ }
8271
8291
  function ensureIssueFactIfNeeded(goal, goalId, cwd) {
8272
8292
  if (!routeNeedsIssueFact(goal)) return;
8273
8293
  const existing = normalizeIssueNumber(goal.facts.issue);
@@ -8400,7 +8420,14 @@ var init_advanceManagedGoal = __esm({
8400
8420
  const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
8401
8421
  const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
8402
8422
  const now = goalLoopNow();
8403
- let decision2 = planTargetLoopSchedule({ goal: managed, previousScheduleState, now });
8423
+ const activeTarget = isGoalTargetLoop(managed) ? resolveActiveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed) : null;
8424
+ const allowRepeatAfterCompletedTarget = isGoalTargetLoop(managed) && !activeTarget && previousDispatchWasTargetInstance(managed, previousScheduleState);
8425
+ let decision2 = planTargetLoopSchedule({
8426
+ goal: managed,
8427
+ previousScheduleState,
8428
+ now,
8429
+ allowRepeatAfterCompletedTarget
8430
+ });
8404
8431
  let targetResolution;
8405
8432
  if (decision2.kind === "dispatch" && decision2.dispatch && isGoalTargetLoop(managed)) {
8406
8433
  targetResolution = resolveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed, now);
@@ -8408,7 +8435,8 @@ var init_advanceManagedGoal = __esm({
8408
8435
  goal: managed,
8409
8436
  previousScheduleState,
8410
8437
  now,
8411
- resolvedGoalTargetId: targetResolution.targetId
8438
+ resolvedGoalTargetId: targetResolution.targetId,
8439
+ allowRepeatAfterCompletedTarget
8412
8440
  });
8413
8441
  }
8414
8442
  restoreGoalIdFact();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.284",
3
+ "version": "0.4.286",
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",