@kody-ade/kody-engine 0.4.283 → 0.4.285

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 +74 -110
  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.285",
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];
@@ -6988,7 +6985,7 @@ function linkContext(stateRepo) {
6988
6985
  function githubBlobUrl(repo, filePath) {
6989
6986
  try {
6990
6987
  const parsed = parseStateRepoSlug(repo);
6991
- return `https://github.com/${parsed.owner}/${parsed.repo}/blob/main/${filePath}`;
6988
+ return `https://github.com/${parsed.owner}/${parsed.repo}/blob/${STATE_BRANCH}/${filePath}`;
6992
6989
  } catch {
6993
6990
  return void 0;
6994
6991
  }
@@ -7071,6 +7068,7 @@ var LOGS_KEY, LOG_RUN_KEY, LOG_STARTED_KEY;
7071
7068
  var init_runLog = __esm({
7072
7069
  "src/goal/runLog.ts"() {
7073
7070
  "use strict";
7071
+ init_stateBranch();
7074
7072
  init_stateRepo();
7075
7073
  init_state2();
7076
7074
  LOGS_KEY = "__goalRunLogs";
@@ -7081,69 +7079,73 @@ var init_runLog = __esm({
7081
7079
 
7082
7080
  // src/goal/managedTodoState.ts
7083
7081
  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);
7082
+ const data = parseJsonRecord(raw) ?? {};
7083
+ const items = normalizeItems(data.items);
7084
+ const destination = recordField(data.destination);
7085
+ 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
7086
  const facts = {
7090
- ...recordField(frontmatter.facts),
7091
- ...Object.fromEntries(items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed]))
7087
+ ...recordField(data.facts),
7088
+ ...Object.fromEntries(
7089
+ items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed])
7090
+ )
7092
7091
  };
7092
+ const route = Array.isArray(data.route) ? data.route : routeFromItems(items);
7093
7093
  return parseGoalState(filePath, {
7094
- ...frontmatter,
7094
+ ...data,
7095
7095
  id: goalId,
7096
- state: frontmatter.state ?? "active",
7096
+ version: data.version ?? 1,
7097
+ state: data.state ?? "active",
7098
+ type: data.type ?? "general",
7097
7099
  destination: {
7098
7100
  ...destination,
7099
- outcome: description || stringField2(destination.outcome),
7101
+ outcome: stringField2(data.description) || stringField2(destination.outcome),
7100
7102
  evidence
7101
7103
  },
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),
7104
+ capabilities: stringArray(data.capabilities).length > 0 ? stringArray(data.capabilities) : route.map((step) => stringField2(step.capability)).filter(Boolean),
7105
+ route,
7104
7106
  facts,
7105
- blockers: stringArray(frontmatter.blockers)
7107
+ blockers: stringArray(data.blockers)
7106
7108
  });
7107
7109
  }
7108
7110
  function isManagedTodoRaw(raw) {
7109
- return isManagedTodoFrontmatter(parseFrontmatter(raw));
7111
+ return isManagedTodoRecord(parseJsonRecord(raw) ?? {});
7110
7112
  }
