@kody-ade/kody-engine 0.4.333 → 0.4.334

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/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.333",
18
+ version: "0.4.334",
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",
@@ -18278,7 +18278,7 @@ function validateOneModel(rawModel, files, label, strictSingleModel, failures, e
18278
18278
  if (!docsUsed.includes(doc)) failures.push(`${label} docsUsed missing ${doc}`);
18279
18279
  }
18280
18280
  validateFilesForKind(kind, slug2, files, strictSingleModel, failures);
18281
- validateModelShape(kind, model, failures);
18281
+ validateModelShape(kind, model, files, slug2, failures);
18282
18282
  }
18283
18283
  }
18284
18284
  function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
@@ -18316,7 +18316,7 @@ function validateFilesForKind(kind, slug2, files, strictSingleModel, failures) {
18316
18316
  if (kind === "agentLoop") {
18317
18317
  if (!paths.some((filePath) => filePath.endsWith("/state.json")))
18318
18318
  failures.push("agentLoop must produce a state.json file");
18319
- if (strictSingleModel) rejectOtherRoots(paths, ["goals/", "loops/"], "agentLoop", failures);
18319
+ if (strictSingleModel) rejectOtherRoots(paths, ["goals/", "loops/", "capabilities/"], "agentLoop", failures);
18320
18320
  }
18321
18321
  if (kind === "workflow") {
18322
18322
  requirePath(paths, `capabilities/${slug2}/profile.json`, "workflow capability profile", failures);
@@ -18344,13 +18344,18 @@ function validateFactoryAssembly(models, failures) {
18344
18344
  const input = model;
18345
18345
  const kind = stringField6(input.kind);
18346
18346
  if (kind === "goal") {
18347
- for (const capability of stringArray5(input.capabilities)) {
18347
+ for (const capability of capabilityRefs(input)) {
18348
18348
  if (!available.has(`capability:${capability}`)) {
18349
18349
  failures.push(`goal ${stringField6(input.slug)} references missing capability ${capability}`);
18350
18350
  }
18351
18351
  }
18352
18352
  }
18353
18353
  if (kind === "workflow") {
18354
+ for (const capability of stringArray5(input.steps)) {
18355
+ if (!available.has(`capability:${capability}`)) {
18356
+ failures.push(`workflow ${stringField6(input.slug)} references missing capability ${capability}`);
18357
+ }
18358
+ }
18354
18359
  for (const step of arrayObjects(input.steps)) {
18355
18360
  const capability = stringField6(step.capability);
18356
18361
  if (capability && !available.has(`capability:${capability}`)) {
@@ -18359,22 +18364,29 @@ function validateFactoryAssembly(models, failures) {
18359
18364
  }
18360
18365
  }
18361
18366
  if (kind === "agentLoop") {
18362
- const wakeTarget = input.wakeTarget;
18363
- if (wakeTarget && typeof wakeTarget === "object" && !Array.isArray(wakeTarget)) {
18364
- const target = wakeTarget;
18365
- const type = stringField6(target.type);
18366
- const slug2 = stringField6(target.slug);
18367
- const modelKind = type === "loop" ? "agentLoop" : type;
18368
- if ((modelKind === "goal" || modelKind === "workflow" || modelKind === "capability") && !available.has(`${modelKind}:${slug2}`)) {
18369
- failures.push(`agentLoop ${stringField6(input.slug)} references missing ${type} ${slug2}`);
18367
+ const target = wakeTarget(input);
18368
+ if (target) {
18369
+ if (!available.has(`${target.kind}:${target.slug}`)) {
18370
+ failures.push(`agentLoop ${stringField6(input.slug)} references missing ${target.kind} ${target.slug}`);
18371
+ }
18372
+ } else {
18373
+ const targetSlug = stringField6(input.target);
18374
+ const targetExists = ["goal", "workflow", "capability"].some(
18375
+ (kindName) => available.has(`${kindName}:${targetSlug}`)
18376
+ );
18377
+ if (targetSlug && !targetExists) {
18378
+ failures.push(`agentLoop ${stringField6(input.slug)} references missing target ${targetSlug}`);
18370
18379
  }
18371
18380
  }
18372
18381
  }
18373
18382
  }
18374
18383
  }
18375
- function validateModelShape(kind, model, failures) {
18384
+ function validateModelShape(kind, model, files, slug2, failures) {
18376
18385
  if (kind === "agent") {
18377
- requireStringArrayIncludes(model.owns, "identity", "agent owns", failures);
18386
+ const agentFile = textFile(files, `agents/${slug2}.md`);
18387
+ if (!stringArray5(model.owns).includes("identity") && !containsWord(agentFile, "identity")) {
18388
+ failures.push("agent owns must include identity");
18389
+ }
18378
18390
  requireStringArrayIncludes(model.doesNotOwn, "tasks", "agent doesNotOwn", failures);
18379
18391
  }
18380
18392
  if (kind === "capability") {
@@ -18389,16 +18401,21 @@ function validateModelShape(kind, model, failures) {
18389
18401
  requireStringArrayIncludes(model.doesNotOwn, "goal progress", "capability doesNotOwn", failures);
18390
18402
  }
18391
18403
  if (kind === "goal") {
18392
- if (!stringField6(model.outcome)) failures.push("goal model must declare outcome");
18393
- if (!Array.isArray(model.evidence) || model.evidence.length === 0)
18404
+ const goalState = parseJsonContent(textFile(files, `goals/templates/${slug2}/state.json`));
18405
+ if (!stringField6(model.outcome) && !stringField6(goalState?.outcome))
18406
+ failures.push("goal model must declare outcome");
18407
+ if (evidenceRefs(model).length === 0 && evidenceRefs(goalState).length === 0) {
18394
18408
  failures.push("goal model evidence must be non-empty");
18395
- if (!Array.isArray(model.capabilities) || model.capabilities.length === 0) {
18409
+ }
18410
+ if (capabilityRefs(model).length === 0 && capabilityRefs(goalState).length === 0) {
18396
18411
  failures.push("goal model capabilities must be non-empty");
18397
18412
  }
18398
18413
  }
18399
18414
  if (kind === "agentLoop") {
18400
18415
  if (!stringField6(model.cadence)) failures.push("agentLoop model must declare cadence");
18401
- if (!model.wakeTarget || typeof model.wakeTarget !== "object" || Array.isArray(model.wakeTarget)) {
18416
+ const loopState = parseJsonContent(firstStateFile(files, slug2));
18417
+ const hasTarget = Boolean(wakeTarget(model)) || Boolean(stringField6(model.target)) || Boolean(wakeTarget(loopState)) || Boolean(stringField6(loopState?.target)) || Boolean(loopTargetString(loopState));
18418
+ if (!hasTarget) {
18402
18419
  failures.push("agentLoop model must declare wakeTarget object");
18403
18420
  }
18404
18421
  }
@@ -18406,6 +18423,48 @@ function validateModelShape(kind, model, failures) {
18406
18423
  if (!Array.isArray(model.steps) || model.steps.length === 0) failures.push("workflow model steps must be non-empty");
18407
18424
  }
18408
18425
  }
18426
+ function capabilityRefs(value) {
18427
+ return [...stringArray5(value?.capabilities), ...stringArray5(value?.allowedCapabilities)];
18428
+ }
18429
+ function evidenceRefs(value) {
18430
+ if (!value) return [];
18431
+ if (Array.isArray(value.evidence)) return value.evidence.map((item) => String(item).trim()).filter(Boolean);
18432
+ if (value.evidence && typeof value.evidence === "object") return Object.keys(value.evidence);
18433
+ return [];
18434
+ }
18435
+ function wakeTarget(value) {
18436
+ const raw = value?.wakeTarget;
18437
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
18438
+ const target = raw;
18439
+ const type = stringField6(target.type);
18440
+ const slug2 = stringField6(target.slug);
18441
+ if ((type === "goal" || type === "workflow" || type === "capability") && slug2) return { kind: type, slug: slug2 };
18442
+ return null;
18443
+ }
18444
+ function loopTargetString(value) {
18445
+ const loop = value?.loop;
18446
+ if (!loop || typeof loop !== "object" || Array.isArray(loop)) return "";
18447
+ return stringField6(loop.target);
18448
+ }
18449
+ function textFile(files, wantedPath) {
18450
+ return files.find((item) => normalizeBundlePath(item.path) === wantedPath)?.content ?? "";
18451
+ }
18452
+ function firstStateFile(files, slug2) {
18453
+ const normalizedSlug = `${slug2}/state.json`;
18454
+ return files.find((item) => normalizeBundlePath(item.path).endsWith(normalizedSlug))?.content ?? "";
18455
+ }
18456
+ function parseJsonContent(content) {
18457
+ if (!content.trim()) return null;
18458
+ try {
18459
+ const parsed = JSON.parse(content);
18460
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
18461
+ } catch {
18462
+ return null;
18463
+ }
18464
+ }
18465
+ function containsWord(content, word) {
18466
+ return new RegExp(`\\b${word}\\b`, "i").test(content);
18467
+ }
18409
18468
  function parseJsonFile(files, wantedPath, failures) {
18410
18469
  const file = files.find((item) => normalizeBundlePath(item.path) === wantedPath);
18411
18470
  if (!file) return null;
@@ -51,6 +51,14 @@ Use these exact model kinds and required file shapes:
51
51
  Do not use `kind: "loop"`; the loop model kind is `agentLoop`.
52
52
  Do not use `agents/<slug>/identity.json`, `goals/<slug>/goal.json`, `workflows/<slug>/workflow.json`, or `executables/<slug>/...`.
53
53
 
54
+ Each `models[]` entry must also carry the creator's canonical model metadata:
55
+
56
+ - Agent models include `"owns": ["identity", "judgment", "boundaries"]` and `doesNotOwn` includes `"tasks"`.
57
+ - Goal models include `"outcome"`, non-empty `"evidence"`, and non-empty `"capabilities"`. Use `"capabilities"`, not only `"allowedCapabilities"`, in `models[]`.
58
+ - Loop models use `"kind": "agentLoop"` and include `"wakeTarget": {"type": "goal|workflow|capability", "slug": "target-slug"}`. Use `"wakeTarget"`, not only `"target"`, in `models[]`.
59
+ - Workflow models include non-empty `"steps"` as objects with a `"capability"` slug.
60
+ - Capability models include `"capabilityKind"`, `"ability"`, `"inputs"`, `"outputs"`, `"allowedActions"`, `"forbiddenActions"`, and `doesNotOwn` includes `"agent identity"` and `"goal progress"`.
61
+
54
62
  Capability files must be shaped by ability, kind, interface, and constraints. Do not include fields or prose that make the capability depend on who asked for it, which workflow calls it, which goal consumes it, which loop wakes it, or which agent may run it.
55
63
 
56
64
  Use the current Kody vocabulary:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.333",
3
+ "version": "0.4.334",
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",