@kody-ade/kody-engine 0.4.281 → 0.4.282

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 +278 -78
  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.281",
18
+ version: "0.4.282",
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",
@@ -724,10 +724,10 @@ function parseStateConfig(raw, github) {
724
724
  const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nested.path;
725
725
  const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${String(github.owner)}/kody-state`;
726
726
  parseStateRepoSlug(stateRepo);
727
- const statePath2 = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : String(github.repo);
727
+ const statePath = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : String(github.repo);
728
728
  return {
729
729
  repo: stateRepo,
730
- path: normalizeStatePath(statePath2)
730
+ path: normalizeStatePath(statePath)
731
731
  };
732
732
  }
733
733
  function parseAccessConfig(raw) {
@@ -6745,7 +6745,7 @@ function goalRunLogPath(goalId, data) {
6745
6745
  return `logs/goals/${safePathSegment(goalId)}/runs/${startedAt}-${runId}.jsonl`;
6746
6746
  }
6747
6747
  function goalStateLogPath(goalId) {
6748
- return `goals/instances/${safePathSegment(goalId)}/state.json`;
6748
+ return `todos/${safePathSegment(goalId)}.md`;
6749
6749
  }
6750
6750
  function goalRunLogSnapshot(goalId, goalState, goal) {
6751
6751
  const requiredEvidence = [...goal.destination.evidence];
@@ -6984,9 +6984,9 @@ function linkContext(stateRepo) {
6984
6984
  const server = process.env.GITHUB_SERVER_URL?.trim() || "https://github.com";
6985
6985
  if (runId && repository) links.workflowRun = `${server}/${repository}/actions/runs/${runId}`;
6986
6986
  const repo = stringValue(stateRepo?.repo);
6987
- const goalStatePath = stringValue(stateRepo?.goalStatePath);
6987
+ const goalStatePath2 = stringValue(stateRepo?.goalStatePath);
6988
6988
  const logPath = stringValue(stateRepo?.logPath);
6989
- if (repo && goalStatePath) links.goalState = githubBlobUrl(repo, goalStatePath);
6989
+ if (repo && goalStatePath2) links.goalState = githubBlobUrl(repo, goalStatePath2);
6990
6990
  if (repo && logPath) links.log = githubBlobUrl(repo, logPath);
6991
6991
  return Object.keys(links).length > 0 ? links : void 0;
6992
6992
  }
@@ -7084,24 +7084,227 @@ var init_runLog = __esm({
7084
7084
  }
7085
7085
  });
7086
7086
 
7087
+ // src/goal/managedTodoState.ts
7088
+ 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);
7094
+ const facts = {
7095
+ ...recordField(frontmatter.facts),
7096
+ ...Object.fromEntries(items.map((item) => [stringField2(recordField(item.meta).evidence) || item.id, item.completed]))
7097
+ };
7098
+ return parseGoalState(filePath, {
7099
+ ...frontmatter,
7100
+ id: goalId,
7101
+ state: frontmatter.state ?? "active",
7102
+ destination: {
7103
+ ...destination,
7104
+ outcome: description || stringField2(destination.outcome),
7105
+ evidence
7106
+ },
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),
7109
+ facts,
7110
+ blockers: stringArray(frontmatter.blockers)
7111
+ });
7112
+ }
7113
+ function isManagedTodoRaw(raw) {
7114
+ return isManagedTodoFrontmatter(parseFrontmatter(raw));
7115
+ }
7116
+ function serializeTodoGoalState(goalId, state, previousRaw) {
7117
+ const raw = JSON.parse(serializeGoalState(state));
7118
+ const destination = recordField(raw.destination);
7119
+ const outcome = stringField2(destination.outcome);
7120
+ const evidence = stringArray(destination.evidence);
7121
+ const route = Array.isArray(raw.route) ? raw.route : [];
7122
+ const facts = recordField(raw.facts);
7123
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7124
+ const createdAt = stringField2(raw.createdAt) || stringField2(raw.startedAt) || now;
7125
+ 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(
7128
+ (capability) => itemFromCapability(capability, createdAt, previousItems.get(capability))
7129
+ );
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");
7149
+ }
7150
+ function isManagedTodoFrontmatter(frontmatter) {
7151
+ return frontmatter.managed === true || frontmatter.managed === "true" || frontmatter.managedModel === "agentGoal" || frontmatter.managedModel === "agentLoop";
7152
+ }
7153
+ function itemFromEvidence(evidence, step, facts, createdAt, now, prior) {
7154
+ const completed = facts[evidence] === true;
7155
+ return {
7156
+ id: evidence,
7157
+ title: (prior?.title ?? stringField2(step?.stage)) || evidence,
7158
+ body: prior?.body ?? "",
7159
+ assignee: prior?.assignee ?? null,
7160
+ completed,
7161
+ createdAt: prior?.createdAt ?? createdAt,
7162
+ completedAt: completed ? prior?.completedAt ?? now : null,
7163
+ meta: {
7164
+ ...prior?.meta ?? {},
7165
+ evidence,
7166
+ ...step ? {
7167
+ stage: stringField2(step.stage),
7168
+ capability: stringField2(step.capability),
7169
+ ...step.args && typeof step.args === "object" ? { args: step.args } : {},
7170
+ ...step.saveReport === true ? { saveReport: true } : {}
7171
+ } : {}
7172
+ }
7173
+ };
7174
+ }
7175
+ function itemFromCapability(capability, createdAt, prior) {
7176
+ return {
7177
+ id: capability,
7178
+ title: prior?.title ?? capability,
7179
+ body: prior?.body ?? "",
7180
+ assignee: prior?.assignee ?? null,
7181
+ completed: prior?.completed ?? false,
7182
+ createdAt: prior?.createdAt ?? createdAt,
7183
+ completedAt: prior?.completedAt ?? null,
7184
+ meta: { ...prior?.meta ?? {}, capability }
7185
+ };
7186
+ }
7187
+ function routeFromItems(items) {
7188
+ return items.flatMap((item) => {
7189
+ const meta = recordField(item.meta);
7190
+ const evidence = stringField2(meta.evidence) || item.id;
7191
+ const stage = stringField2(meta.stage);
7192
+ const capability = stringField2(meta.capability);
7193
+ if (!evidence || !stage || !capability) return [];
7194
+ return [{ evidence, stage, capability, ...meta.args ? { args: meta.args } : {}, ...meta.saveReport === true ? { saveReport: true } : {} }];
7195
+ });
7196
+ }
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;
7225
+ }
7226
+ function serializeFrontmatterValue(value) {
7227
+ if (typeof value === "string") return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7228
+ return `"${JSON.stringify(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
7229
+ }
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 [];
7236
+ try {
7237
+ const parsed = JSON.parse(match[1] ?? "[]");
7238
+ return Array.isArray(parsed) ? parsed.filter((item) => item && typeof item === "object") : [];
7239
+ } catch {
7240
+ return [];
7241
+ }
7242
+ }
7243
+ function recordField(value) {
7244
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
7245
+ }
7246
+ function stringField2(value) {
7247
+ return typeof value === "string" ? value : "";
7248
+ }
7249
+ function stringArray(value) {
7250
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
7251
+ }
7252
+ var init_managedTodoState = __esm({
7253
+ "src/goal/managedTodoState.ts"() {
7254
+ "use strict";
7255
+ init_state2();
7256
+ }
7257
+ });
7258
+
7087
7259
  // src/goal/stateStore.ts