7111
7113
  function serializeTodoGoalState(goalId, state, previousRaw) {
7112
7114
  const raw = JSON.parse(serializeGoalState(state));
7113
7115
  const destination = recordField(raw.destination);
7114
- const outcome = stringField2(destination.outcome);
7115
- const evidence = stringArray(destination.evidence);
7116
+ const outcome = stringField2(raw.description) || stringField2(destination.outcome);
7117
+ const evidence = stringArray(destination.evidence).length > 0 ? stringArray(destination.evidence) : stringArray(raw.evidence);
7116
7118
  const route = Array.isArray(raw.route) ? raw.route : [];
7117
7119
  const facts = recordField(raw.facts);
7118
7120
  const now = (/* @__PURE__ */ new Date()).toISOString();
7119
7121
  const createdAt = stringField2(raw.createdAt) || stringField2(raw.startedAt) || now;
7120
7122
  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(
7123
+ const previousItems = new Map(parseItemsFromAnyRaw(previousRaw ?? "").map((item) => [item.id, item]));
7124
+ const items = evidence.length > 0 ? evidence.map(
7125
+ (key) => itemFromEvidence(key, routeByEvidence.get(key), facts, createdAt, now, previousItems.get(key))
7126
+ ) : stringArray(raw.capabilities).map(
7123
7127
  (capability) => itemFromCapability(capability, createdAt, previousItems.get(capability))
7124
7128
  );
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");
7129
+ return `${JSON.stringify(
7130
+ {
7131
+ version: 1,
7132
+ ...raw,
7133
+ id: goalId,
7134
+ title: goalId,
7135
+ description: outcome,
7136
+ createdAt,
7137
+ managed: true,
7138
+ managedModel: raw.scheduleMode === "agentLoop" || raw.type === "agentLoop" ? "agentLoop" : "agentGoal",
7139
+ evidence,
7140
+ items
7141
+ },
7142
+ null,
7143
+ 2
7144
+ )}
7145
+ `;
7144
7146
  }
7145
- function isManagedTodoFrontmatter(frontmatter) {
7146
- return frontmatter.managed === true || frontmatter.managed === "true" || frontmatter.managedModel === "agentGoal" || frontmatter.managedModel === "agentLoop";
7147
+ function isManagedTodoRecord(record2) {
7148
+ return record2.managed === true || record2.managed === "true" || record2.managedModel === "agentGoal" || record2.managedModel === "agentLoop";
7147
7149
  }
7148
7150
  function itemFromEvidence(evidence, step, facts, createdAt, now, prior) {
7149
7151
  const completed = facts[evidence] === true;
@@ -7186,53 +7188,30 @@ function routeFromItems(items) {
7186
7188
  const stage = stringField2(meta.stage);
7187
7189
  const capability = stringField2(meta.capability);
7188
7190
  if (!evidence || !stage || !capability) return [];
7189
- return [{ evidence, stage, capability, ...meta.args ? { args: meta.args } : {}, ...meta.saveReport === true ? { saveReport: true } : {} }];
7191
+ return [
7192
+ {
7193
+ evidence,
7194
+ stage,
7195
+ capability,
7196
+ ...meta.args ? { args: meta.args } : {},
7197
+ ...meta.saveReport === true ? { saveReport: true } : {}
7198
+ }
7199
+ ];
7190
7200
  });
7191
7201
  }
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;
7202
+ function parseItemsFromAnyRaw(raw) {
7203
+ const json = parseJsonRecord(raw);
7204
+ return json ? normalizeItems(json.items) : [];
7220
7205
  }
7221
- function serializeFrontmatterValue(value) {
7222
- if (typeof value === "string") return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7223
- return `"${JSON.stringify(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7206
+ function normalizeItems(value) {
7207
+ return Array.isArray(value) ? value.filter((item) => item && typeof item === "object") : [];
7224
7208
  }
7225
- function itemsBlockRe() {
7226
- return /<!--\s*kody-todo-items-json\s*\r?\n([\s\S]*?)\r?\n-->/;
7227
- }
7228
- function parseItems(raw) {
7229
- const match = itemsBlockRe().exec(raw);
7230
- if (!match) return [];
7209
+ function parseJsonRecord(raw) {
7231
7210
  try {
7232
- const parsed = JSON.parse(match[1] ?? "[]");
7233
- return Array.isArray(parsed) ? parsed.filter((item) => item && typeof item === "object") : [];
7211
+ const parsed = JSON.parse(raw);
7212
+ return recordField(parsed);
7234
7213
  } catch {
7235
- return [];
7214
+ return null;
7236
7215
  }
7237
7216
  }
7238
7217
  function recordField(value) {
@@ -7253,22 +7232,14 @@ var init_managedTodoState = __esm({
7253
7232
 
7254
7233
  // src/goal/stateStore.ts
7255
7234
  function goalStatePath(goalId) {
7256
- return `todos/${goalId}.md`;
7257
- }
7258
- function legacyGoalStatePath(goalId) {
7259
- return `goals/instances/${goalId}/state.json`;
7235
+ return `todos/${goalId}.json`;
7260
7236
  }
7261
7237
  function fetchGoalState(config, goalId, cwd) {
7262
7238
  const filePath = goalStatePath(goalId);
7263
7239
  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));
7240
+ if (!loaded) return null;
7241
+ if (!isManagedTodoRaw(loaded.content)) return null;
7242
+ return parseTodoGoalState(goalId, loaded.path, loaded.content);
7272
7243
  }
7273
7244
  function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
7274
7245
  const previous = readStateText(config, cwd, goalStatePath(goalId));
@@ -7279,26 +7250,19 @@ function putGoalState(config, goalId, state, message = `chore(goals): update ${g
7279
7250
  }
7280
7251
  function listGoalStateIds(config, cwd) {
7281
7252
  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);
7253
+ const todoEntries = listStateDirectory(config, cwd, "todos");
7254
+ for (const entry of todoEntries) {
7255
+ if (entry.type !== "file" || !entry.name?.endsWith(".json")) continue;
7256
+ const id = entry.name.slice(0, -5);
7287
7257
  const loaded = readStateText(config, cwd, goalStatePath(id));
7288
7258
  if (loaded && isManagedTodoRaw(loaded.content)) ids.add(id);
7289
7259
  }
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
7260
  return [...ids].sort();
7296
7261
  }
7297
7262
  var init_stateStore = __esm({
7298
7263
  "src/goal/stateStore.ts"() {
7299
7264
  "use strict";
7300
7265
  init_stateRepo();
7301
- init_state2();
7302
7266
  init_managedTodoState();
7303
7267
  }
7304
7268
  });
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.285",
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",