@kody-ade/kody-engine 0.4.253 → 0.4.255

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 +254 -5
  2. package/package.json +22 -23
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.253",
18
+ version: "0.4.255",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative agentAction profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -6179,6 +6179,88 @@ var init_state2 = __esm({
6179
6179
  }
6180
6180
  });
6181
6181
 
6182
+ // src/goal/runLog.ts
6183
+ function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
6184
+ const logs = goalRunLogs(data);
6185
+ const existing = logs[goalId];
6186
+ const path48 = existing?.path ?? goalRunLogPath(goalId, data);
6187
+ logs[goalId] = {
6188
+ path: path48,
6189
+ events: [
6190
+ ...existing?.events ?? [],
6191
+ {
6192
+ version: 1,
6193
+ time: at,
6194
+ goalId,
6195
+ ...event
6196
+ }
6197
+ ]
6198
+ };
6199
+ }
6200
+ function flushGoalRunLogEvents(config, cwd, data) {
6201
+ const logs = goalRunLogs(data);
6202
+ for (const [goalId, log2] of Object.entries(logs)) {
6203
+ if (log2.events.length === 0) continue;
6204
+ const lines = `${log2.events.map((event) => JSON.stringify(event)).join("\n")}
6205
+ `;
6206
+ appendStateLine(config, cwd, log2.path, lines, `chore(goal-logs): append ${goalId}`);
6207
+ log2.events = [];
6208
+ }
6209
+ }
6210
+ function goalRunLogPath(goalId, data) {
6211
+ const startedAt = goalRunStartedAt(data);
6212
+ const runId = goalRunId(data);
6213
+ return `logs/goals/${safePathSegment(goalId)}/runs/${startedAt}-${runId}.jsonl`;
6214
+ }
6215
+ function goalRunLogs(data) {
6216
+ const existing = data[LOGS_KEY];
6217
+ if (existing && typeof existing === "object" && !Array.isArray(existing)) {
6218
+ return existing;
6219
+ }
6220
+ const logs = {};
6221
+ data[LOGS_KEY] = logs;
6222
+ return logs;
6223
+ }
6224
+ function goalRunStartedAt(data) {
6225
+ const existing = data[LOG_STARTED_KEY];
6226
+ if (typeof existing === "string" && existing.length > 0) return existing;
6227
+ const stamp = nowIso().replace(/[:.]/g, "-");
6228
+ data[LOG_STARTED_KEY] = stamp;
6229
+ return stamp;
6230
+ }
6231
+ function goalRunId(data) {
6232
+ const existing = data[LOG_RUN_KEY];
6233
+ if (typeof existing === "string" && existing.length > 0) return existing;
6234
+ const raw = stringValue(data.jobId) ?? githubRunId() ?? `local-${process.pid}-${Date.now()}`;
6235
+ const safe = safePathSegment(raw);
6236
+ data[LOG_RUN_KEY] = safe;
6237
+ return safe;
6238
+ }
6239
+ function githubRunId() {
6240
+ const runId = process.env.GITHUB_RUN_ID?.trim();
6241
+ if (!runId) return null;
6242
+ const attempt = process.env.GITHUB_RUN_ATTEMPT?.trim();
6243
+ return attempt ? `gh-${runId}-${attempt}` : `gh-${runId}`;
6244
+ }
6245
+ function stringValue(value) {
6246
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
6247
+ }
6248
+ function safePathSegment(value) {
6249
+ const safe = value.trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "");
6250
+ return safe || "unknown";
6251
+ }
6252
+ var LOGS_KEY, LOG_RUN_KEY, LOG_STARTED_KEY;
6253
+ var init_runLog = __esm({
6254
+ "src/goal/runLog.ts"() {
6255
+ "use strict";
6256
+ init_stateRepo();
6257
+ init_state2();
6258
+ LOGS_KEY = "__goalRunLogs";
6259
+ LOG_RUN_KEY = "__goalRunLogRunId";
6260
+ LOG_STARTED_KEY = "__goalRunLogStartedAt";
6261
+ }
6262
+ });
6263
+
6182
6264
  // src/goal/typeDefinitions.ts