7088
- function statePath(goalId) {
7260
+ function goalStatePath(goalId) {
7261
+ return `todos/${goalId}.md`;
7262
+ }
7263
+ function legacyGoalStatePath(goalId) {
7089
7264
  return `goals/instances/${goalId}/state.json`;
7090
7265
  }
7091
7266
  function fetchGoalState(config, goalId, cwd) {
7092
- const filePath = statePath(goalId);
7267
+ const filePath = goalStatePath(goalId);
7093
7268
  const loaded = readStateText(config, cwd, filePath);
7094
- if (!loaded) return null;
7095
- return parseGoalState(loaded.path, JSON.parse(loaded.content));
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));
7096
7277
  }
7097
7278
  function putGoalState(config, goalId, state, message = `chore(goals): update ${goalId}`, cwd) {
7098
- upsertStateText(config, cwd, statePath(goalId), serializeGoalState(state), message);
7279
+ const previous = readStateText(config, cwd, goalStatePath(goalId));
7280
+ if (previous && !isManagedTodoRaw(previous.content)) {
7281
+ throw new Error(`Cannot overwrite regular todo list ${goalId} as managed goal`);
7282
+ }
7283
+ upsertStateText(config, cwd, goalStatePath(goalId), serializeTodoGoalState(goalId, state, previous?.content), message);
7284
+ }
7285
+ function listGoalStateIds(config, cwd) {
7286
+ 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);
7292
+ const loaded = readStateText(config, cwd, goalStatePath(id));
7293
+ if (loaded && isManagedTodoRaw(loaded.content)) ids.add(id);
7294
+ }
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
+ return [...ids].sort();
7099
7301
  }
