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