@kody-ade/kody-engine 0.4.315 → 0.4.316

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 +162 -175
  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.315",
18
+ version: "0.4.316",
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",
@@ -1909,6 +1909,7 @@ function parseCapabilityConfig(raw) {
1909
1909
  implementation: stringField(raw.implementation ?? raw.executable),
1910
1910
  executable: stringField(raw.executable),
1911
1911
  tickScript: stringField(raw.tickScript),
1912
+ capabilityKind: parseCapabilityKind(raw.capabilityKind),
1912
1913
  disabled: typeof raw.disabled === "boolean" ? raw.disabled : void 0,
1913
1914
  internal: typeof raw.internal === "boolean" ? raw.internal : void 0,
1914
1915
  public: typeof raw.public === "boolean" ? raw.public : void 0,
@@ -1927,6 +1928,9 @@ function parseCapabilityConfig(raw) {
1927
1928
  workflow: parseCapabilityWorkflow(raw.workflow)
1928
1929
  };
1929
1930
  }
1931
+ function parseCapabilityKind(raw) {
1932
+ return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
1933
+ }
1930
1934
  function parseCapabilityToolMode(raw) {
1931
1935
  if (raw === void 0 || raw === null || raw === "") return void 0;
1932
1936
  if (raw === "lock" || raw === "append") return raw;
@@ -2633,82 +2637,13 @@ function readCheckRuns(repoSlug, ref, ignoreNames) {
2633
2637
  const state = failing.length > 0 ? "RED" : pending.length > 0 ? "PENDING" : "GREEN";
2634
2638
  return { sha, state, failing, pending };
2635
2639
  }
2636
- function cleanLogins(values) {
2637
- return [
2638
- ...new Set(
2639
- (values ?? []).map((value) => value.trim().replace(/^@/, "")).filter(Boolean)
2640
- )
2641
- ];
2642
- }
2643
- function cleanLabels(values) {
2644
- return [
2645
- ...new Set(
2646
- (values ?? []).map((value) => value.trim()).filter(Boolean)
2647
- )
2648
- ];
2649
- }
2650
- function ensureKodyLabel(repoSlug, label) {
2651
- if (!label.toLowerCase().startsWith("kody:")) return;
2652
- gh([
2653
- "label",
2654
- "create",
2655
- label,
2656
- "-R",
2657
- repoSlug,
2658
- "--color",
2659
- "8b5cf6",
2660
- "--description",
2661
- "Kody-owned tracking issue",
2662
- "--force"
2663
- ]);
2664
- }
2665
- function applyIssueUpdates(repoSlug, number, opts) {
2666
- const labels = cleanLabels(opts?.labels);
2667
- const assignees = cleanLogins(opts?.assignees);
2668
- if (labels.length === 0 && assignees.length === 0) return null;
2669
- const labelsApplied = [];
2670
- const assigneesApplied = [];
2671
- const warnings = [];
2672
- for (const label of labels) {
2673
- try {
2674
- gh(["issue", "edit", String(number), "-R", repoSlug, "--add-label", label]);
2675
- labelsApplied.push(label);
2676
- } catch (firstErr) {
2677
- try {
2678
- ensureKodyLabel(repoSlug, label);
2679
- gh(["issue", "edit", String(number), "-R", repoSlug, "--add-label", label]);
2680
- labelsApplied.push(label);
2681
- } catch (err) {
2682
- warnings.push(
2683
- `label ${label}: ${err instanceof Error ? err.message : firstErr instanceof Error ? firstErr.message : String(err)}`
2684
- );
2685
- }
2686
- }
2687
- }
2688
- for (const assignee of assignees) {
2689
- try {
2690
- gh(["issue", "edit", String(number), "-R", repoSlug, "--add-assignee", assignee]);
2691
- assigneesApplied.push(assignee);
2692
- } catch (err) {
2693
- warnings.push(`assignee ${assignee}: ${err instanceof Error ? err.message : String(err)}`);
2694
- }
2695
- }
2696
- return {
2697
- ...labelsApplied.length > 0 ? { labelsApplied } : {},
2698
- ...assigneesApplied.length > 0 ? { assigneesApplied } : {},
2699
- ...warnings.length > 0 ? { warnings } : {}
2700
- };
2701
- }
2702
- function ensureIssue(repoSlug, key, title, body, opts) {
2640
+ function ensureIssue(repoSlug, key, title, body) {
2703
2641
  const marker = trackMarker(key);
2704
2642
  try {
2705
2643
  const raw = gh(["issue", "list", "-R", repoSlug, "--state", "open", "--limit", "100", "--json", "number,body"]);
2706
2644
  const issues = JSON.parse(raw);
2707
2645
  const existing = issues.find((i) => (i.body ?? "").includes(marker));
2708
- if (existing) {
2709
- const updates2 = applyIssueUpdates(repoSlug, existing.number, opts);
2710
- return updates2 ? { created: false, number: existing.number, ...updates2 } : { created: false, number: existing.number };
2711
- }
2646
+ if (existing) return { created: false, number: existing.number };
2712
2647
  const url = gh(["issue", "create", "-R", repoSlug, "--title", title, "--body-file", "-"], {
2713
2648
  input: `${body}
2714
2649
 
@@ -2716,9 +2651,7 @@ ${marker}`
2716
2651
  });
2717
2652
  const m = url.trim().match(/\/(\d+)\s*$/);
2718
2653
  if (!m) return { error: `issue created but could not parse its number from: ${url}` };
2719
- const number = Number(m[1]);
2720
- const updates = applyIssueUpdates(repoSlug, number, opts);
2721
- return updates ? { created: true, number, ...updates } : { created: true, number };
2654
+ return { created: true, number: Number(m[1]) };
2722
2655
  } catch (err) {
2723
2656
  return { error: err instanceof Error ? err.message : String(err) };
2724
2657
  }
@@ -2912,19 +2845,13 @@ function capabilityToolDefinitions(opts) {
2912
2845
  title: z3.string().min(1).describe("Issue title (used only on first creation)."),
2913
2846
  body: z3.string().min(1).describe(
2914
2847
  "Issue body markdown (used only on first creation). Include the operator mention verbatim if the capability body has one."
2915
- ),
2916
- labels: z3.array(z3.string().min(1)).optional().describe(
2917
- "Optional labels to apply to the tracking issue every time, including reused issues. Use for dashboard visibility, e.g. ['kody:backlog']."
2918
- ),
2919
- assignees: z3.array(z3.string().min(1)).optional().describe("Optional GitHub logins to assign to the tracking issue every time, including reused issues.")
2848
+ )
2920
2849
  },
2921
2850
  handler: async (args) => {
2922
2851
  const key = String(args.key ?? "");
2923
2852
  const title = String(args.title ?? "");
2924
2853
  const body = String(args.body ?? "");
2925
- const labels = Array.isArray(args.labels) ? args.labels.map((label) => String(label)) : void 0;
2926
- const assignees = Array.isArray(args.assignees) ? args.assignees.map((assignee) => String(assignee)) : void 0;
2927
- const result = ensureIssue(opts.repoSlug, key, title, body, { labels, assignees });
2854
+ const result = ensureIssue(opts.repoSlug, key, title, body);
2928
2855
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
2929
2856
  }
2930
2857
  };
@@ -3869,6 +3796,89 @@ var init_gha = __esm({
3869
3796
  }
3870
3797
  });