7100
7302
  var init_stateStore = __esm({
7101
7303
  "src/goal/stateStore.ts"() {
7102
7304
  "use strict";
7103
7305
  init_stateRepo();
7104
7306
  init_state2();
7307
+ init_managedTodoState();
7105
7308
  }
7106
7309
  });
7107
7310
 
@@ -7156,10 +7359,9 @@ function hasExplicitStateRepo(config) {
7156
7359
  return !!state && typeof state.repo === "string" && state.repo.trim().length > 0 && typeof state.path === "string" && state.path.trim().length > 0;
7157
7360
  }
7158
7361
  function findActiveTargetInstance(config, cwd, loopGoalId, targetId) {
7159
- const entries = listStateDirectory(config, cwd, "goals/instances");
7160
7362
  const candidates = [];
7161
- for (const entry of entries) {
7162
- const id = typeof entry.name === "string" ? entry.name.trim() : "";
7363
+ for (const entryId of listGoalStateIds(config, cwd)) {
7364
+ const id = entryId.trim();
7163
7365
  if (!id || id === loopGoalId || id === targetId || !id.startsWith(`${targetId}-`)) continue;
7164
7366
  assertSafeGoalId(id, "goal instance");
7165
7367
  const state = fetchGoalState(config, id, cwd);
@@ -7261,7 +7463,6 @@ var init_targetLoopResolution = __esm({
7261
7463
  "src/goal/targetLoopResolution.ts"() {
7262
7464
  "use strict";
7263
7465
  init_companyStore();
7264
- init_stateRepo();
7265
7466
  init_stateStore();
7266
7467
  }
7267
7468
  });
@@ -7276,7 +7477,7 @@ function cloneRoute(route) {
7276
7477
  ...step.args ? { args: structuredClone(step.args) } : {}
7277
7478
  }));
7278
7479
  }
