@kody-ade/kody-engine 0.4.289 → 0.4.291

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.
package/README.md CHANGED
@@ -78,10 +78,6 @@ See [SECURITY.md](SECURITY.md) to report a vulnerability.
78
78
  │ src/executor.ts — runs capability implementations │
79
79
  │ .kody/capabilities/<slug>/ │
80
80
  │ profile.json · capability.md · optional skills/scripts │
81
- │ .kody/capabilities/<slug>/ │
82
- │ legacy fallback: profile.json · capability.md │
83
- │ .kody/executables/<name>/ │
84
- │ legacy fallback: profile.json · prompt.md · *.sh │
85
81
  │ src/scripts/*.ts — cross-cutting catalog │
86
82
  └─────────────────────────────────────────────┘
87
83
  ```
@@ -91,10 +87,10 @@ Every top-level command is an auto-discovered capability action. The router has
91
87
  after `@kody` through `config.aliases`, then falls back to the legacy-named
92
88
  `config.defaultExecutable` / `config.defaultPrExecutable` fields as default
93
89
  capability actions. Drop a new `.kody/capabilities/<slug>/` directory with
94
- `profile.json` + `capability.md`; legacy `.kody/capabilities/` and
95
- `.kody/executables/` roots still load while repos migrate.
90
+ `profile.json` + `capability.md`. Project/store `.kody/executables/` folders
91
+ are obsolete and are not resolver sources.
96
92
 
97
- Legacy Executable directories are private implementation units and contain
93
+ Capability implementation profiles are private implementation units and contain
98
94
  **only** three kinds of files: `profile.json` (declaration), `prompt.md` (agent
99
95
  instructions), and `.sh` scripts (mechanical side-effect work). Cross-cutting
100
96
  TypeScript lives in [src/scripts/](src/scripts/); it can't import from
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.289",
18
+ version: "0.4.291",
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",
@@ -1266,7 +1266,7 @@ var init_events = __esm({
1266
1266
  // src/verify.ts
1267
1267
  import { spawn } from "child_process";
1268
1268
  function runCommand(command, cwd) {
1269
- return new Promise((resolve9) => {
1269
+ return new Promise((resolve10) => {
1270
1270
  const start = Date.now();
1271
1271
  const child = spawn(command, {
1272
1272
  cwd,
@@ -1295,11 +1295,11 @@ function runCommand(command, cwd) {
1295
1295
  child.on("exit", (code) => {
1296
1296
  clearTimeout(timer);
1297
1297
  const tail = Buffer.concat(buffers).toString("utf-8").slice(-TAIL_CHARS);
1298
- resolve9({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
1298
+ resolve10({ exitCode: code ?? -1, durationMs: Date.now() - start, tail });
1299
1299
  });
1300
1300
  child.on("error", (err) => {
1301
1301
  clearTimeout(timer);
1302
- resolve9({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
1302
+ resolve10({ exitCode: -1, durationMs: Date.now() - start, tail: err.message });
1303
1303
  });
1304
1304
  });
1305
1305
  }
@@ -1907,6 +1907,8 @@ function parseCapabilityConfig(raw) {
1907
1907
  executable: stringField(raw.executable),
1908
1908
  tickScript: stringField(raw.tickScript),
1909
1909
  disabled: typeof raw.disabled === "boolean" ? raw.disabled : void 0,
1910
+ internal: typeof raw.internal === "boolean" ? raw.internal : void 0,
1911
+ public: typeof raw.public === "boolean" ? raw.public : void 0,
1910
1912
  agent: stringField(raw.agent),
1911
1913
  mentions: stringList(raw.mentions).map((m) => m.replace(/^@/, "")),
1912
1914
  tools,
@@ -2022,7 +2024,6 @@ function getCompanyStoreAssetRoot(kind) {
2022
2024
  if (!root) return null;
2023
2025
  const folderByKind = {
2024
2026
  capabilities: "capabilities",
2025
- executables: "executables",
2026
2027
  goals: "goals",
2027
2028
  agents: "agents",
2028
2029
  workflows: "workflows"
@@ -2128,15 +2129,9 @@ function getExecutablesRoot() {
2128
2129
  }
2129
2130
  return candidates[0];
2130
2131
  }
2131
- function getProjectExecutablesRoot() {
2132
- return path8.join(process.cwd(), ".kody", "executables");
2133
- }
2134
2132
  function getProjectCapabilitiesRoot() {
2135
2133
  return path8.join(process.cwd(), ".kody", "capabilities");
2136
2134
  }
2137
- function getCompanyStoreExecutablesRoot() {
2138
- return getCompanyStoreAssetRoot("executables");
2139
- }
2140
2135
  function getCompanyStoreCapabilitiesRoot() {
2141
2136
  return getCompanyStoreAssetRoot("capabilities");
2142
2137
  }
@@ -2157,14 +2152,10 @@ function getBuiltinCapabilitiesRoot() {
2157
2152
  }
2158
2153
  function getExecutableRoots() {
2159
2154
  const projectCapabilitiesRoot = getProjectCapabilitiesRoot();
2160
- const projectExecutablesRoot = getProjectExecutablesRoot();
2161
2155
  const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
2162
- const storeExecutablesRoot = getCompanyStoreExecutablesRoot();
2163
2156
  return [
2164
2157
  projectCapabilitiesRoot,
2165
- projectExecutablesRoot,
2166
2158
  ...storeCapabilitiesRoot ? [storeCapabilitiesRoot] : [],
2167
- ...storeExecutablesRoot ? [storeExecutablesRoot] : [],
2168
2159
  getExecutablesRoot()
2169
2160
  ];
2170
2161
  }
@@ -2216,21 +2207,12 @@ function listCapabilityActions(projectCapabilitiesRoot = getProjectCapabilitiesR
2216
2207
  seen.add(action.action);
2217
2208
  out.push(action);
2218
2209
  };
2219
- const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
2220
- const projectExecutableRoots = [getProjectExecutablesRoot()];
2221
- const storeExecutableRoot = getCompanyStoreExecutablesRoot();
2222
- const storeExecutableRoots = storeExecutableRoot ? [storeExecutableRoot] : [];
2223
2210
  for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder"))
2224
2211
  add(action);
2225
- for (const root of projectExecutableRoots) {
2226
- for (const action of listExecutableCapabilityActions(root, "project-executable")) add(action);
2227
- }
2212
+ const storeCapabilitiesRoot = getCompanyStoreCapabilitiesRoot();
2228
2213
  if (storeCapabilitiesRoot) {
2229
2214
  for (const action of listFolderCapabilityActions(storeCapabilitiesRoot, "company-store")) add(action);
2230
2215
  }
2231
- for (const root of storeExecutableRoots) {
2232
- for (const action of listExecutableCapabilityActions(root, "company-store-executable")) add(action);
2233
- }
2234
2216
  for (const action of listBuiltinCapabilityActions(getBuiltinCapabilitiesRoot())) add(action);
2235
2217
  return out.sort((a, b) => a.action.localeCompare(b.action));
2236
2218
  }
@@ -2294,34 +2276,6 @@ function isImplementationProfile(profilePath, requireImplementationProfile) {
2294
2276
  return false;
2295
2277
  }
2296
2278
  }
2297
- function listExecutableCapabilityActions(root, source) {
2298
- if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
2299
- const out = [];
2300
- for (const ent of fs6.readdirSync(root, { withFileTypes: true })) {
2301
- if (!ent.isDirectory() || !isSafeName(ent.name)) continue;
2302
- const profilePath = path8.join(root, ent.name, CAPABILITY_PROFILE_FILE);
2303
- if (!fs6.existsSync(profilePath) || !fs6.statSync(profilePath).isFile()) continue;
2304
- try {
2305
- const raw = JSON.parse(fs6.readFileSync(profilePath, "utf-8"));
2306
- const action = typeof raw.action === "string" && raw.action.trim() ? raw.action.trim() : "";
2307
- if (!action) continue;
2308
- if (!PUBLIC_EXECUTABLE_ROLES.has(String(raw.role))) continue;
2309
- if (typeof raw.kind !== "string" || !raw.kind.trim()) continue;
2310
- if (!Array.isArray(raw.inputs)) continue;
2311
- out.push({
2312
- action,
2313
- capability: ent.name,
2314
- executable: ent.name,
2315
- cliArgs: {},
2316
- source,
2317
- describe: typeof raw.describe === "string" ? raw.describe : void 0,
2318
- profilePath
2319
- });
2320
- } catch {
2321
- }
2322
- }
2323
- return out.sort((a, b) => a.action.localeCompare(b.action));
2324
- }
2325
2279
  function listFolderCapabilityActions(root, source) {
2326
2280
  if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
2327
2281
  const out = [];
@@ -2329,6 +2283,7 @@ function listFolderCapabilityActions(root, source) {
2329
2283
  if (!isSafeName(slug2)) continue;
2330
2284
  const capability = readCapabilityFolder(root, slug2);
2331
2285
  if (!capability) continue;
2286
+ if (capability.config.internal === true || capability.config.public === false) continue;
2332
2287
  const action = capability.config.action ?? slug2;
2333
2288
  const { executable, cliArgs } = resolveCapabilityExecution(capability);
2334
2289
  out.push({
@@ -2978,7 +2933,7 @@ var init_repoWorkspace = __esm({
2978
2933
  defaultCloneRepo = (repo, token, dir) => {
2979
2934
  fs7.mkdirSync(path9.dirname(dir), { recursive: true });
2980
2935
  const authUrl = token ? `https://x-access-token:${token}@github.com/${repo}.git` : `https://github.com/${repo}.git`;
2981
- return new Promise((resolve9, reject) => {
2936
+ return new Promise((resolve10, reject) => {
2982
2937
  const child = spawn2("git", ["clone", "--depth=1", authUrl, dir], {
2983
2938
  stdio: "inherit"
2984
2939
  });
@@ -2994,7 +2949,7 @@ var init_repoWorkspace = __esm({
2994
2949
  spawnSync("git", ["-C", dir, "config", "user.email", email]);
2995
2950
  } catch {
2996
2951
  }
2997
- resolve9();
2952
+ resolve10();
2998
2953
  });
2999
2954
  child.on("error", reject);
3000
2955
  });
@@ -3205,18 +3160,18 @@ async function runAgent(opts) {
3205
3160
  }
3206
3161
  if (opts.enableCapabilityTool) {
3207
3162
  const { buildCapabilityMcpServer: buildCapabilityMcpServer2 } = await Promise.resolve().then(() => (init_capabilityMcp(), capabilityMcp_exports));
3208
- if (!opts.dutyRepoSlug) {
3163
+ if (!opts.capabilityRepoSlug) {
3209
3164
  throw new Error(
3210
- "enableCapabilityTool requires dutyRepoSlug (owner/name) \u2014 set kody.config.json github.{owner,repo} or GITHUB_REPOSITORY env var"
3165
+ "enableCapabilityTool requires capabilityRepoSlug (owner/name) \u2014 set kody.config.json github.{owner,repo} or GITHUB_REPOSITORY env var"
3211
3166
  );
3212
3167
  }
3213
- const dutyHandle = buildCapabilityMcpServer2({
3214
- repoSlug: opts.dutyRepoSlug,
3168
+ const capabilityHandle = buildCapabilityMcpServer2({
3169
+ repoSlug: opts.capabilityRepoSlug,
3215
3170
  state: opts.capabilityState,
3216
3171
  operatorMention: opts.capabilityOperatorMention ?? "",
3217
3172
  ...opts.capabilitySlug ? { capabilitySlug: opts.capabilitySlug } : {}
3218
3173
  });
3219
- mcpEntries.push(["kody-capability", dutyHandle.server]);
3174
+ mcpEntries.push(["kody-capability", capabilityHandle.server]);
3220
3175
  }
3221
3176
  if (opts.enableDashboardCmsTool) {
3222
3177
  const { buildDashboardCmsMcpServer: buildDashboardCmsMcpServer2, DASHBOARD_CMS_MCP_TOOL_NAMES: DASHBOARD_CMS_MCP_TOOL_NAMES2 } = await Promise.resolve().then(() => (init_dashboardCmsMcp(), dashboardCmsMcp_exports));
@@ -3302,10 +3257,10 @@ async function runAgent(opts) {
3302
3257
  let timer;
3303
3258
  let next;
3304
3259
  if (turnTimeoutMs > 0) {
3305
- const timeoutPromise = new Promise((resolve9) => {
3260
+ const timeoutPromise = new Promise((resolve10) => {
3306
3261
  timer = setTimeout(() => {
3307
3262
  timedOut = true;
3308
- resolve9({ done: true, value: void 0 });
3263
+ resolve10({ done: true, value: void 0 });
3309
3264
  }, turnTimeoutMs);
3310
3265
  });
3311
3266
  next = await Promise.race([nextPromise, timeoutPromise]);
@@ -4255,18 +4210,29 @@ function loadProfile(profilePath) {
4255
4210
  if (!refPath) {
4256
4211
  throw new ProfileError(profilePath, `capability references unknown executable '${execRef}'`);
4257
4212
  }
4258
- const base = loadProfile(refPath);
4259
- return {
4260
- ...base,
4261
- name: requireString(profilePath, r, "name"),
4262
- action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
4263
- implementation: execRef,
4264
- executable: execRef,
4265
- describe: typeof r.describe === "string" ? r.describe : base.describe,
4266
- agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
4267
- capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
4268
- mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
4269
- };
4213
+ if (path19.resolve(refPath) === path19.resolve(profilePath)) {
4214
+ } else {
4215
+ const base = loadProfile(refPath);
4216
+ return {
4217
+ ...base,
4218
+ name: requireString(profilePath, r, "name"),
4219
+ action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
4220
+ implementation: execRef,
4221
+ executable: execRef,
4222
+ internal: typeof r.internal === "boolean" ? r.internal : base.internal,
4223
+ public: typeof r.public === "boolean" ? r.public : base.public,
4224
+ capabilityKind: parseCapabilityKind(r.capabilityKind) ?? base.capabilityKind,
4225
+ slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : base.slug,
4226
+ title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : base.title,
4227
+ skills: parseStringArray2(r.skills) ?? base.skills,
4228
+ prompt: typeof r.prompt === "string" && r.prompt.trim() ? r.prompt.trim() : base.prompt,
4229
+ chatTools: parseStringArray2(r.chatTools) ?? base.chatTools,
4230
+ describe: typeof r.describe === "string" ? r.describe : base.describe,
4231
+ agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
4232
+ capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
4233
+ mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
4234
+ };
4235
+ }
4270
4236
  }
4271
4237
  const kind = r.kind === "scheduled" ? "scheduled" : "oneshot";
4272
4238
  if (kind === "scheduled" && typeof r.schedule !== "string") {
@@ -4306,6 +4272,14 @@ function loadProfile(profilePath) {
4306
4272
  action: typeof r.action === "string" && r.action.trim() ? r.action.trim() : void 0,
4307
4273
  implementation: void 0,
4308
4274
  executable: void 0,
4275
+ internal: typeof r.internal === "boolean" ? r.internal : void 0,
4276
+ public: typeof r.public === "boolean" ? r.public : void 0,
4277
+ capabilityKind: parseCapabilityKind(r.capabilityKind),
4278
+ slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : void 0,
4279
+ title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : void 0,
4280
+ skills: parseStringArray2(r.skills),
4281
+ prompt: typeof r.prompt === "string" && r.prompt.trim() ? r.prompt.trim() : void 0,
4282
+ chatTools: parseStringArray2(r.chatTools),
4309
4283
  describe: typeof r.describe === "string" ? r.describe : "",
4310
4284
  // Optional agent to run as. Empty/blank string → undefined (no agent).
4311
4285
  agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : void 0,
@@ -4406,6 +4380,9 @@ function parseStringArray2(raw) {
4406
4380
  const values = raw.map((t) => String(t).trim()).filter(Boolean);
4407
4381
  return values.length > 0 ? values : void 0;
4408
4382
  }
4383
+ function parseCapabilityKind(raw) {
4384
+ return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
4385
+ }
4409
4386
  function parseInputs(p, raw) {
4410
4387
  if (!Array.isArray(raw)) throw new ProfileError(p, `"inputs" must be an array`);
4411
4388
  const out = [];
@@ -4670,6 +4647,14 @@ var init_profile = __esm({
4670
4647
  "implementations",
4671
4648
  "executable",
4672
4649
  "executables",
4650
+ "internal",
4651
+ "public",
4652
+ "capabilityKind",
4653
+ "slug",
4654
+ "title",
4655
+ "skills",
4656
+ "prompt",
4657
+ "chatTools",
4673
4658
  "agent",
4674
4659
  "every",
4675
4660
  "capabilityTools",
@@ -8145,7 +8130,7 @@ async function planGoalCapabilitySchedule(opts) {
8145
8130
  }
8146
8131
  };
8147
8132
  }
8148
- const dispatch2 = dutyDispatch(capability);
8133
+ const dispatch2 = capabilityDispatch(capability);
8149
8134
  statuses[due.slug] = markCapabilitySelected(statuses[due.slug], now);
8150
8135
  return {
8151
8136
  kind: "dispatch",
@@ -8205,7 +8190,7 @@ async function describeCapabilitySchedule(capability, slug2, backend, previous)
8205
8190
  lastFiredAt
8206
8191
  };
8207
8192
  }
8208
- function dutyDispatch(capability) {
8193
+ function capabilityDispatch(capability) {
8209
8194
  const { executable, cliArgs } = resolveCapabilityExecution(capability);
8210
8195
  return { capability: capability.slug, executable, cliArgs };
8211
8196
  }
@@ -9739,7 +9724,7 @@ var init_applyCapabilityReports = __esm({
9739
9724
  init_stateStore();
9740
9725
  applyCapabilityReports = async (ctx, _profile, agentResult) => {
9741
9726
  const reports = collectReports(ctx.data.capabilityReports, agentResult);
9742
- const results = collectResults(ctx.data.dutyResults, agentResult);
9727
+ const results = collectResults(ctx.data.capabilityResults ?? ctx.data.dutyResults, agentResult);
9743
9728
  const resultGoalId = typeof ctx.args.goal === "string" && ctx.args.goal.length > 0 ? ctx.args.goal : null;
9744
9729
  const explicitEvidence = typeof ctx.args.evidence === "string" && ctx.args.evidence.length > 0 ? ctx.args.evidence : void 0;
9745
9730
  const evidenceItems = collectGoalCapabilityEvidence(reports, results, resultGoalId, explicitEvidence);
@@ -10258,7 +10243,7 @@ function formatCapabilityReference(data, profileName) {
10258
10243
  if (capabilitySchedule) {
10259
10244
  lines.push(`- Cadence: \`${capabilitySchedule}\``);
10260
10245
  }
10261
- const capabilityBody = pickToken(data, "dutyIntent", "jobIntent");
10246
+ const capabilityBody = pickToken(data, "capabilityIntent", "jobIntent", "dutyIntent");
10262
10247
  if (capabilityBody) {
10263
10248
  lines.push("", "## Capability body", "", capabilityBody);
10264
10249
  }
@@ -12961,7 +12946,7 @@ function retryDelaysMs() {
12961
12946
  }
12962
12947
  function sleep(ms) {
12963
12948
  if (ms <= 0) return Promise.resolve();
12964
- return new Promise((resolve9) => setTimeout(resolve9, ms));
12949
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
12965
12950
  }
12966
12951
  async function fetchGoalStateWithRetry(config, goalId, cwd) {
12967
12952
  let state = fetchGoalState(config, goalId, cwd);
@@ -13798,6 +13783,11 @@ function normalizeBundleFiles(ctx, bundle) {
13798
13783
  if (!relativePath) {
13799
13784
  throw new Error(`openAgentFactoryStatePr: files[${index}].path must point to a state repo file`);
13800
13785
  }
13786
+ if (relativePath === "executables" || relativePath.startsWith("executables/")) {
13787
+ throw new Error(
13788
+ `openAgentFactoryStatePr: files[${index}].path uses obsolete executables storage; use capabilities/<slug>/ instead`
13789
+ );
13790
+ }
13801
13791
  if (seen.has(relativePath)) {
13802
13792
  throw new Error(`openAgentFactoryStatePr: duplicate generated file path: ${relativePath}`);
13803
13793
  }
@@ -15637,7 +15627,7 @@ var init_previewBuildHelpers = __esm({
15637
15627
  // src/scripts/previewBuildRun.ts
15638
15628
  import { spawn as spawn4 } from "child_process";
15639
15629
  async function runCmd(cmd, args, opts = {}) {
15640
- await new Promise((resolve9, reject) => {
15630
+ await new Promise((resolve10, reject) => {
15641
15631
  const child = spawn4(cmd, args, {
15642
15632
  cwd: opts.cwd,
15643
15633
  env: { ...process.env, ...opts.env ?? {} },
@@ -15649,7 +15639,7 @@ async function runCmd(cmd, args, opts = {}) {
15649
15639
  }
15650
15640
  child.on("error", reject);
15651
15641
  child.on("close", (code) => {
15652
- if (code === 0) resolve9();
15642
+ if (code === 0) resolve10();
15653
15643
  else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
15654
15644
  });
15655
15645
  });
@@ -16773,7 +16763,7 @@ function stripAnsi2(s) {
16773
16763
  return s.replace(ANSI_RE2, "");
16774
16764
  }
16775
16765
  function runCommand2(command, cwd) {
16776
- return new Promise((resolve9) => {
16766
+ return new Promise((resolve10) => {
16777
16767
  const child = spawn5(command, {
16778
16768
  cwd,
16779
16769
  shell: true,
@@ -16800,11 +16790,11 @@ function runCommand2(command, cwd) {
16800
16790
  }, TEST_TIMEOUT_MS);
16801
16791
  child.on("exit", (code) => {
16802
16792
  clearTimeout(timer);
16803
- resolve9({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
16793
+ resolve10({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
16804
16794
  });
16805
16795
  child.on("error", (err) => {
16806
16796
  clearTimeout(timer);
16807
- resolve9({ exitCode: -1, output: err.message });
16797
+ resolve10({ exitCode: -1, output: err.message });
16808
16798
  });
16809
16799
  });
16810
16800
  }
@@ -17209,21 +17199,21 @@ function lineStream(stream) {
17209
17199
  tryDeliver();
17210
17200
  });
17211
17201
  return {
17212
- next: (timeoutMs) => new Promise((resolve9) => {
17202
+ next: (timeoutMs) => new Promise((resolve10) => {
17213
17203
  if (queue.length > 0) {
17214
- resolve9(queue.shift());
17204
+ resolve10(queue.shift());
17215
17205
  return;
17216
17206
  }
17217
17207
  if (ended) {
17218
- resolve9(null);
17208
+ resolve10(null);
17219
17209
  return;
17220
17210
  }
17221
- waiter = resolve9;
17211
+ waiter = resolve10;
17222
17212
  const t = setTimeout(
17223
17213
  () => {
17224
- if (waiter === resolve9) {
17214
+ if (waiter === resolve10) {
17225
17215
  waiter = null;
17226
- resolve9(null);
17216
+ resolve10(null);
17227
17217
  }
17228
17218
  },
17229
17219
  Math.max(0, timeoutMs)
@@ -17712,7 +17702,6 @@ var init_stateWorkspace = __esm({
17712
17702
  "use strict";
17713
17703
  init_stateRepo();
17714
17704
  DIR_MAPPINGS = [
17715
- { stateDir: "executables", localDir: path41.join(".kody", "executables") },
17716
17705
  { stateDir: "capabilities", localDir: path41.join(".kody", "capabilities") },
17717
17706
  { stateDir: "agents", localDir: path41.join(".kody", "agents") },
17718
17707
  { stateDir: "context", localDir: path41.join(".kody", "context") },
@@ -17817,10 +17806,11 @@ function collectShellSideChannels(ctx, stdout) {
17817
17806
  const prior = Array.isArray(ctx.data.capabilityReports) ? ctx.data.capabilityReports : [];
17818
17807
  ctx.data.capabilityReports = [...prior, ...capabilityReports];
17819
17808
  }
17820
- const dutyResults = parseCapabilityResultsFromText(stdout);
17821
- if (dutyResults.length > 0) {
17822
- const prior = Array.isArray(ctx.data.dutyResults) ? ctx.data.dutyResults : [];
17823
- ctx.data.dutyResults = [...prior, ...dutyResults];
17809
+ const capabilityResults = parseCapabilityResultsFromText(stdout);
17810
+ if (capabilityResults.length > 0) {
17811
+ const prior = Array.isArray(ctx.data.capabilityResults) ? ctx.data.capabilityResults : Array.isArray(ctx.data.dutyResults) ? ctx.data.dutyResults : [];
17812
+ ctx.data.capabilityResults = [...prior, ...capabilityResults];
17813
+ ctx.data.dutyResults = ctx.data.capabilityResults;
17824
17814
  }
17825
17815
  }
17826
17816
  function operatorRequestBlock(why) {
@@ -18036,7 +18026,7 @@ async function runExecutable(profileName, input) {
18036
18026
  // owner/repo from kody.config.json; envelope falls back to GITHUB_REPOSITORY
18037
18027
  // for tester repos that don't set config.github (the file isn't always
18038
18028
  // checked in). Either way, capabilityMcp needs "owner/name" to hit the compare API.
18039
- dutyRepoSlug: config.github?.owner && config.github?.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY?.trim() || void 0,
18029
+ capabilityRepoSlug: config.github?.owner && config.github?.repo ? `${config.github.owner}/${config.github.repo}` : process.env.GITHUB_REPOSITORY?.trim() || void 0,
18040
18030
  verifyToolMaxAttempts: profile.claudeCode.verifyAttempts ?? null,
18041
18031
  verifyConfig: profile.claudeCode.enableVerifyTool ? config : void 0,
18042
18032
  executableName: profileName,
@@ -18513,14 +18503,14 @@ async function runShellEntry(entry, ctx, profile) {
18513
18503
  let killTimer;
18514
18504
  let escalateTimer;
18515
18505
  const result = await new Promise(
18516
- (resolve9) => {
18506
+ (resolve10) => {
18517
18507
  let settled = false;
18518
18508
  const settle = (code, signal, spawnErr) => {
18519
18509
  if (settled) return;
18520
18510
  settled = true;
18521
18511
  if (killTimer) clearTimeout(killTimer);
18522
18512
  if (escalateTimer) clearTimeout(escalateTimer);
18523
- resolve9({ code, signal, spawnErr });
18513
+ resolve10({ code, signal, spawnErr });
18524
18514
  };
18525
18515
  child.on("error", (err) => settle(null, null, err));
18526
18516
  child.on("close", (code, signal) => settle(code, signal));
@@ -18781,7 +18771,7 @@ async function runJob(job, base) {
18781
18771
  }
18782
18772
  const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
18783
18773
  const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
18784
- const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
18774
+ const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.role ? capabilityContext.slug : void 0) ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
18785
18775
  const profileName = valid.executable ?? capabilitySelectedExecutable;
18786
18776
  if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedExecutable, base)) {
18787
18777
  const workflowCapability = capabilityContext ?? workflowContext;
@@ -18825,6 +18815,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
18825
18815
  if (capabilityContext) {
18826
18816
  preloadedData.capabilitySlug = capabilityContext.slug;
18827
18817
  preloadedData.capabilityTitle = capabilityContext.title;
18818
+ preloadedData.capabilityIntent = capabilityContext.body;
18828
18819
  preloadedData.dutyIntent = capabilityContext.body;
18829
18820
  preloadedData.jobIntent = capabilityContext.body;
18830
18821
  if (preloadedData.jobCapability === void 0) preloadedData.jobCapability = capabilityContext.slug;
@@ -19509,11 +19500,11 @@ function buildExecutableCatalog() {
19509
19500
  if (entries.length === 0) return "";
19510
19501
  const lines = [
19511
19502
  "",
19512
- "# Available executables",
19503
+ "# Available capability implementations",
19513
19504
  "These run inside the engine, NOT inside this chat. You cannot invoke them",
19514
- "directly \u2014 to run one, tell the user to post `@kody <name>` (with any flags)",
19505
+ "directly \u2014 to run one, tell the user to post the matching `@kody <action>`",
19515
19506
  "as a comment on the relevant issue or PR. The dispatcher binds the issue/PR",
19516
- "number to the executable's inputs automatically.",
19507
+ "number to the implementation inputs automatically.",
19517
19508
  ""
19518
19509
  ];
19519
19510
  for (const e of entries) {
@@ -20729,12 +20720,12 @@ async function runCi(argv) {
20729
20720
  const evt = JSON.parse(fs46.readFileSync(dispatchEventPath, "utf-8"));
20730
20721
  const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
20731
20722
  const sessionInput = String(evt?.inputs?.sessionId ?? "");
20732
- const dutyInput = String(evt?.inputs?.capability ?? evt?.inputs?.executable ?? "").trim();
20723
+ const capabilityInput = String(evt?.inputs?.capability ?? evt?.inputs?.executable ?? "").trim();
20733
20724
  const messageInput = String(evt?.inputs?.message ?? "").trim();
20734
20725
  const noTarget = !sessionInput && !(Number.isFinite(issueInput) && issueInput > 0);
20735
- if (noTarget && dutyInput) {
20736
- forceRunAction = dutyInput;
20737
- if (dutyInput === "goal-manager" && messageInput) {
20726
+ if (noTarget && capabilityInput) {
20727
+ forceRunAction = capabilityInput;
20728
+ if (capabilityInput === "goal-manager" && messageInput) {
20738
20729
  forceRunCliArgs = { goal: messageInput };
20739
20730
  }
20740
20731
  } else {
@@ -20747,8 +20738,8 @@ async function runCi(argv) {
20747
20738
  if (forceRunAction) {
20748
20739
  const config = earlyConfig ?? loadConfig(cwd);
20749
20740
  const manualGoalManager = forceRunAction === "goal-manager";
20750
- const dutyRoute = manualGoalManager ? null : resolveCapabilityAction(forceRunAction);
20751
- const scheduledWatchRoute = manualGoalManager || dutyRoute ? void 0 : dispatchScheduledWatches({ force: true }).find(
20741
+ const capabilityRoute = manualGoalManager ? null : resolveCapabilityAction(forceRunAction);
20742
+ const scheduledWatchRoute = manualGoalManager || capabilityRoute ? void 0 : dispatchScheduledWatches({ force: true }).find(
20752
20743
  (match) => match.action === forceRunAction || match.executable === forceRunAction
20753
20744
  );
20754
20745
  const route = manualGoalManager ? {
@@ -20756,7 +20747,7 @@ async function runCi(argv) {
20756
20747
  capability: "goal-manager",
20757
20748
  executable: "goal-manager",
20758
20749
  cliArgs: forceRunCliArgs
20759
- } : dutyRoute ?? scheduledWatchRoute;
20750
+ } : capabilityRoute ?? scheduledWatchRoute;
20760
20751
  if (!route) {
20761
20752
  process.stderr.write(`[kody] manual one-shot action '${forceRunAction}' has no capability action
20762
20753
  `);
@@ -21250,17 +21241,17 @@ function authOk(req, expected) {
21250
21241
  return false;
21251
21242
  }
21252
21243
  function readJsonBody(req) {
21253
- return new Promise((resolve9, reject) => {
21244
+ return new Promise((resolve10, reject) => {
21254
21245
  const chunks = [];
21255
21246
  req.on("data", (c) => chunks.push(c));
21256
21247
  req.on("end", () => {
21257
21248
  const raw = Buffer.concat(chunks).toString("utf-8");
21258
21249
  if (!raw.trim()) {
21259
- resolve9({});
21250
+ resolve10({});
21260
21251
  return;
21261
21252
  }
21262
21253
  try {
21263
- resolve9(JSON.parse(raw));
21254
+ resolve10(JSON.parse(raw));
21264
21255
  } catch (err) {
21265
21256
  reject(err instanceof Error ? err : new Error(String(err)));
21266
21257
  }
@@ -21615,11 +21606,11 @@ async function brainServe(opts) {
21615
21606
  model,
21616
21607
  litellmUrl
21617
21608
  });
21618
- await new Promise((resolve9) => {
21609
+ await new Promise((resolve10) => {
21619
21610
  server.listen(port, "0.0.0.0", () => {
21620
21611
  process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
21621
21612
  `);
21622
- resolve9();
21613
+ resolve10();
21623
21614
  });
21624
21615
  });
21625
21616
  const shutdown = (signal) => {
@@ -21872,14 +21863,14 @@ async function startBrainProxy(opts) {
21872
21863
  const { httpServer, handler } = buildBrainProxy(opts);
21873
21864
  const port = opts.port ?? 0;
21874
21865
  const host = opts.host ?? "127.0.0.1";
21875
- await new Promise((resolve9) => httpServer.listen(port, host, () => resolve9()));
21866
+ await new Promise((resolve10) => httpServer.listen(port, host, () => resolve10()));
21876
21867
  const addr = httpServer.address();
21877
21868
  return {
21878
21869
  httpServer,
21879
21870
  port: addr.port,
21880
21871
  url: `http://${host}:${addr.port}`,
21881
- stop: () => new Promise((resolve9) => {
21882
- httpServer.close(() => resolve9());
21872
+ stop: () => new Promise((resolve10) => {
21873
+ httpServer.close(() => resolve10());
21883
21874
  }),
21884
21875
  handler
21885
21876
  };
@@ -22029,23 +22020,23 @@ function buildMcpHttpServer(opts) {
22029
22020
  httpServer,
22030
22021
  routes,
22031
22022
  port,
22032
- stop: () => new Promise((resolve9) => {
22023
+ stop: () => new Promise((resolve10) => {
22033
22024
  let pending = transports.size;
22034
22025
  if (pending === 0) {
22035
- httpServer.close(() => resolve9());
22026
+ httpServer.close(() => resolve10());
22036
22027
  return;
22037
22028
  }
22038
22029
  for (const transport of transports.values()) {
22039
22030
  void transport.close().finally(() => {
22040
22031
  pending--;
22041
- if (pending === 0) httpServer.close(() => resolve9());
22032
+ if (pending === 0) httpServer.close(() => resolve10());
22042
22033
  });
22043
22034
  }
22044
22035
  })
22045
22036
  };
22046
22037
  }
22047
22038
  function listenMcpHttpServer(server, host = "127.0.0.1") {
22048
- return new Promise((resolve9, reject) => {
22039
+ return new Promise((resolve10, reject) => {
22049
22040
  server.httpServer.once("error", reject);
22050
22041
  server.httpServer.listen(server.port, host, () => {
22051
22042
  server.httpServer.off("error", reject);
@@ -22053,7 +22044,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
22053
22044
  if (addr && typeof addr === "object") {
22054
22045
  server.port = addr.port;
22055
22046
  }
22056
- resolve9();
22047
+ resolve10();
22057
22048
  });
22058
22049
  });
22059
22050
  }
@@ -22194,7 +22185,7 @@ async function waitForNextUserMessage(opts) {
22194
22185
  }
22195
22186
  }
22196
22187
  function sleep3(ms) {
22197
- return new Promise((resolve9) => setTimeout(resolve9, ms));
22188
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
22198
22189
  }
22199
22190
  function currentBranch(cwd) {
22200
22191
  try {
@@ -23297,14 +23288,14 @@ function sendJson2(res, status, body) {
23297
23288
  res.end(JSON.stringify(body));
23298
23289
  }
23299
23290
  function readJsonBody2(req) {
23300
- return new Promise((resolve9, reject) => {
23291
+ return new Promise((resolve10, reject) => {
23301
23292
  const chunks = [];
23302
23293
  req.on("data", (c) => chunks.push(c));
23303
23294
  req.on("end", () => {
23304
23295
  const raw = Buffer.concat(chunks).toString("utf-8");
23305
- if (!raw.trim()) return resolve9({});
23296
+ if (!raw.trim()) return resolve10({});
23306
23297
  try {
23307
- resolve9(JSON.parse(raw));
23298
+ resolve10(JSON.parse(raw));
23308
23299
  } catch (err) {
23309
23300
  reject(err instanceof Error ? err : new Error(String(err)));
23310
23301
  }
@@ -23427,9 +23418,9 @@ async function poolServe() {
23427
23418
  const tick = setInterval(() => {
23428
23419
  registry.resyncAll().catch((err) => log(`resync tick failed: ${err instanceof Error ? err.message : String(err)}`));
23429
23420
  }, refillMs);
23430
- const dutyTickEnabled = (process.env.POOL_CAPABILITY_TICK ?? "1") !== "0";
23431
- const dutyTickMs = envInt2("POOL_CAPABILITY_TICK_MS", 15 * 6e4);
23432
- const dutyTick = dutyTickEnabled ? setInterval(() => {
23421
+ const capabilityTickEnabled = (process.env.POOL_CAPABILITY_TICK ?? "1") !== "0";
23422
+ const capabilityTickMs = envInt2("POOL_CAPABILITY_TICK_MS", 15 * 6e4);
23423
+ const capabilityTick = capabilityTickEnabled ? setInterval(() => {
23433
23424
  runCapabilityFallbackTick({
23434
23425
  isDegraded: () => gitHubActionsDegraded(),
23435
23426
  activeRepos: () => registry.activeRepos(),
@@ -23438,7 +23429,7 @@ async function poolServe() {
23438
23429
  }).catch(
23439
23430
  (err) => log(`capability fallback tick failed: ${err instanceof Error ? err.message : String(err)}`)
23440
23431
  );
23441
- }, dutyTickMs) : null;
23432
+ }, capabilityTickMs) : null;
23442
23433
  const server = createServer4(async (req, res) => {
23443
23434
  try {
23444
23435
  if (!req.method || !req.url) return sendJson2(res, 400, { error: "bad request" });
@@ -23486,16 +23477,16 @@ async function poolServe() {
23486
23477
  }
23487
23478
  });
23488
23479
  const apiHost = process.env.POOL_API_HOST ?? "::";
23489
- await new Promise((resolve9) => {
23480
+ await new Promise((resolve10) => {
23490
23481
  server.listen(apiPort, apiHost, () => {
23491
23482
  log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
23492
- resolve9();
23483
+ resolve10();
23493
23484
  });
23494
23485
  });
23495
23486
  const shutdown = (signal) => {
23496
23487
  log(`${signal} \u2014 shutting down`);
23497
23488
  clearInterval(tick);
23498
- if (dutyTick) clearInterval(dutyTick);
23489
+ if (capabilityTick) clearInterval(capabilityTick);
23499
23490
  server.close(() => process.exit(0));
23500
23491
  };
23501
23492
  process.once("SIGINT", () => shutdown("SIGINT"));
@@ -23528,17 +23519,17 @@ function authOk2(req, expected) {
23528
23519
  return false;
23529
23520
  }
23530
23521
  function readJsonBody3(req) {
23531
- return new Promise((resolve9, reject) => {
23522
+ return new Promise((resolve10, reject) => {
23532
23523
  const chunks = [];
23533
23524
  req.on("data", (c) => chunks.push(c));
23534
23525
  req.on("end", () => {
23535
23526
  const raw = Buffer.concat(chunks).toString("utf-8");
23536
23527
  if (!raw.trim()) {
23537
- resolve9({});
23528
+ resolve10({});
23538
23529
  return;
23539
23530
  }
23540
23531
  try {
23541
- resolve9(JSON.parse(raw));
23532
+ resolve10(JSON.parse(raw));
23542
23533
  } catch (err) {
23543
23534
  reject(err instanceof Error ? err : new Error(String(err)));
23544
23535
  }
@@ -23672,13 +23663,13 @@ async function defaultRunJob(job) {
23672
23663
  ...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
23673
23664
  ...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
23674
23665
  };
23675
- const run = (cmd, args, cwd) => new Promise((resolve9) => {
23666
+ const run = (cmd, args, cwd) => new Promise((resolve10) => {
23676
23667
  const child = spawn8(cmd, args, { stdio: "inherit", env: childEnv, cwd });
23677
- child.on("exit", (code) => resolve9(code ?? 0));
23668
+ child.on("exit", (code) => resolve10(code ?? 0));
23678
23669
  child.on("error", (err) => {
23679
23670
  process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
23680
23671
  `);
23681
- resolve9(1);
23672
+ resolve10(1);
23682
23673
  });
23683
23674
  });
23684
23675
  process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
@@ -23754,11 +23745,11 @@ async function runnerServe() {
23754
23745
  const port = Number(process.env.PORT ?? DEFAULT_PORT2);
23755
23746
  const server = buildServer2({ apiKey });
23756
23747
  const host = process.env.RUNNER_HOST ?? "::";
23757
- await new Promise((resolve9) => {
23748
+ await new Promise((resolve10) => {
23758
23749
  server.listen(port, host, () => {
23759
23750
  process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
23760
23751
  `);
23761
- resolve9();
23752
+ resolve10();
23762
23753
  });
23763
23754
  });
23764
23755
  const shutdown = (signal) => {
@@ -23827,14 +23818,14 @@ async function serve(opts) {
23827
23818
  `);
23828
23819
  const args = ["--dangerously-skip-permissions", "--model", model.model];
23829
23820
  const child = spawn9("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
23830
- const exitCode = await new Promise((resolve9) => {
23831
- child.on("exit", (code) => resolve9(code ?? 0));
23821
+ const exitCode = await new Promise((resolve10) => {
23822
+ child.on("exit", (code) => resolve10(code ?? 0));
23832
23823
  child.on("error", (err) => {
23833
23824
  process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
23834
23825
  `);
23835
23826
  process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
23836
23827
  `);
23837
- resolve9(1);
23828
+ resolve10(1);
23838
23829
  });
23839
23830
  });
23840
23831
  killProxy();
@@ -18,7 +18,7 @@ You are Kody's agent factory. Convert the operator request into review-ready Kod
18
18
 
19
19
  # Task
20
20
 
21
- Design the smallest Kody model structure that satisfies the request. You may create or assemble simple executables, capabilities, loops, goals, and agents.
21
+ Design the smallest Kody model structure that satisfies the request. You may create or assemble simple capability implementation profiles, capabilities, loops, goals, and agents.
22
22
 
23
23
  Use the current Kody vocabulary:
24
24
 
@@ -31,7 +31,7 @@ Use the current Kody vocabulary:
31
31
  Use current storage names when producing files:
32
32
 
33
33
  - capability: capability contract, public action ownership, kind, agent, cadence, and output contract
34
- - executable: capability implementation
34
+ - implementation profile: capability implementation stored under `capabilities/<slug>/`
35
35
 
36
36
  # Boundaries
37
37
 
@@ -40,7 +40,8 @@ Use current storage names when producing files:
40
40
  - Do not activate generated definitions yourself.
41
41
  - Do not create a consumer-repo PR.
42
42
  - The deterministic postflight will open a review PR in the configured state repo under the configured state path.
43
- - Put generated file paths relative to the configured state path, for example `executables/...`, `capabilities/...`, `agents/...`, `goals/...`, or `memory/...`.
43
+ - Put generated file paths relative to the configured state path, for example `capabilities/...`, `agents/...`, `goals/...`, or `memory/...`.
44
+ - Do not create `executables/...` paths. External executables are obsolete; implementation profiles live in capability folders.
44
45
  - Produce complete file contents. Do not describe patches.
45
46
  - Prefer a small bundle over a broad framework. Include assumptions in the summary.
46
47
 
@@ -59,7 +60,7 @@ PR_SUMMARY:
59
60
  "summary": "human explanation and assumptions",
60
61
  "files": [
61
62
  {
62
- "path": "executables/example/profile.json",
63
+ "path": "capabilities/example/profile.json",
63
64
  "content": "{\n \"name\": \"example\"\n}\n"
64
65
  }
65
66
  ]
@@ -56,6 +56,18 @@ export interface Profile {
56
56
  executable?: string
57
57
  implementations?: string[]
58
58
  executables?: string[]
59
+ /** Hide a capability implementation profile from public action discovery. */
60
+ internal?: boolean
61
+ /** Explicit public-action flag for capability profiles. */
62
+ public?: boolean
63
+ /** Public capability output class when the profile also serves as a capability contract. */
64
+ capabilityKind?: "observe" | "act" | "verify"
65
+ /** Optional dashboard-facing capability metadata. The executor does not act on these fields. */
66
+ slug?: string
67
+ title?: string
68
+ skills?: string[]
69
+ prompt?: string
70
+ chatTools?: string[]
59
71
  /**
60
72
  * Execution model — orthogonal to `role`.
61
73
  * `oneshot` (default): single invocation on demand.
@@ -160,7 +172,7 @@ export interface Profile {
160
172
  * preflight runs. composePrompt prefers these over a fresh disk read so the
161
173
  * template survives working-tree churn from runFlow's branch setup — on the CI
162
174
  * runner a branch checkout can drop the tracked-but-ignore-negated
163
- * `.kody/executables/<name>/` dir, and reading prompt.md afterwards fails with
175
+ * `.kody/capabilities/<name>/` dir, and reading prompt.md afterwards fails with
164
176
  * ENOENT even though profile.json (read here, earlier) loaded fine.
165
177
  */
166
178
  promptTemplates?: Record<string, string>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.289",
3
+ "version": "0.4.291",
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",