3871
3798
 
3799
+ // src/agencyBoundaryEval.ts
3800
+ function evaluateAgencyBoundaries(input) {
3801
+ const findings = [];
3802
+ const results = input.results ?? [];
3803
+ findings.push(evaluateObserveBoundary(input.capabilityKind, results));
3804
+ findings.push(evaluateVerifyBoundary(input.capabilityKind, results));
3805
+ findings.push(evaluateGoalOwnershipBoundary(results));
3806
+ return {
3807
+ version: 1,
3808
+ status: findings.some((finding) => finding.status === "fail") ? "fail" : "pass",
3809
+ ...input.capability ? { capability: input.capability } : {},
3810
+ ...input.capabilityKind ? { capabilityKind: input.capabilityKind } : {},
3811
+ findings
3812
+ };
3813
+ }
3814
+ function evaluateObserveBoundary(capabilityKind, results) {
3815
+ if (capabilityKind !== "observe") {
3816
+ return pass("observe-does-not-act", "capability is not observe", { capabilityKind });
3817
+ }
3818
+ const actionResults = results.filter(resultLooksLikeAction);
3819
+ if (actionResults.length === 0) {
3820
+ return pass("observe-does-not-act", "observe capability reported facts without action output", {
3821
+ resultCount: results.length
3822
+ });
3823
+ }
3824
+ return fail("observe-does-not-act", "observe capability returned action-shaped output", {
3825
+ resultCount: results.length,
3826
+ actionResults: actionResults.map(resultSummary)
3827
+ });
3828
+ }
3829
+ function evaluateVerifyBoundary(capabilityKind, results) {
3830
+ if (capabilityKind !== "verify") {
3831
+ return pass("verify-does-not-fix", "capability is not verify", { capabilityKind });
3832
+ }
3833
+ const actionResults = results.filter(resultLooksLikeAction);
3834
+ if (actionResults.length === 0) {
3835
+ return pass("verify-does-not-fix", "verify capability returned verdict evidence without action output", {
3836
+ resultCount: results.length
3837
+ });
3838
+ }
3839
+ return fail("verify-does-not-fix", "verify capability returned fix/change output", {
3840
+ resultCount: results.length,
3841
+ actionResults: actionResults.map(resultSummary)
3842
+ });
3843
+ }
3844
+ function evaluateGoalOwnershipBoundary(results) {
3845
+ const targetBearing = results.filter((result) => result.target?.type === "goal");
3846
+ if (targetBearing.length === 0) {
3847
+ return pass("capability-does-not-own-goal-progress", "capability output is parent-neutral", {
3848
+ resultCount: results.length
3849
+ });
3850
+ }
3851
+ return fail("capability-does-not-own-goal-progress", "capability output names a goal target", {
3852
+ resultCount: results.length,
3853
+ targetBearingResults: targetBearing.map(resultSummary)
3854
+ });
3855
+ }
3856
+ function resultLooksLikeAction(result) {
3857
+ if (result.status === "changed") return true;
3858
+ return Object.keys(result.facts).some((key) => ACTION_FACT_KEYS.has(key));
3859
+ }
3860
+ function resultSummary(result) {
3861
+ return {
3862
+ status: result.status,
3863
+ summary: result.summary,
3864
+ target: result.target,
3865
+ actionFactKeys: Object.keys(result.facts).filter((key) => ACTION_FACT_KEYS.has(key))
3866
+ };
3867
+ }
3868
+ function pass(rule, message, evidence) {
3869
+ return { rule, status: "pass", message, evidence };
3870
+ }
3871
+ function fail(rule, message, evidence) {
3872
+ return { rule, status: "fail", message, evidence };
3873
+ }
3874
+ var ACTION_FACT_KEYS;
3875
+ var init_agencyBoundaryEval = __esm({
3876
+ "src/agencyBoundaryEval.ts"() {
3877
+ "use strict";
3878
+ ACTION_FACT_KEYS = /* @__PURE__ */ new Set(["changedResources", "createdResources", "actionResult"]);
3879
+ }
3880
+ });
3881
+
3872
3882
  // src/capabilityReport.ts
