@kody-ade/kody-engine 0.4.282 → 0.4.284

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 +72 -114
  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.282",
18
+ version: "0.4.284",
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",
@@ -6520,11 +6520,6 @@ function planManagedGoalTick(goal) {
6520
6520
  delete goal.facts.pendingEvidence;
6521
6521
  return { kind: "done" };
6522
6522
  }
6523
- const pending = goal.facts.pendingEvidence;
6524
- if (pending === missing) {
6525
- const stage = typeof goal.stage === "string" ? goal.stage : "waiting";
6526
- return { kind: "wait", evidence: missing, stage, reason: `waiting for evidence: ${missing}` };
6527
- }
6528
6523
  const step = goal.route.find((candidate) => candidate.evidence === missing);
6529
6524
  if (!step) {
6530
6525
  if (isSimpleGoal(goal) && missing === SIMPLE_GOAL_EVIDENCE) {
@@ -6723,10 +6718,7 @@ function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
6723
6718
  const path50 = existing?.path ?? goalRunLogPath(goalId, data);
6724
6719
  logs[goalId] = {
6725
6720
  path: path50,
6726
- events: [
6727
- ...existing?.events ?? [],
6728
- buildGoalRunLogEvent(data, goalId, event, at)
6729
- ]
6721
+ events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
6730
6722
  };
6731
6723
  }
6732
6724
  function flushGoalRunLogEvents(config, cwd, data) {
@@ -6745,7 +6737,7 @@ function goalRunLogPath(goalId, data) {
6745
6737
  return `logs/goals/${safePathSegment(goalId)}/runs/${startedAt}-${runId}.jsonl`;
6746
6738
  }
6747
6739
  function goalStateLogPath(goalId) {
6748
- return `todos/${safePathSegment(goalId)}.md`;
6740
+ return `todos/${safePathSegment(goalId)}.json`;
6749
6741
  }
6750
6742
  function goalRunLogSnapshot(goalId, goalState, goal) {
6751
6743
  const requiredEvidence = [...goal.destination.evidence];
@@ -7086,69 +7078,73 @@ var init_runLog = __esm({
7086
7078
 
7087
7079
  // src/goal/managedTodoState.ts
7088
7080
  function parseTodoGoalState(goalId, filePath, raw) {
7089
- const frontmatter = parseFrontmatter(raw);
7090
- const description = raw.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(itemsBlockRe(), "").trim();
7091
- const items = parseItems(raw);
7092
- const destination = recordField(frontmatter.destination);
7093
- const evidence = stringArray(destination.evidence).length > 0 ? stringArray(destination.evidence) : stringArray(frontmatter.evidence).length > 0 ? stringArray(frontmatter.evidence) : items.map((item) => stringField2(recordField(item.meta).evidence) || item.id).filter(Boolean);
7081
+ const data = parseJsonRecord(raw) ?? {};
7082
+ const items = normalizeItems(data.items);
7083
+ const destination = recordField(data.destination);
7084
+ const evidence = stringArray(destination.evidence).length > 0 ? stringArray(destination.evidence) : stringArray(data.evidence).length > 0 ? stringArray(data.evidence) : items.map((item) => stringField2(recordField(item.meta).evidence) || item.id).filter(Boolean);
7094
7085
  const facts = {
7095
- ...recordField(frontmatter.facts),
7096
- ...Object.fromEntries(items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed]))
7086
+ ...recordField(data.facts),
7087
+ ...Object.fromEntries(
7088
+ items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed])
7089
+ )
7097
7090
  };
7091
+ const route = Array.isArray(data.route) ? data.route : routeFromItems(items);
7098
7092
  return parseGoalState(filePath, {
7099
- ...frontmatter,
7093
+ ...data,
7100
7094
  id: goalId,
7101
- state: frontmatter.state ?? "active",
7095
+ version: data.version ?? 1,
7096
+ state: data.state ?? "active",
7097
+ type: data.type ?? "general",
7102
7098
  destination: {
7103
7099
  ...destination,
7104
- outcome: description || stringField2(destination.outcome),
7100
+ outcome: stringField2(data.description) || stringField2(destination.outcome),
7105
7101
  evidence
7106
7102
  },
7107
- capabilities: stringArray(frontmatter.capabilities).length > 0 ? stringArray(frontmatter.capabilities) : items.map((item) => stringField2(recordField(item.meta).capability)).filter(Boolean),
7108
- route: Array.isArray(frontmatter.route) ? frontmatter.route : routeFromItems(items),
7103
+ capabilities: stringArray(data.capabilities).length > 0 ? stringArray(data.capabilities) : route.map((step) => stringField2(step.capability)).filter(Boolean),
7104
+ route,
7109
7105
  facts,
7110
- blockers: stringArray(frontmatter.blockers)
7106
+ blockers: stringArray(data.blockers)
7111
7107
  });
7112
7108
  }
7113
7109
  function isManagedTodoRaw(raw) {
7114
- return isManagedTodoFrontmatter(parseFrontmatter(raw));
7110
+ return isManagedTodoRecord(parseJsonRecord(raw) ?? {});
7115
7111
  }
7116
7112
  function serializeTodoGoalState(goalId, state, previousRaw) {
7117
7113
  const raw = JSON.parse(serializeGoalState(state));
7118
7114
  const destination = recordField(raw.destination);
7119
- const outcome = stringField2(destination.outcome);
7120
- const evidence = stringArray(destination.evidence);
7115
+ const outcome = stringField2(raw.description) || stringField2(destination.outcome);
7116
+ const evidence = stringArray(destination.evidence).length > 0 ? stringArray(destination.evidence) : stringArray(raw.evidence);
7121
7117
  const route = Array.isArray(raw.route) ? raw.route : [];
7122
7118
  const facts = recordField(raw.facts);
7123
7119
  const now = (/* @__PURE__ */ new Date()).toISOString();
7124
7120
  const createdAt = stringField2(raw.createdAt) || stringField2(raw.startedAt) || now;
7125
7121
  const routeByEvidence = new Map(route.map((step) => [stringField2(step.evidence), step]));
7126
- const previousItems = new Map(parseItems(previousRaw ?? "").map((item) => [item.id, item]));
7127
- const items = evidence.length > 0 ? evidence.map((key) => itemFromEvidence(key, routeByEvidence.get(key), facts, createdAt, now, previousItems.get(key))) : stringArray(raw.capabilities).map(
7122
+ const previousItems = new Map(parseItemsFromAnyRaw(previousRaw ?? "").map((item) => [item.id, item]));
7123
+ const items = evidence.length > 0 ? evidence.map(
7124
+ (key) => itemFromEvidence(key, routeByEvidence.get(key), facts, createdAt, now, previousItems.get(key))
7125
+ ) : stringArray(raw.capabilities).map(
7128
7126
  (capability) => itemFromCapability(capability, createdAt, previousItems.get(capability))
7129
7127
  );
7130
- delete raw.destination;
7131
- raw.id = goalId;
7132
- raw.title = goalId;
7133
- raw.createdAt = createdAt;
7134
- raw.managed = true;
7135
- raw.managedModel = raw.scheduleMode === "agentLoop" || raw.type === "agentLoop" ? "agentLoop" : "agentGoal";
7136
- raw.evidence = evidence;
7137
- return [
7138
- "---",
7139
- ...Object.entries(raw).filter(([, value]) => value !== void 0).map(([key, value]) => `${key}: ${serializeFrontmatterValue(value)}`),
7140
- "---",
7141
- "",
7142
- outcome,
7143
- "",
7144
- "<!-- kody-todo-items-json",
7145
- JSON.stringify(items, null, 2),
7146
- "-->",
7147
- ""
7148
- ].join("\n");
7128
+ return `${JSON.stringify(
7129
+ {
7130
+ version: 1,
7131
+ ...raw,
7132
+ id: goalId,
7133
+ title: goalId,
7134
+ description: outcome,
7135
+ createdAt,
7136
+ managed: true,
7137
+ managedModel: raw.scheduleMode === "agentLoop" || raw.type === "agentLoop" ? "agentLoop" : "agentGoal",
7138
+ evidence,
7139
+ items
7140
+ },
7141
+ null,
7142
+ 2
7143
+ )}
7144
+ `;
7149
7145
  }
7150
- function isManagedTodoFrontmatter(frontmatter) {
7151
- return frontmatter.managed === true || frontmatter.managed === "true" || frontmatter.managedModel === "agentGoal" || frontmatter.managedModel === "agentLoop";
7146
+ function isManagedTodoRecord(record2) {
7147
+ return record2.managed === true || record2.managed === "true" || record2.managedModel === "agentGoal" || record2.managedModel === "agentLoop";
7152
7148
  }
7153
7149
  function itemFromEvidence(evidence, step, facts, createdAt, now, prior) {
7154
7150
  const completed = facts[evidence] === true;
@@ -7191,53 +7187,30 @@ function routeFromItems(items) {
7191
7187
  const stage = stringField2(meta.stage);
7192
7188
  const capability = stringField2(meta.capability);
7193
7189
  if (!evidence || !stage || !capability) return [];
7194
- return [{ evidence, stage, capability, ...meta.args ? { args: meta.args } : {}, ...meta.saveReport === true ? { saveReport: true } : {} }];
7190
+ return [
7191
+ {
7192
+ evidence,
7193
+ stage,
7194
+ capability,
7195
+ ...meta.args ? { args: meta.args } : {},
7196
+ ...meta.saveReport === true ? { saveReport: true } : {}
7197
+ }
7198
+ ];
7195
7199
  });
7196
7200
  }
7197
- function parseFrontmatter(raw) {
7198
- const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
7199
- if (!match) return {};
7200
- const parsed = {};
7201
- for (const rawLine of (match[1] ?? "").split(/\r?\n/)) {
7202
- const line = rawLine.trim();
7203
- if (!line || line.startsWith("#")) continue;
7204
- const colon = line.indexOf(":");
7205
- if (colon === -1) continue;
7206
- parsed[line.slice(0, colon).trim()] = parseFrontmatterValue(line.slice(colon + 1).trim());
7207
- }
7208
- return parsed;
7209
- }
7210
- function parseFrontmatterValue(raw) {
7211
- let value = raw;
7212
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
7213
- value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
7214
- }
7215
- if (value === "true") return true;
7216
- if (value === "false") return false;
7217
- if (value === "null") return null;
7218
- if (value.startsWith("{") || value.startsWith("[") || /^-?\d+(\.\d+)?$/.test(value)) {
7219
- try {
7220
- return JSON.parse(value);
7221
- } catch {
7222
- }
7223
- }
7224
- return value;
7201
+ function parseItemsFromAnyRaw(raw) {
7202
+ const json = parseJsonRecord(raw);
7203
+ return json ? normalizeItems(json.items) : [];
7225
7204
  }
7226
- function serializeFrontmatterValue(value) {
7227
- if (typeof value === "string") return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7228
- return `"${JSON.stringify(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7205
+ function normalizeItems(value) {
7206
+ return Array.isArray(value) ? value.filter((item) => item && typeof item === "object") : [];
7229
7207
  }
7230
- function itemsBlockRe() {
7231
- return /<!--\s*kody-todo-items-json\s*\r?\n([\s\S]*?)\r?\n-->/;
7232
- }
7233
- function parseItems(raw) {
7234
- const match = itemsBlockRe().exec(raw);
7235
- if (!match) return [];
7208
+ function parseJsonRecord(raw) {
7236
7209
  try {
7237
- const parsed = JSON.parse(match[1] ?? "[]");
7238
- return Array.isArray(parsed) ? parsed.filter((item) => item && typeof item === "object") : [];
7210
+ const parsed = JSON.parse(raw);
7211
+ return recordField(parsed);
7239
7212
  } catch {
7240
- return [];
7213
+ return null;
7241
7214
  }
7242
7215
  }
7243
7216
  function recordField(value) {
@@ -7258,22 +7231,14 @@ var init_managedTodoState = __esm({
7258
7231
 
7259
7232
  // src/goal/stateStore.ts
7260
7233
  function goalStatePath(goalId) {
7261
- return `todos/${goalId}.md`;
7262
- }
7263
- function legacyGoalStatePath(goalId) {
7264
- return `goals/instances/${goalId}/state.json`;
7234
+ return `todos/${goalId}.json`;
7265
7235
  }
7266
7236
  function fetchGoalState(config, goalId, cwd) {
7267
7237
  const filePath = goalStatePath(goalId);
7268
7238
  const loaded = readStateText(config, cwd, filePath);
7269
- if (loaded) {
7270
- if (!isManagedTodoRaw(loaded.content)) return null;
7271
- return parseTodoGoalState(goalId, loaded.path, loaded.content);
7272
- }
7273
- const legacyPath = legacyGoalStatePath(goalId);
7274
- const legacy = readStateText(config, cwd, legacyPath);
7275
- if (!legacy) return null;
7276
- return parseGoalState(legacy.path, JSON.parse(legacy.content));
7239
+ if (!loaded) return null;
7240
+ if (!isManagedTodoRaw(loaded.content)) return null;
7241
+ return parseTodoGoalState(goalId, loaded.path, loaded.content);
7277
7242
  }
7278
7243
  function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
7279
7244
  const previous = readStateText(config, cwd, goalStatePath(goalId));
@@ -7284,26 +7249,19 @@ function putGoalState(config, goalId, state, message = `chore(goals): update ${g
7284
7249
  }
7285
7250
  function listGoalStateIds(config, cwd) {
7286
7251
  const ids = /* @__PURE__ */ new Set();
7287
- const todoFileIds = /* @__PURE__ */ new Set();
7288
- for (const entry of listStateDirectory(config, cwd, "todos")) {
7289
- if (entry.type !== "file" || !entry.name?.endsWith(".md")) continue;
7290
- const id = entry.name.slice(0, -3);
7291
- todoFileIds.add(id);
7252
+ const todoEntries = listStateDirectory(config, cwd, "todos");
7253
+ for (const entry of todoEntries) {
7254
+ if (entry.type !== "file" || !entry.name?.endsWith(".json")) continue;
7255
+ const id = entry.name.slice(0, -5);
7292
7256
  const loaded = readStateText(config, cwd, goalStatePath(id));
7293
7257
  if (loaded && isManagedTodoRaw(loaded.content)) ids.add(id);
7294
7258
  }
7295
- for (const entry of listStateDirectory(config, cwd, "goals/instances")) {
7296
- if (entry.type !== "dir" || !entry.name) continue;
7297
- if (todoFileIds.has(entry.name)) continue;
7298
- ids.add(entry.name);
7299
- }
7300
7259
  return [...ids].sort();
7301
7260
  }
7302
7261
  var init_stateStore = __esm({
7303
7262
  "src/goal/stateStore.ts"() {
7304
7263
  "use strict";
7305
7264
  init_stateRepo();
7306
- init_state2();
7307
7265
  init_managedTodoState();
7308
7266
  }
7309
7267
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.282",
3
+ "version": "0.4.284",
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",