6183
6265
  function cloneRoute(route) {
6184
6266
  return route.map((step) => ({
@@ -6918,6 +7000,59 @@ var init_goalAgentResponsibilityScheduling = __esm({
6918
7000
  });
6919
7001
 
6920
7002
  // src/scripts/advanceManagedGoal.ts
7003
+ function stageManagedGoalDecision(data, goalId, goal, goalState, decision) {
7004
+ if (decision.kind === "dispatch") {
7005
+ stageGoalRunLogEvent(data, goalId, {
7006
+ source: "goal-manager",
7007
+ event: "goal.tick.dispatch",
7008
+ goalType: goal.type,
7009
+ goalState,
7010
+ stage: decision.stage,
7011
+ evidence: decision.evidence,
7012
+ status: decision.kind,
7013
+ dispatch: {
7014
+ agentResponsibility: decision.agentResponsibility,
7015
+ agentAction: decision.agentAction,
7016
+ cliArgs: decision.cliArgs
7017
+ }
7018
+ });
7019
+ return;
7020
+ }
7021
+ if (decision.kind === "done") {
7022
+ stageGoalRunLogEvent(data, goalId, {
7023
+ source: "goal-manager",
7024
+ event: "goal.tick.done",
7025
+ goalType: goal.type,
7026
+ goalState: "done",
7027
+ stage: "done",
7028
+ status: decision.kind,
7029
+ reason: "managed goal complete"
7030
+ });
7031
+ return;
7032
+ }
7033
+ if (decision.kind === "idle") {
7034
+ stageGoalRunLogEvent(data, goalId, {
7035
+ source: "goal-manager",
7036
+ event: "goal.tick.idle",
7037
+ goalType: goal.type,
7038
+ goalState,
7039
+ stage: goal.stage,
7040
+ status: decision.kind,
7041
+ reason: decision.reason
7042
+ });
7043
+ return;
7044
+ }
7045
+ stageGoalRunLogEvent(data, goalId, {
7046
+ source: "goal-manager",
7047
+ event: `goal.tick.${decision.kind}`,
7048
+ goalType: goal.type,
7049
+ goalState,
7050
+ stage: decision.stage,
7051
+ evidence: decision.evidence,
7052
+ status: decision.kind,
7053
+ reason: decision.reason
7054
+ });
7055
+ }
6921
7056
  function readSimpleGoalTaskSummary(goalId, cwd) {
6922
7057
  const raw = gh(
6923
7058
  ["issue", "list", "--state", "all", "--label", `goal:${goalId}`, "--limit", "1000", "--json", "number,state"],
@@ -6984,6 +7119,7 @@ var init_advanceManagedGoal = __esm({
6984
7119
  "src/scripts/advanceManagedGoal.ts"() {
6985
7120
  "use strict";
6986
7121
  init_manager();
7122
+ init_runLog();
6987
7123
  init_state2();
6988
7124
  init_typeDefinitions();
6989
7125
  init_issue();
@@ -7003,6 +7139,14 @@ var init_advanceManagedGoal = __esm({
7003
7139
  ctx.output.reason = "goal has no managed-goal contract; nothing to advance";
7004
7140
  return;
7005
7141
  }
7142
+ stageGoalRunLogEvent(ctx.data, goal.id, {
7143
+ source: "goal-manager",
7144
+ event: "goal.tick.start",
7145
+ goalType: managed.type,
7146
+ goalState: goal.state,
7147
+ stage: managed.stage,
7148
+ facts: managed.facts
7149
+ });
7006
7150
  const previousGoalIdFact = managed.facts.goalId;
7007
7151
  managed.facts.goalId = goal.id;
7008
7152
  const restoreGoalIdFact = () => {
@@ -7017,6 +7161,15 @@ var init_advanceManagedGoal = __esm({
7017
7161
  if (!managed.blockers.includes(reason)) managed.blockers.push(reason);
7018
7162
  restoreGoalIdFact();
7019
7163
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
7164
+ stageGoalRunLogEvent(ctx.data, goal.id, {
7165
+ source: "goal-manager",
7166
+ event: "goal.tick.blocked",
7167
+ goalType: managed.type,
7168
+ goalState: goal.state,
7169
+ stage: managed.stage,
7170
+ status: "blocked",
7171
+ reason
7172
+ });
7020
7173
  ctx.output.reason = reason;
7021
7174
  return;
7022
7175
  }
@@ -7034,6 +7187,17 @@ var init_advanceManagedGoal = __esm({
7034
7187
  cliArgs: decision2.dispatch.cliArgs
7035
7188
  };
7036
7189
  }
7190
+ stageGoalRunLogEvent(ctx.data, goal.id, {
7191
+ source: "goal-manager",
7192
+ event: decision2.kind === "dispatch" ? "loop.tick.dispatch" : `loop.tick.${decision2.kind}`,
7193
+ goalType: managed.type,
7194
+ goalState: goal.state,
7195
+ stage: managed.stage,
7196
+ status: decision2.kind,
7197
+ reason: decision2.reason,
7198
+ target: decision2.dispatch?.cliArgs.goal && typeof decision2.dispatch.cliArgs.goal === "string" ? { type: "goal", id: decision2.dispatch.cliArgs.goal } : managed.loopTarget,
7199
+ dispatch: decision2.dispatch
7200
+ });
7037
7201
  ctx.output.reason = decision2.reason;
7038
7202
  return;
7039
7203
  }
@@ -7057,6 +7221,16 @@ var init_advanceManagedGoal = __esm({
7057
7221
  ...goal.raw.extra.saveReport === true ? { saveReport: true } : {}
7058
7222
  };
7059
7223
  }
7224
+ stageGoalRunLogEvent(ctx.data, goal.id, {
7225
+ source: "goal-manager",
7226
+ event: decision2.kind === "dispatch" ? "loop.tick.dispatch" : `loop.tick.${decision2.kind}`,
7227
+ goalType: managed.type,
7228
+ goalState: goal.state,
7229
+ stage: managed.stage,
7230
+ status: decision2.kind,
7231
+ reason: decision2.reason,
7232
+ dispatch: decision2.dispatch
7233
+ });
7060
7234
  ctx.output.reason = decision2.reason;
7061
7235
  return;
7062
7236
  }
@@ -7066,6 +7240,7 @@ var init_advanceManagedGoal = __esm({
7066
7240
  const decision = planManagedGoalTick(managed);
7067
7241
  restoreGoalIdFact();
7068
7242
  ctx.data.managedGoalDecision = decision;
7243
+ stageManagedGoalDecision(ctx.data, goal.id, managed, goal.state, decision);
7069
7244
  if (decision.kind === "done") {
7070
7245
  goal.state = "done";
7071
7246
  }
@@ -7616,6 +7791,16 @@ var init_appendCompanyIntentDecision = __esm({
7616
7791
  });
7617
7792
 
7618
7793
  // src/scripts/applyAgentResponsibilityReports.ts
7794
+ function flushLogs(ctx) {
7795
+ try {
7796
+ flushGoalRunLogEvents(ctx.config, ctx.cwd, ctx.data);
7797
+ } catch (err) {
7798
+ process.stderr.write(
7799
+ `[kody agentResponsibility-report] goal log persist failed (${err instanceof Error ? err.message : String(err)})
7800
+ `
7801
+ );
7802
+ }
7803
+ }
7619
7804
  function collectReports(raw, agentResult) {
7620
7805
  const out = [];
7621
7806
  if (Array.isArray(raw)) {
@@ -7648,6 +7833,15 @@ function groupGoalReports(reports) {
7648
7833
  }
7649
7834
  return grouped;
7650
7835
  }
7836
+ function completeSatisfiedManagedGoal(state) {
7837
+ if (state.state !== "active") return state;
7838
+ const managed = managedGoalFromState(state);
7839
+ if (!managed) return state;
7840
+ if (!managed.destination.evidence.every((evidence) => managed.facts[evidence] === true)) return state;
7841
+ const decision = planManagedGoalTick(managed);
7842
+ if (decision.kind !== "done") return state;
7843
+ return writeManagedGoalToState({ ...state, state: "done" }, managed);
7844
+ }
7651
7845
  function describeMessage(goalId, reports, results) {
7652
7846
  const pieces = [];
7653
7847
  if (reports && reports.length > 0) pieces.push(`report=${reports.length}`);
@@ -7660,6 +7854,8 @@ var init_applyAgentResponsibilityReports = __esm({
7660
7854
  "use strict";
7661
7855
  init_agent_responsibilityReport();
7662
7856
  init_agent_responsibilityResult();
7857
+ init_manager();
7858
+ init_runLog();
7663
7859
  init_state2();
7664
7860
  init_stateStore();
7665
7861
  applyAgentResponsibilityReports = async (ctx, _profile, agentResult) => {
@@ -7679,15 +7875,45 @@ var init_applyAgentResponsibilityReports = __esm({
7679
7875
  }
7680
7876
  let next = prior;
7681
7877
  for (const report of reportsByGoal.get(goalId) ?? []) {
7878
+ stageGoalRunLogEvent(ctx.data, goalId, {
7879
+ source: "goal-report",
7880
+ event: "goal.evidence.reported",
7881
+ goalState: prior.state,
7882
+ evidenceValues: report.evidence,
7883
+ facts: report.facts
7884
+ });
7682
7885
  next = applyAgentResponsibilityReportToGoalState(next, report);
7683
7886
  }
7684
7887
  if (goalId === resultGoalId) {
7685
7888
  const evidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
7686
7889
  for (const result of results) {
7890
+ stageGoalRunLogEvent(ctx.data, goalId, {
7891
+ source: "goal-report",
7892
+ event: "goal.result.applied",
7893
+ goalState: prior.state,
7894
+ evidence,
7895
+ status: result.status,
7896
+ reason: result.summary,
7897
+ facts: result.facts,
7898
+ artifacts: result.artifacts
7899
+ });
7687
7900
  next = applyAgentResponsibilityResultToObjectiveState(next, result, evidence);
7688
7901
  }
7689
7902
  }
7690
- if (serializeGoalState(next) === serializeGoalState(prior)) continue;
7903
+ next = completeSatisfiedManagedGoal(next);
7904
+ if (prior.state !== "done" && next.state === "done") {
7905
+ stageGoalRunLogEvent(ctx.data, goalId, {
7906
+ source: "goal-report",
7907
+ event: "goal.completed",
7908
+ goalState: "done",
7909
+ status: "done",
7910
+ reason: "destination evidence satisfied"
7911
+ });
7912
+ }
7913
+ if (serializeGoalState(next) === serializeGoalState(prior)) {
7914
+ flushLogs(ctx);
7915
+ continue;
7916
+ }
7691
7917
  putGoalState(
7692
7918
  ctx.config,
7693
7919
  goalId,
@@ -7695,6 +7921,7 @@ var init_applyAgentResponsibilityReports = __esm({
7695
7921
  describeMessage(goalId, reportsByGoal.get(goalId), results),
7696
7922
  ctx.cwd
7697
7923
  );
7924
+ flushLogs(ctx);
7698
7925
  }
7699
7926
  };
7700
7927
  }
@@ -7966,6 +8193,16 @@ var init_commitAndPush = __esm({
7966
8193
  });
7967
8194
 
7968
8195
  // src/scripts/commitGoalState.ts
8196
+ function flushLogs2(ctx) {
8197
+ try {
8198
+ flushGoalRunLogEvents(ctx.config, ctx.cwd, ctx.data);
8199
+ } catch (err) {
8200
+ process.stderr.write(
8201
+ `[goal-manager] goal log persist failed (${err instanceof Error ? err.message : String(err)})
8202
+ `
8203
+ );
8204
+ }
8205
+ }
7969
8206
  function describeCommitMessage(goal) {
7970
8207
  if (goal.state === "done") return `chore(goals): complete ${goal.id}`;
7971
8208
  return `chore(goals): update ${goal.id}`;
@@ -7974,13 +8211,23 @@ var commitGoalState;
7974
8211
  var init_commitGoalState = __esm({
7975
8212
  "src/scripts/commitGoalState.ts"() {
7976
8213
  "use strict";
8214
+ init_runLog();
7977
8215
  init_stateStore();
7978
8216
  commitGoalState = async (ctx) => {
7979
8217
  const goal = ctx.data.goal;
7980
- if (!goal) return;
7981
- if (ctx.data.goalPersistChanged !== true) return;
8218
+ if (!goal) {
8219
+ flushLogs2(ctx);
8220
+ return;
8221
+ }
8222
+ if (ctx.data.goalPersistChanged !== true) {
8223
+ flushLogs2(ctx);
8224
+ return;
8225
+ }
7982
8226
  const updated = ctx.data.goalPersistState;
7983
- if (!updated) return;
8227
+ if (!updated) {
8228
+ flushLogs2(ctx);
8229
+ return;
8230
+ }
7984
8231
  try {
7985
8232
  putGoalState(ctx.config, goal.id, updated, describeCommitMessage(goal), ctx.cwd);
7986
8233
  } catch (err) {
@@ -7988,6 +8235,8 @@ var init_commitGoalState = __esm({
7988
8235
  `[goal-manager] commitGoalState: persist to state repo failed (${err instanceof Error ? err.message : String(err)}); will retry next tick
7989
8236
  `
7990
8237
  );
8238
+ } finally {
8239
+ flushLogs2(ctx);
7991
8240
  }
7992
8241
  };
7993
8242
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.253",
3
+ "version": "0.4.255",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative agentAction profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,26 +12,6 @@
12
12
  "templates",
13
13
  "kody.config.schema.json"
14
14
  ],
15
- "scripts": {
16
- "kody:run": "tsx bin/kody.ts",
17
- "serve": "tsx bin/kody.ts serve",
18
- "serve:vscode": "tsx bin/kody.ts serve vscode",
19
- "serve:claude": "tsx bin/kody.ts serve claude",
20
- "build": "tsup && node scripts/copy-assets.cjs",
21
- "check:modularity": "tsx scripts/check-script-modularity.ts",
22
- "pretest": "pnpm check:modularity",
23
- "test": "vitest run tests/unit tests/int --coverage",
24
- "posttest": "tsx scripts/check-coverage-floor.ts",
25
- "test:smoke": "vitest run tests/smoke --no-coverage",
26
- "test:e2e": "vitest run tests/e2e --no-coverage",
27
- "test:all": "vitest run tests --no-coverage",
28
- "typecheck": "tsc --noEmit",
29
- "lint": "biome check",
30
- "lint:fix": "biome check --write",
31
- "format": "biome format --write",
32
- "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
33
- "prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build"
34
- },
35
15
  "dependencies": {
36
16
  "@actions/cache": "^6.0.0",
37
17
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
@@ -55,5 +35,24 @@
55
35
  "url": "git+https://github.com/aharonyaircohen/kody-engine.git"
56
36
  },
57
37
  "homepage": "https://github.com/aharonyaircohen/kody-engine",
58
- "bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
59
- }
38
+ "bugs": "https://github.com/aharonyaircohen/kody-engine/issues",
39
+ "scripts": {
40
+ "kody:run": "tsx bin/kody.ts",
41
+ "serve": "tsx bin/kody.ts serve",
42
+ "serve:vscode": "tsx bin/kody.ts serve vscode",
43
+ "serve:claude": "tsx bin/kody.ts serve claude",
44
+ "build": "tsup && node scripts/copy-assets.cjs",
45
+ "check:modularity": "tsx scripts/check-script-modularity.ts",
46
+ "pretest": "pnpm check:modularity",
47
+ "test": "vitest run tests/unit tests/int --coverage",
48
+ "posttest": "tsx scripts/check-coverage-floor.ts",
49
+ "test:smoke": "vitest run tests/smoke --no-coverage",
50
+ "test:e2e": "vitest run tests/e2e --no-coverage",
51
+ "test:all": "vitest run tests --no-coverage",
52
+ "typecheck": "tsc --noEmit",
53
+ "lint": "biome check",
54
+ "lint:fix": "biome check --write",
55
+ "format": "biome format --write",
56
+ "brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
57
+ }
58
+ }