3873
3883
  function parseCapabilityReportsFromText(text) {
3874
3884
  const reports = [];
@@ -4388,7 +4398,7 @@ function loadProfile(profilePath) {
4388
4398
  executable: execRef,
4389
4399
  internal: typeof r.internal === "boolean" ? r.internal : base.internal,
4390
4400
  public: typeof r.public === "boolean" ? r.public : base.public,
4391
- capabilityKind: parseCapabilityKind(r.capabilityKind) ?? base.capabilityKind,
4401
+ capabilityKind: parseCapabilityKind2(r.capabilityKind) ?? base.capabilityKind,
4392
4402
  slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : base.slug,
4393
4403
  title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : base.title,
4394
4404
  skills: parseStringArray2(r.skills) ?? base.skills,
@@ -4442,7 +4452,7 @@ function loadProfile(profilePath) {
4442
4452
  executable: void 0,
4443
4453
  internal: typeof r.internal === "boolean" ? r.internal : void 0,
4444
4454
  public: typeof r.public === "boolean" ? r.public : void 0,
4445
- capabilityKind: parseCapabilityKind(r.capabilityKind),
4455
+ capabilityKind: parseCapabilityKind2(r.capabilityKind),
4446
4456
  slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : void 0,
4447
4457
  title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : void 0,
4448
4458
  skills: parseStringArray2(r.skills),
@@ -4549,7 +4559,7 @@ function parseStringArray2(raw) {
4549
4559
  const values = raw.map((t) => String(t).trim()).filter(Boolean);
4550
4560
  return values.length > 0 ? values : void 0;
4551
4561
  }
4552
- function parseCapabilityKind(raw) {
4562
+ function parseCapabilityKind2(raw) {
4553
4563
  return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
4554
4564
  }
4555
4565
  function parseInputs(p, raw) {
@@ -9965,10 +9975,10 @@ function refreshReportOrFail(ctx, goalId, state, evidenceItems) {
9965
9975
  evidenceItems
9966
9976
  });
9967
9977
  } catch (err) {
9968
- fail(ctx, err instanceof Error ? err.message : String(err));
9978
+ fail2(ctx, err instanceof Error ? err.message : String(err));
9969
9979
  }
9970
9980
  }
9971
- function fail(ctx, reason) {
9981
+ function fail2(ctx, reason) {
9972
9982
  ctx.output.reason = ctx.output.reason ? `${ctx.output.reason}; ${reason}` : reason;
9973
9983
  if (ctx.output.exitCode === 0) ctx.output.exitCode = 99;
9974
9984
  }
@@ -12408,90 +12418,20 @@ var init_ensurePr = __esm({
12408
12418
  }
12409
12419
  });
12410
12420
 
12411
- // src/agencyBoundaryEval.ts
12412
- function evaluateAgencyBoundaries(input) {
12413
- const findings = [];
12414
- const results = input.results ?? [];
12415
- findings.push(evaluateObserveBoundary(input.capabilityKind, results));
12416
- findings.push(evaluateVerifyBoundary(input.capabilityKind, results));
12417
- findings.push(evaluateGoalOwnershipBoundary(results));
12418
- return {
12419
- version: 1,
12420
- status: findings.some((finding) => finding.status === "fail") ? "fail" : "pass",
12421
- ...input.capability ? { capability: input.capability } : {},
12422
- ...input.capabilityKind ? { capabilityKind: input.capabilityKind } : {},
12423
- findings
12424
- };
12425
- }
12426
- function evaluateObserveBoundary(capabilityKind, results) {
12427
- if (capabilityKind !== "observe") {
12428
- return pass("observe-does-not-act", "capability is not observe", { capabilityKind });
12429
- }
12430
- const actionResults = results.filter(resultLooksLikeAction);
12431
- if (actionResults.length === 0) {
12432
- return pass("observe-does-not-act", "observe capability reported facts without action output", {
12433
- resultCount: results.length
12434
- });
12435
- }
12436
- return fail2("observe-does-not-act", "observe capability returned action-shaped output", {
12437
- resultCount: results.length,
12438
- actionResults: actionResults.map(resultSummary)
12439
- });
12440
- }
12441
- function evaluateVerifyBoundary(capabilityKind, results) {
12442
- if (capabilityKind !== "verify") {
12443
- return pass("verify-does-not-fix", "capability is not verify", { capabilityKind });
12444
- }
12445
- const actionResults = results.filter(resultLooksLikeAction);
12446
- if (actionResults.length === 0) {
12447
- return pass("verify-does-not-fix", "verify capability returned verdict evidence without action output", {
12448
- resultCount: results.length
12449
- });
12450
- }
12451
- return fail2("verify-does-not-fix", "verify capability returned fix/change output", {
12452
- resultCount: results.length,
12453
- actionResults: actionResults.map(resultSummary)
12454
- });
12455
- }
12456
- function evaluateGoalOwnershipBoundary(results) {
12457
- const targetBearing = results.filter((result) => result.target?.type === "goal");
12458
- if (targetBearing.length === 0) {
12459
- return pass("capability-does-not-own-goal-progress", "capability output is parent-neutral", {
12460
- resultCount: results.length
12461
- });
12462
- }
12463
- return fail2("capability-does-not-own-goal-progress", "capability output names a goal target", {
12464
- resultCount: results.length,
12465
- targetBearingResults: targetBearing.map(resultSummary)
12466
- });
12467
- }
12468
- function resultLooksLikeAction(result) {
12469
- if (result.status === "changed") return true;
12470
- return Object.keys(result.facts).some((key) => ACTION_FACT_KEYS.has(key));
12471
- }
12472
- function resultSummary(result) {
12473
- return {
12474
- status: result.status,
12475
- summary: result.summary,
12476
- target: result.target,
12477
- actionFactKeys: Object.keys(result.facts).filter((key) => ACTION_FACT_KEYS.has(key))
12478
- };
12421
+ // src/scripts/evaluateAgencyBoundaries.ts
12422
+ function shouldEvaluateAgencyBoundaries(data, profile) {
12423
+ return Boolean(agencyBoundaryCapabilityKind(data, profile));
12479
12424
  }
12480
- function pass(rule, message, evidence) {
12481
- return { rule, status: "pass", message, evidence };
12425
+ function agencyBoundaryCapability(data, profile) {
12426
+ if (typeof data.jobCapability === "string" && data.jobCapability.length > 0) return data.jobCapability;
12427
+ if (typeof data.capabilitySlug === "string" && data.capabilitySlug.length > 0) return data.capabilitySlug;
12428
+ return profile.name;
12482
12429
  }
12483
- function fail2(rule, message, evidence) {
12484
- return { rule, status: "fail", message, evidence };
12430
+ function agencyBoundaryCapabilityKind(data, profile) {
12431
+ const fromJob = data.jobCapabilityKind;
12432
+ if (fromJob === "observe" || fromJob === "act" || fromJob === "verify") return fromJob;
12433
+ return profile.capabilityKind;
12485
12434
  }
12486
- var ACTION_FACT_KEYS;
12487
- var init_agencyBoundaryEval = __esm({
12488
- "src/agencyBoundaryEval.ts"() {
12489
- "use strict";
12490
- ACTION_FACT_KEYS = /* @__PURE__ */ new Set(["changedResources", "createdResources", "actionResult"]);
12491
- }
12492
- });
12493
-
12494
- // src/scripts/evaluateAgencyBoundaries.ts
12495
12435
  function collectResults2(raw, agentResult) {
12496
12436
  const out = [];
12497
12437
  if (Array.isArray(raw)) {
@@ -12511,9 +12451,11 @@ var init_evaluateAgencyBoundaries = __esm({
12511
12451
  init_capabilityResult();
12512
12452
  evaluateAgencyBoundariesScript = async (ctx, profile, agentResult) => {
12513
12453
  const results = collectResults2(ctx.data.capabilityResults ?? ctx.data.dutyResults, agentResult);
12454
+ const capabilityKind = agencyBoundaryCapabilityKind(ctx.data, profile);
12455
+ const capability = agencyBoundaryCapability(ctx.data, profile);
12514
12456
  const evalResult = evaluateAgencyBoundaries({
12515
- capability: profile.name,
12516
- capabilityKind: profile.capabilityKind,
12457
+ capability,
12458
+ capabilityKind,
12517
12459
  results
12518
12460
  });
12519
12461
  ctx.data.agencyBoundaryEval = evalResult;
@@ -19016,7 +18958,7 @@ async function runExecutable(profileName, input) {
19016
18958
  }
19017
18959
  });
19018
18960
  }
19019
- for (const entry of profile.scripts.postflight) {
18961
+ for (const entry of postflightEntriesForRun(profile, ctx)) {
19020
18962
  const entryLabel = entry.script ?? entry.shell ?? "<unknown>";
19021
18963
  if (shouldBlockMutatingPostflight(entry.script, ctx.output.exitCode)) {
19022
18964
  if (entry.script === "commitAndPush" && ctx.data.commitResult === void 0) {
@@ -19144,6 +19086,30 @@ async function runExecutable(profileName, input) {
19144
19086
  }
19145
19087
  }
19146
19088
  }
19089
+ function postflightEntriesForRun(profile, ctx) {
19090
+ const entries = profile.scripts.postflight;
19091
+ if (!shouldEvaluateAgencyBoundaries(ctx.data, profile)) return entries;
19092
+ if (entries.some((entry) => entry.script === "evaluateAgencyBoundaries")) return entries;
19093
+ const evalEntry = { script: "evaluateAgencyBoundaries" };
19094
+ const afterParser = lastIndexOfScript(entries, /* @__PURE__ */ new Set(["parseAgentResult", "parseJobStateFromAgentResult"]));
19095
+ if (afterParser >= 0) {
19096
+ return [...entries.slice(0, afterParser + 1), evalEntry, ...entries.slice(afterParser + 1)];
19097
+ }
19098
+ const beforeStateChange = entries.findIndex(
19099
+ (entry) => isMutatingPostflight(entry.script) || entry.script === "writeJobStateFile" || entry.script === "saveTaskState"
19100
+ );
19101
+ if (beforeStateChange >= 0) {
19102
+ return [...entries.slice(0, beforeStateChange), evalEntry, ...entries.slice(beforeStateChange)];
19103
+ }
19104
+ return [...entries, evalEntry];
19105
+ }
19106
+ function lastIndexOfScript(entries, names) {
19107
+ for (let i = entries.length - 1; i >= 0; i--) {
19108
+ const entry = entries[i];
19109
+ if (entry?.script && names.has(entry.script)) return i;
19110
+ }
19111
+ return -1;
19112
+ }
19147
19113
  async function runExecutableChain(profileName, input) {
19148
19114
  let result = await runExecutable(profileName, input);
19149
19115
  let chainData = {
@@ -19528,6 +19494,7 @@ var init_executor = __esm({
19528
19494
  init_scripts();
19529
19495
  init_stateWorkspace();
19530
19496
  init_subagents();
19497
+ init_evaluateAgencyBoundaries();
19531
19498
  init_task_artifacts();
19532
19499
  init_tools();
19533
19500
  MUTATING_POSTFLIGHTS = /* @__PURE__ */ new Set([
@@ -19759,6 +19726,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
19759
19726
  if (capabilityContext) {
19760
19727
  preloadedData.capabilitySlug = capabilityContext.slug;
19761
19728
  preloadedData.capabilityTitle = capabilityContext.title;
19729
+ if (capabilityContext.config.capabilityKind) preloadedData.jobCapabilityKind = capabilityContext.config.capabilityKind;
19762
19730
  preloadedData.capabilityIntent = capabilityContext.body;
19763
19731
  preloadedData.dutyIntent = capabilityContext.body;
19764
19732
  preloadedData.jobIntent = capabilityContext.body;
@@ -19844,13 +19812,31 @@ async function runCapabilityWorkflow(parent, workflow, capability, base) {
19844
19812
  ...parsePrNumber5(prUrl) ? { workflowPrNumber: parsePrNumber5(prUrl) } : {}
19845
19813
  };
19846
19814
  if (result.exitCode !== 0 && !canContinueWorkflow(step, outcome)) {
19847
- return {
19815
+ return withWorkflowBoundaryEval(capability, {
19848
19816
  ...result,
19849
19817
  reason: result.reason ?? `workflow ${capability.slug} stopped at step ${index + 1}/${workflow.steps.length}: ${label}`
19850
- };
19818
+ });
19851
19819
  }
19852
19820
  }
19853
- return result;
19821
+ return withWorkflowBoundaryEval(capability, result);
19822
+ }
19823
+ function withWorkflowBoundaryEval(capability, result) {
19824
+ const capabilityKind = capability.config.capabilityKind;
19825
+ if (!capabilityKind) return result;
19826
+ const evalResult = evaluateAgencyBoundaries({
19827
+ capability: capability.slug,
19828
+ capabilityKind,
19829
+ results: []
19830
+ });
19831
+ process.stdout.write(`KODY_AGENCY_BOUNDARY_EVAL=${JSON.stringify(evalResult)}
19832
+ `);
19833
+ if (evalResult.status !== "fail" || result.exitCode !== 0) return result;
19834
+ const failed = evalResult.findings.filter((finding) => finding.status === "fail").map((finding) => finding.rule);
19835
+ return {
19836
+ ...result,
19837
+ exitCode: 99,
19838
+ reason: result.reason ? `${result.reason}; agency boundary eval failed: ${failed.join(", ")}` : `agency boundary eval failed: ${failed.join(", ")}`
19839
+ };
19854
19840
  }
19855
19841
  function workflowStepToJob(step, parent, chainData) {
19856
19842
  const action = step.action ?? step.capability;
@@ -19992,6 +19978,7 @@ var DEFAULT_INSTANT_AGENT, localJobSeq, InvalidJobError;
19992
19978
  var init_job = __esm({
19993
19979
  "src/job.ts"() {
19994
19980
  "use strict";
19981
+ init_agencyBoundaryEval();
19995
19982
  init_executor();
19996
19983
  init_registry();
19997
19984
  init_workflowDefinitions();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.315",
3
+ "version": "0.4.316",
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",