7279
- function stringArray(value) {
7480
+ function stringArray2(value) {
7280
7481
  return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : null;
7281
7482
  }
7282
7483
  function routeArray(value) {
@@ -7306,11 +7507,11 @@ function expandManagedGoalState(state) {
7306
7507
  if (!definition) return state;
7307
7508
  const destination = state.extra.destination && typeof state.extra.destination === "object" && !Array.isArray(state.extra.destination) ? { ...state.extra.destination } : {};
7308
7509
  const outcome = typeof destination.outcome === "string" ? destination.outcome : "";
7309
- const evidence = stringArray(destination.evidence);
7310
- const capabilities = stringArray(state.extra.capabilities);
7510
+ const evidence = stringArray2(destination.evidence);
7511
+ const capabilities = stringArray2(state.extra.capabilities);
7311
7512
  const route = routeArray(state.extra.route);
7312
7513
  const facts = state.extra.facts && typeof state.extra.facts === "object" && !Array.isArray(state.extra.facts) ? { ...state.extra.facts } : {};
7313
- const blockers = stringArray(state.extra.blockers);
7514
+ const blockers = stringArray2(state.extra.blockers);
7314
7515
  return {
7315
7516
  ...state,
7316
7517
  extra: {
@@ -8517,7 +8718,7 @@ function parseAction(value) {
8517
8718
  function parseCreateManagedGoal(input) {
8518
8719
  const route = Array.isArray(input.route) ? input.route.map(parseRouteStep) : [];
8519
8720
  if (route.length === 0) throw new Error("createManagedGoal requires route");
8520
- const evidence = stringArray2(input.evidence);
8721
+ const evidence = stringArray3(input.evidence);
8521
8722
  if (evidence.length === 0) throw new Error("createManagedGoal requires evidence");
8522
8723
  return {
8523
8724
  kind: "createManagedGoal",
@@ -8556,9 +8757,9 @@ function parseUpdateIntentPortfolio(input) {
8556
8757
  return {
8557
8758
  kind: "updateIntentPortfolio",
8558
8759
  intentId: slug(input.intentId, "intentId"),
8559
- goals: stringArray2(input.goals).filter(isSlug),
8560
- loops: stringArray2(input.loops).filter(isSlug),
8561
- capabilities: stringArray2(input.capabilities).filter(isSlug),
8760
+ goals: stringArray3(input.goals).filter(isSlug),
8761
+ loops: stringArray3(input.loops).filter(isSlug),
8762
+ capabilities: stringArray3(input.capabilities).filter(isSlug),
8562
8763
  reason: requiredString(input.reason, "reason")
8563
8764
  };
8564
8765
  }
@@ -8592,12 +8793,12 @@ function requiredString(value, field) {
8592
8793
  if (typeof value !== "string" || !value.trim()) throw new Error(`${field} is required`);
8593
8794
  return value.trim();
8594
8795
  }
8595
- function stringArray2(value) {
8796
+ function stringArray3(value) {
8596
8797
  if (!Array.isArray(value)) return [];
8597
8798
  return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
8598
8799
  }
8599
8800
  function nonEmptyStringArray(value, field) {
8600
- const values = stringArray2(value);
8801
+ const values = stringArray3(value);
8601
8802
  if (values.length === 0) throw new Error(`${field} must not be empty`);
8602
8803
  return values;
8603
8804
  }
@@ -8629,15 +8830,15 @@ function normalizeCompanyIntent(path50, raw) {
8629
8830
  throw new Error(`${path50}: intent must be JSON object`);
8630
8831
  }
8631
8832
  const input = raw;
8632
- const id = stringField2(input.id);
8833
+ const id = stringField3(input.id);
8633
8834
  if (!id || !isCompanyIntentId(id)) throw new Error(`${path50}: invalid intent id`);
8634
- const createdAt = stringField2(input.createdAt) || nowIso();
8635
- const updatedAt = stringField2(input.updatedAt) || createdAt;
8835
+ const createdAt = stringField3(input.createdAt) || nowIso();
8836
+ const updatedAt = stringField3(input.updatedAt) || createdAt;
8636
8837
  return {
8637
8838
  version: 1,
8638
8839
  id,
8639
8840
  status: oneOf2(input.status, ["active", "paused", "archived"], "active"),
8640
- for: stringField2(input.for),
8841
+ for: stringField3(input.for),
8641
8842
  priority: numberField(input.priority, 100),
8642
8843
  posture: oneOf2(
8643
8844
  input.posture,
@@ -8645,21 +8846,21 @@ function normalizeCompanyIntent(path50, raw) {
8645
8846
  "balanced"
8646
8847
  ),
8647
8848
  scope: {
8648
- repos: stringArray3(recordField(input.scope)?.repos),
8649
- areas: stringArray3(recordField(input.scope)?.areas)
8849
+ repos: stringArray4(recordField2(input.scope)?.repos),
8850
+ areas: stringArray4(recordField2(input.scope)?.areas)
8650
8851
  },
8651
- principles: stringArray3(input.principles),
8652
- metrics: stringArray3(input.metrics),
8852
+ principles: stringArray4(input.principles),
8853
+ metrics: stringArray4(input.metrics),
8653
8854
  policy: {
8654
- release: normalizeReleasePolicy(recordField(recordField(input.policy)?.release)),
8655
- automation: normalizeAutomationPolicy(recordField(recordField(input.policy)?.automation))
8855
+ release: normalizeReleasePolicy(recordField2(recordField2(input.policy)?.release)),
8856
+ automation: normalizeAutomationPolicy(recordField2(recordField2(input.policy)?.automation))
8656
8857
  },
8657
8858
  portfolio: {
8658
- goals: stringArray3(recordField(input.portfolio)?.goals).filter(isCompanyIntentId),
8659
- loops: stringArray3(recordField(input.portfolio)?.loops).filter(isCompanyIntentId),
8660
- capabilities: stringArray3(recordField(input.portfolio)?.capabilities).filter(isCompanyIntentId)
8859
+ goals: stringArray4(recordField2(input.portfolio)?.goals).filter(isCompanyIntentId),
8860
+ loops: stringArray4(recordField2(input.portfolio)?.loops).filter(isCompanyIntentId),
8861
+ capabilities: stringArray4(recordField2(input.portfolio)?.capabilities).filter(isCompanyIntentId)
8661
8862
  },
8662
- manager: normalizeManager(recordField(input.manager)),
8863
+ manager: normalizeManager(recordField2(input.manager)),
8663
8864
  createdAt,
8664
8865
  updatedAt
8665
8866
  };
@@ -8695,20 +8896,18 @@ function appendCompanyIntentDecision(config, cwd, intentId, entry) {
8695
8896
  appendStateLine(config, cwd, `intents/${intentId}/decisions.jsonl`, JSON.stringify(entry), `chore(intents): log ${intentId} decision`);
8696
8897
  }
8697
8898
  function listCompanyPortfolio(config, cwd) {
8698
- const entries = listStateDirectory(config, cwd, "goals/instances");
8699
8899
  const goals = [];
8700
- for (const entry of entries) {
8701
- if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
8702
- const file = readStateText(config, cwd, `goals/instances/${entry.name}/state.json`);
8703
- if (!file) continue;
8704
- const state = parseGoalState(file.path, JSON.parse(file.content));
8705
- const destination = recordField(state.extra.destination);
8900
+ for (const id of listGoalStateIds(config, cwd)) {
8901
+ if (!isCompanyIntentId(id)) continue;
8902
+ const state = fetchGoalState(config, id, cwd);
8903
+ if (!state) continue;
8904
+ const destination = recordField2(state.extra.destination);
8706
8905
  goals.push({
8707
- id: entry.name,
8906
+ id,
8708
8907
  state: state.state,
8709
- type: stringField2(state.extra.type) || void 0,
8710
- outcome: stringField2(destination?.outcome) || void 0,
8711
- capabilities: stringArray3(state.extra.capabilities),
8908
+ type: stringField3(state.extra.type) || void 0,
8909
+ outcome: stringField3(destination?.outcome) || void 0,
8910
+ capabilities: stringArray4(state.extra.capabilities),
8712
8911
  isLoop: state.extra.scheduleMode === "agentLoop" || state.extra.type === "agentLoop",
8713
8912
  updatedAt: state.updatedAt
8714
8913
  });
@@ -8717,21 +8916,21 @@ function listCompanyPortfolio(config, cwd) {
8717
8916
  }
8718
8917
  function writeCompanyGoalState(config, cwd, id, state, message) {
8719
8918
  assertIntentId(id);
8720
- upsertStateText(config, cwd, `goals/instances/${id}/state.json`, serializeGoalState(state), message);
8919
+ putGoalState(config, id, state, message, cwd);
8721
8920
  }
8722
8921
  function assertIntentId(id) {
8723
8922
  if (!isCompanyIntentId(id)) throw new Error(`invalid intent/portfolio id: ${id}`);
8724
8923
  }
8725
- function stringField2(value) {
8924
+ function stringField3(value) {
8726
8925
  return typeof value === "string" ? value.trim() : "";
8727
8926
  }
8728
8927
  function numberField(value, fallback) {
8729
8928
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
8730
8929
  }
8731
- function recordField(value) {
8930
+ function recordField2(value) {
8732
8931
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
8733
8932
  }
8734
- function stringArray3(value) {
8933
+ function stringArray4(value) {
8735
8934
  if (!Array.isArray(value)) return [];
8736
8935
  return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
8737
8936
  }
@@ -8752,7 +8951,7 @@ function normalizeAutomationPolicy(raw) {
8752
8951
  authority: "full-auto",
8753
8952
  maxConcurrentGoals: Math.max(1, Math.floor(numberField(raw?.maxConcurrentGoals, 1))),
8754
8953
  maxDailyActions: Math.max(1, Math.floor(numberField(raw?.maxDailyActions, 6))),
8755
- requiresHumanFor: stringArray3(raw?.requiresHumanFor)
8954
+ requiresHumanFor: stringArray4(raw?.requiresHumanFor)
8756
8955
  };
8757
8956
  }
8758
8957
  function normalizeManager(raw) {
@@ -8769,6 +8968,7 @@ var init_companyIntent = __esm({
8769
8968
  "src/companyIntent.ts"() {
8770
8969
  "use strict";
8771
8970
  init_state2();
8971
+ init_stateStore();
8772
8972
  init_stateRepo();
8773
8973
  SLUG_RE2 = /^[a-z][a-z0-9-]{0,63}$/;
8774
8974
  }
@@ -9115,7 +9315,7 @@ function capabilityEvidenceOutput(evidence) {
9115
9315
  function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
9116
9316
  const outputs = evidenceItems.map(capabilityEvidenceOutput);
9117
9317
  const latestOutput = outputs.at(-1);
9118
- const facts = recordField2(snapshot, "facts") ?? recordField2(state.extra, "facts") ?? {};
9318
+ const facts = recordField3(snapshot, "facts") ?? recordField3(state.extra, "facts") ?? {};
9119
9319
  const blockers = uniqueStrings2([
9120
9320
  ...stringArrayField(snapshot, "blockers"),
9121
9321
  ...stringArrayField(latestEvent, "blockers"),
@@ -9134,12 +9334,12 @@ function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
9134
9334
  "",
9135
9335
  "## Status",
9136
9336
  `- State: ${state.state}`,
9137
- `- Stage: ${stringField3(snapshot, "stage") ?? stringField3(state.extra, "stage") ?? "unknown"}`,
9337
+ `- Stage: ${stringField4(snapshot, "stage") ?? stringField4(state.extra, "stage") ?? "unknown"}`,
9138
9338
  `- Next step: ${nextStepFromEvent(state, snapshot, latestOutput, latestEvent)}`,
9139
9339
  `- Updated: ${state.updatedAt ?? state.createdAt ?? state.startedAt ?? "unknown"}`,
9140
9340
  "",
9141
9341
  "## Decision",
9142
- `- Event: ${stringField3(latestEvent, "event") ?? "unknown"}`,
9342
+ `- Event: ${stringField4(latestEvent, "event") ?? "unknown"}`,
9143
9343
  `- Reason: ${decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers)}`,
9144
9344
  `- Required evidence: ${listOrNone(stringArrayField(snapshot, "requiredEvidence"))}`,
9145
9345
  `- Satisfied evidence: ${listOrNone(stringArrayField(snapshot, "satisfiedEvidence"))}`,
@@ -9167,9 +9367,9 @@ function capabilityEvidenceMarkdown(outputs) {
9167
9367
  function decisionReason(state, latestEvent, latestOutput, missingEvidence, blockers) {
9168
9368
  if (state.state === "done") return "destination evidence satisfied";
9169
9369
  if (blockers.length > 0) return blockers[0] ?? "blocked";
9170
- const eventReason = stringField3(latestEvent, "reason") ?? stringField3(recordField2(latestEvent, "decision"), "reason");
9370
+ const eventReason = stringField4(latestEvent, "reason") ?? stringField4(recordField3(latestEvent, "decision"), "reason");
9171
9371
  if (eventReason) return eventReason;
9172
- const summary = stringField3(latestOutput, "summary");
9372
+ const summary = stringField4(latestOutput, "summary");
9173
9373
  if (summary) return summary;
9174
9374
  if (missingEvidence.length > 0) return `waiting for ${missingEvidence[0]}`;
9175
9375
  return "waiting for more evidence";
@@ -9177,33 +9377,33 @@ function decisionReason(state, latestEvent, latestOutput, missingEvidence, block
9177
9377
  function evidenceOutputMarkdown(index, output) {
9178
9378
  return [
9179
9379
  `### Output ${index}`,
9180
- `- Status: ${stringField3(output, "status") ?? "unknown"}`,
9181
- `- Summary: ${stringField3(output, "summary") ?? "no summary"}`,
9380
+ `- Status: ${stringField4(output, "status") ?? "unknown"}`,
9381
+ `- Summary: ${stringField4(output, "summary") ?? "no summary"}`,
9182
9382
  `- Sources: ${listOrNone(stringArrayField(output, "sources"))}`,
9183
- `- Evidence values: ${inlineJson(recordField2(output, "evidence") ?? {})}`,
9383
+ `- Evidence values: ${inlineJson(recordField3(output, "evidence") ?? {})}`,
9184
9384
  `- Missing evidence: ${listOrNone(stringArrayField(output, "missingEvidence"))}`,
9185
9385
  `- Blockers: ${listOrNone(stringArrayField(output, "blockers"))}`,
9186
9386
  ""
9187
9387
  ];
9188
9388
  }
9189
9389
  function dispatchContextMarkdown(latestEvent) {
9190
- const context = recordField2(latestEvent, "dispatchContext");
9390
+ const context = recordField3(latestEvent, "dispatchContext");
9191
9391
  if (!context) return ["- none"];
9192
- const githubActor = stringField3(context, "githubActor");
9193
- const githubActorRole = stringField3(context, "githubActorRole");
9194
- const target = dispatchTargetLabel(recordField2(context, "target"));
9392
+ const githubActor = stringField4(context, "githubActor");
9393
+ const githubActorRole = stringField4(context, "githubActorRole");
9394
+ const target = dispatchTargetLabel(recordField3(context, "target"));
9195
9395
  return [
9196
- `- Triggered by: ${stringField3(context, "triggeredBy") ?? "unknown"}`,
9197
- `- Mode: ${stringField3(context, "dispatchMode") ?? "unknown"}`,
9396
+ `- Triggered by: ${stringField4(context, "triggeredBy") ?? "unknown"}`,
9397
+ `- Mode: ${stringField4(context, "dispatchMode") ?? "unknown"}`,
9198
9398
  `- GitHub actor: ${githubActor ? `${githubActor}${githubActorRole ? ` (${githubActorRole})` : ""}` : "none"}`,
9199
- `- Decided by: ${stringField3(context, "decidedBy") ?? "unknown"}`,
9200
- `- Dispatched by: ${stringField3(context, "dispatchedBy") ?? "unknown"}`,
9399
+ `- Decided by: ${stringField4(context, "decidedBy") ?? "unknown"}`,
9400
+ `- Dispatched by: ${stringField4(context, "dispatchedBy") ?? "unknown"}`,
9201
9401
  `- Target: ${target ?? "none"}`
9202
9402
  ];
9203
9403
  }
9204
9404
  function dispatchTargetLabel(target) {
9205
- const type = stringField3(target, "type");
9206
- const id = stringField3(target, "id");
9405
+ const type = stringField4(target, "type");
9406
+ const id = stringField4(target, "id");
9207
9407
  if (type && id) return `${type} ${id}`;
9208
9408
  return id ?? type;
9209
9409
  }
@@ -9226,11 +9426,11 @@ function listOrNone(values) {
9226
9426
  function uniqueStrings2(values) {
9227
9427
  return [...new Set(values)].sort();
9228
9428
  }
9229
- function stringField3(record2, key) {
9429
+ function stringField4(record2, key) {
9230
9430
  const value = record2?.[key];
9231
9431
  return typeof value === "string" && value.trim() ? value : void 0;
9232
9432
  }
9233
- function recordField2(record2, key) {
9433
+ function recordField3(record2, key) {
9234
9434
  const value = record2?.[key];
9235
9435
  return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : void 0;
9236
9436
  }
@@ -9263,7 +9463,7 @@ ${artifact.path ?? ""}`;
9263
9463
  }
9264
9464
  function nextStepFromEvent(state, goalAfter, capabilityOutput, latestEvent) {
9265
9465
  if (state.state === "done") return "done";
9266
- const decisionKind = stringField3(recordField2(latestEvent, "decision"), "kind") ?? stringField3(latestEvent, "status");
9466
+ const decisionKind = stringField4(recordField3(latestEvent, "decision"), "kind") ?? stringField4(latestEvent, "status");
9267
9467
  if (decisionKind === "done") return "done";
9268
9468
  if (decisionKind === "dispatch") return "dispatch";
9269
9469
  if (decisionKind === "blocked" || decisionKind === "reject-evidence") return "block";
@@ -15504,12 +15704,12 @@ async function loadGithubStateConfig(opts) {
15504
15704
  const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nestedState.path;
15505
15705
  const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${github.owner}/kody-state`;
15506
15706
  parseStateRepoSlug(stateRepo);
15507
- const statePath2 = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : github.repo;
15707
+ const statePath = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : github.repo;
15508
15708
  return {
15509
15709
  github,
15510
15710
  state: {
15511
15711
  repo: stateRepo,
15512
- path: normalizeStatePath(statePath2)
15712
+ path: normalizeStatePath(statePath)
15513
15713
  }
15514
15714
  };
15515
15715
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.281",
3
+ "version": "0.4.282",
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",