@kody-ade/kody-engine 0.4.392 → 0.4.393

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 +46 -35
  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.391",
18
+ version: "0.4.392",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -8900,13 +8900,24 @@ async function fetchGoalStateAsync(config, goalId, cwd) {
8900
8900
  if (backendRequired()) throw new Error("Convex backend is required for goal state in GitHub Actions");
8901
8901
  return fetchGoalStateLegacy(config, goalId, cwd);
8902
8902
  }
8903
- function fetchGoalState(config, goalId, cwd) {
8904
- return fetchGoalStateLegacy(config, goalId, cwd);
8905
- }
8906
- function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
8903
+ async function putGoalStateAsync(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
8904
+ const tenantId = backendTenant(config);
8905
+ if (backendEnabled(config) && tenantId) {
8906
+ const backend = createStateBackendFromEnv();
8907
+ const previous = await backend.getGoal(tenantId, goalId);
8908
+ await backend.saveGoal(tenantId, goalId, state, state.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(), previous?.updatedAt);
8909
+ return;
8910
+ }
8911
+ if (backendRequired()) throw new Error("Convex backend is required for goal state in GitHub Actions");
8907
8912
  putGoalStateLegacy(config, goalId, state, message, cwd);
8908
8913
  }
8909
- function listGoalStateIds(config, cwd) {
8914
+ async function listGoalStateIdsAsync(config, cwd) {
8915
+ const tenantId = backendTenant(config);
8916
+ if (backendEnabled(config) && tenantId) {
8917
+ const docs = await createStateBackendFromEnv().listGoals(tenantId);
8918
+ return docs.map((doc) => doc.goalId).filter(Boolean).sort();
8919
+ }
8920
+ if (backendRequired()) throw new Error("Convex backend is required for goal state in GitHub Actions");
8910
8921
  return listGoalStateIdsLegacy(config, cwd);
8911
8922
  }
8912
8923
  var init_stateStore = __esm({
@@ -8922,11 +8933,11 @@ var init_stateStore = __esm({
8922
8933
  // src/goal/targetLoopResolution.ts
8923
8934
  import * as fs27 from "fs";
8924
8935
  import * as path25 from "path";
8925
- function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
8936
+ async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
8926
8937
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
8927
8938
  assertSafeGoalId(targetId, "loop target");
8928
8939
  if (!hasExplicitStateRepo(config)) return null;
8929
- const activeInstance = findActiveTargetInstance(config, cwd, loopGoalId, targetId);
8940
+ const activeInstance = await findActiveTargetInstance(config, cwd, loopGoalId, targetId);
8930
8941
  if (activeInstance) {
8931
8942
  return {
8932
8943
  targetId: activeInstance.id,
@@ -8934,21 +8945,21 @@ function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
8934
8945
  reason: "active target instance"
8935
8946
  };
8936
8947
  }
8937
- const directTarget = fetchGoalState(config, targetId, cwd);
8948
+ const directTarget = await fetchGoalStateAsync(config, targetId, cwd);
8938
8949
  if (directTarget?.state === "active") {
8939
8950
  return { targetId, templateId: targetId, reason: "active target goal" };
8940
8951
  }
8941
8952
  return null;
8942
8953
  }
8943
- function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
8954
+ async function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
8944
8955
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
8945
8956
  assertSafeGoalId(targetId, "loop target");
8946
8957
  if (!hasExplicitStateRepo(config)) {
8947
8958
  return { targetId, templateId: targetId, reason: "literal target; state repo not configured" };
8948
8959
  }
8949
- const activeTarget = resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal);
8960
+ const activeTarget = await resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal);
8950
8961
  if (activeTarget) return activeTarget;
8951
- const directTarget = fetchGoalState(config, targetId, cwd);
8962
+ const directTarget = await fetchGoalStateAsync(config, targetId, cwd);
8952
8963
  const template = loadGoalTemplate(cwd, targetId);
8953
8964
  if (!template) {
8954
8965
  if (directTarget) {
@@ -8956,9 +8967,9 @@ function resolveGoalLoopTarget(config, cwd, loopGoalId, loopGoal, now) {
8956
8967
  }
8957
8968
  return { targetId, templateId: targetId, reason: "literal target; no target state or template found" };
8958
8969
  }
8959
- const instanceId = chooseTargetInstanceId(config, cwd, targetId, loopGoal.preferredRunTime?.timezone, now);
8970
+ const instanceId = await chooseTargetInstanceId(config, cwd, targetId, loopGoal.preferredRunTime?.timezone, now);
8960
8971
  const instance = buildGoalTargetInstance(template, targetId, now);
8961
- putGoalState(config, instanceId, instance, `chore(goals): create ${instanceId}`, cwd);
8972
+ await putGoalStateAsync(config, instanceId, instance, `chore(goals): create ${instanceId}`, cwd);
8962
8973
  return {
8963
8974
  targetId: instanceId,
8964
8975
  templateId: targetId,
@@ -8978,13 +8989,13 @@ function hasExplicitStateRepo(config) {
8978
8989
  const state = config.state;
8979
8990
  return !!state && typeof state.repo === "string" && state.repo.trim().length > 0 && typeof state.path === "string" && state.path.trim().length > 0;
8980
8991
  }
8981
- function findActiveTargetInstance(config, cwd, loopGoalId, targetId) {
8992
+ async function findActiveTargetInstance(config, cwd, loopGoalId, targetId) {
8982
8993
  const candidates = [];
8983
- for (const entryId of listGoalStateIds(config, cwd)) {
8994
+ for (const entryId of await listGoalStateIdsAsync(config, cwd)) {
8984
8995
  const id = entryId.trim();
8985
8996
  if (!id || id === loopGoalId || id === targetId || !id.startsWith(`${targetId}-`)) continue;
8986
8997
  assertSafeGoalId(id, "goal instance");
8987
- const state = fetchGoalState(config, id, cwd);
8998
+ const state = await fetchGoalStateAsync(config, id, cwd);
8988
8999
  if (!state || state.state !== "active") continue;
8989
9000
  if (!isTargetInstanceState(id, state, targetId)) continue;
8990
9001
  candidates.push({ id, state });
@@ -9022,12 +9033,12 @@ function readJsonObject(filePath) {
9022
9033
  }
9023
9034
  return parsed;
9024
9035
  }
9025
- function chooseTargetInstanceId(config, cwd, targetId, timezone, now) {
9036
+ async function chooseTargetInstanceId(config, cwd, targetId, timezone, now) {
9026
9037
  const base = `${targetId}-${zonedDate(now, timezone ?? "UTC")}`;
9027
9038
  for (let index = 1; index <= 20; index += 1) {
9028
9039
  const id = index === 1 ? base : `${base}-${index}`;
9029
9040
  assertSafeGoalId(id, "goal instance");
9030
- const existing = fetchGoalState(config, id, cwd);
9041
+ const existing = await fetchGoalStateAsync(config, id, cwd);
9031
9042
  if (!existing || existing.state === "active") return id;
9032
9043
  }
9033
9044
  throw new Error(`could not allocate goal target instance id for ${targetId}`);
@@ -10266,7 +10277,7 @@ function scalarFacts(facts) {
10266
10277
  )
10267
10278
  );
10268
10279
  }
10269
- function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options = {}) {
10280
+ async function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options = {}) {
10270
10281
  if (ctx.data.jobForce === true) return null;
10271
10282
  const selfKind = managedModelKind(goal);
10272
10283
  const selfMode = selfKind === "Goal" ? firstTrustOverride(ctx, subjectCandidates("goal", goalId, goalState)) : null;
@@ -10282,7 +10293,7 @@ function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2, options =
10282
10293
  }
10283
10294
  const targetGoal = dispatch2.action === "goal-manager" && typeof dispatch2.cliArgs.goal === "string" ? dispatch2.cliArgs.goal : null;
10284
10295
  if (targetGoal && targetGoal !== goalId && options.checkTargets !== false) {
10285
- const target = fetchGoalState(ctx.config, targetGoal, ctx.cwd);
10296
+ const target = await fetchGoalStateAsync(ctx.config, targetGoal, ctx.cwd);
10286
10297
  const targetManaged = target ? managedGoalFromState(expandManagedGoalState(target)) : null;
10287
10298
  const targetIsGoal = targetManaged ? managedModelKind(targetManaged) === "Goal" : false;
10288
10299
  const targetMode = targetManaged && targetIsGoal ? firstTrustOverride(ctx, subjectCandidates("goal", targetGoal, target)) : null;
@@ -10616,7 +10627,7 @@ var init_advanceManagedGoal = __esm({
10616
10627
  const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
10617
10628
  const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
10618
10629
  const now = goalLoopNow();
10619
- const activeTarget = isGoalTargetLoop(managed) ? resolveActiveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed) : null;
10630
+ const activeTarget = isGoalTargetLoop(managed) ? await resolveActiveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed) : null;
10620
10631
  const allowSameDayTargetDispatch = isGoalTargetLoop(managed) && (!!activeTarget || previousDispatchWasTargetInstance(managed, previousScheduleState));
10621
10632
  let decision2 = planTargetLoopSchedule({
10622
10633
  goal: managed,
@@ -10625,7 +10636,7 @@ var init_advanceManagedGoal = __esm({
10625
10636
  allowSameDayTargetDispatch
10626
10637
  });
10627
10638
  let targetResolution;
10628
- const selfAutonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch, { checkTargets: false }) : null;
10639
+ const selfAutonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? await autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch, { checkTargets: false }) : null;
10629
10640
  if (selfAutonomyBlock) {
10630
10641
  restoreGoalIdFact();
10631
10642
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
@@ -10637,7 +10648,7 @@ var init_advanceManagedGoal = __esm({
10637
10648
  return;
10638
10649
  }
10639
10650
  if (decision2.kind === "dispatch" && decision2.dispatch && isGoalTargetLoop(managed)) {
10640
- targetResolution = resolveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed, now);
10651
+ targetResolution = await resolveGoalLoopTarget(ctx.config, ctx.cwd, goal.id, managed, now);
10641
10652
  decision2 = planTargetLoopSchedule({
10642
10653
  goal: managed,
10643
10654
  previousScheduleState,
@@ -10648,7 +10659,7 @@ var init_advanceManagedGoal = __esm({
10648
10659
  }
10649
10660
  restoreGoalIdFact();
10650
10661
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
10651
- const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
10662
+ const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? await autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
10652
10663
  if (autonomyBlock) {
10653
10664
  const waitDecision = scheduleWaitDecision(previousScheduleState, decision2, autonomyBlock);
10654
10665
  goal.raw.extra.scheduleState = waitDecision.scheduleState;
@@ -10713,7 +10724,7 @@ var init_advanceManagedGoal = __esm({
10713
10724
  });
10714
10725
  restoreGoalIdFact();
10715
10726
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
10716
- const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
10727
+ const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? await autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
10717
10728
  if (autonomyBlock) {
10718
10729
  const waitDecision = scheduleWaitDecision(previousScheduleState, decision2, autonomyBlock);
10719
10730
  goal.raw.extra.scheduleState = waitDecision.scheduleState;
@@ -10783,7 +10794,7 @@ var init_advanceManagedGoal = __esm({
10783
10794
  ...decision.implementation ? { implementation: decision.implementation } : {},
10784
10795
  cliArgs: decision.cliArgs
10785
10796
  };
10786
- const autonomyBlock = autonomyBlockReason(ctx, goal.id, managed, goal.raw, planned);
10797
+ const autonomyBlock = await autonomyBlockReason(ctx, goal.id, managed, goal.raw, planned);
10787
10798
  if (autonomyBlock) {
10788
10799
  stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
10789
10800
  ctx.output.reason = autonomyBlock;
@@ -11592,7 +11603,7 @@ var init_applyCapabilityReports = __esm({
11592
11603
  if (evidenceItems.length === 0) return;
11593
11604
  const evidenceByGoal = groupGoalEvidence(evidenceItems);
11594
11605
  for (const [goalId, goalEvidence] of evidenceByGoal) {
11595
- const prior = fetchGoalState(ctx.config, goalId, ctx.cwd);
11606
+ const prior = await fetchGoalStateAsync(ctx.config, goalId, ctx.cwd);
11596
11607
  if (!prior) {
11597
11608
  stageGoalRunLogEvent(ctx.data, goalId, {
11598
11609
  source: "goal-loop",
@@ -11667,7 +11678,7 @@ var init_applyCapabilityReports = __esm({
11667
11678
  const nextForOutput = changed ? { ...next, updatedAt: nowIso() } : next;
11668
11679
  try {
11669
11680
  if (changed) {
11670
- putGoalState(ctx.config, goalId, nextForOutput, describeMessage(goalId, goalEvidence), ctx.cwd);
11681
+ await putGoalStateAsync(ctx.config, goalId, nextForOutput, describeMessage(goalId, goalEvidence), ctx.cwd);
11671
11682
  }
11672
11683
  refreshReportOrFail(ctx, goalId, nextForOutput, goalEvidence);
11673
11684
  if (changed && ctx.output.exitCode === 0 && !ctx.output.nextDispatch && shouldResumeManagedGoal(goalId, nextForOutput)) {
@@ -12015,7 +12026,7 @@ var init_commitGoalState = __esm({
12015
12026
  return;
12016
12027
  }
12017
12028
  try {
12018
- putGoalState(ctx.config, goal.id, updated, describeCommitMessage(goal), ctx.cwd);
12029
+ await putGoalStateAsync(ctx.config, goal.id, updated, describeCommitMessage(goal), ctx.cwd);
12019
12030
  refreshReportOrFail2(ctx, goal.id, updated);
12020
12031
  } catch (err) {
12021
12032
  process.stderr.write(
@@ -12723,7 +12734,7 @@ ${markdown}`, ctx.cwd);
12723
12734
  extra: { version: 1, ...managedGoal }
12724
12735
  };
12725
12736
  try {
12726
- putGoalState(ctx.config, goalId, goalState, `chore(goals): activate ${goalId}`, ctx.cwd);
12737
+ await putGoalStateAsync(ctx.config, goalId, goalState, `chore(goals): activate ${goalId}`, ctx.cwd);
12727
12738
  } catch (err) {
12728
12739
  process.stderr.write(
12729
12740
  `[createQaGoal] failed to persist goal state to state repo: ${err instanceof Error ? err.message : String(err)}
@@ -14999,11 +15010,11 @@ function listCompanyIntents(config, cwd) {
14999
15010
  }
15000
15011
  return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
15001
15012
  }
15002
- function listCompanyPortfolio(config, cwd) {
15013
+ async function listCompanyPortfolio(config, cwd) {
15003
15014
  const goals = [];
15004
- for (const id of listGoalStateIds(config, cwd)) {
15015
+ for (const id of await listGoalStateIdsAsync(config, cwd)) {
15005
15016
  if (!isCompanyIntentId(id)) continue;
15006
- const state = fetchGoalState(config, id, cwd);
15017
+ const state = await fetchGoalStateAsync(config, id, cwd);
15007
15018
  if (!state) continue;
15008
15019
  const destination = recordField5(state.extra.destination);
15009
15020
  goals.push({
@@ -15099,7 +15110,7 @@ var init_loadCompanyPortfolio = __esm({
15099
15110
  "use strict";
15100
15111
  init_companyIntent();
15101
15112
  loadCompanyPortfolio = async (ctx) => {
15102
- const portfolio = listCompanyPortfolio(ctx.config, ctx.cwd);
15113
+ const portfolio = await listCompanyPortfolio(ctx.config, ctx.cwd);
15103
15114
  ctx.data.companyPortfolio = portfolio;
15104
15115
  ctx.data.companyPortfolioJson = JSON.stringify(portfolio, null, 2);
15105
15116
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.392",
3
+ "version": "0.4.393",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",