@kody-ade/kody-engine 0.4.314 → 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 +158 -94
  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.314",
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;
@@ -2154,7 +2158,7 @@ var init_companyStore = __esm({
2154
2158
  "src/companyStore.ts"() {
2155
2159
  "use strict";
2156
2160
  DEFAULT_COMPANY_STORE = "aharonyaircohen/kody-company-store";
2157
- DEFAULT_COMPANY_STORE_REF = "stable";
2161
+ DEFAULT_COMPANY_STORE_REF = "main";
2158
2162
  STORE_ENV = "KODY_COMPANY_STORE";
2159
2163
  REF_ENV = "KODY_COMPANY_STORE_REF";
2160
2164
  CACHE_ENV = "KODY_COMPANY_STORE_CACHE";
@@ -3792,6 +3796,89 @@ var init_gha = __esm({
3792
3796
  }
3793
3797
  });
3794
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
+
3795
3882
  // src/capabilityReport.ts
3796
3883
  function parseCapabilityReportsFromText(text) {
3797
3884
  const reports = [];
@@ -4311,7 +4398,7 @@ function loadProfile(profilePath) {
4311
4398
  executable: execRef,
4312
4399
  internal: typeof r.internal === "boolean" ? r.internal : base.internal,
4313
4400
  public: typeof r.public === "boolean" ? r.public : base.public,
4314
- capabilityKind: parseCapabilityKind(r.capabilityKind) ?? base.capabilityKind,
4401
+ capabilityKind: parseCapabilityKind2(r.capabilityKind) ?? base.capabilityKind,
4315
4402
  slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : base.slug,
4316
4403
  title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : base.title,
4317
4404
  skills: parseStringArray2(r.skills) ?? base.skills,
@@ -4365,7 +4452,7 @@ function loadProfile(profilePath) {
4365
4452
  executable: void 0,
4366
4453
  internal: typeof r.internal === "boolean" ? r.internal : void 0,
4367
4454
  public: typeof r.public === "boolean" ? r.public : void 0,
4368
- capabilityKind: parseCapabilityKind(r.capabilityKind),
4455
+ capabilityKind: parseCapabilityKind2(r.capabilityKind),
4369
4456
  slug: typeof r.slug === "string" && r.slug.trim() ? r.slug.trim() : void 0,
4370
4457
  title: typeof r.title === "string" && r.title.trim() ? r.title.trim() : void 0,
4371
4458
  skills: parseStringArray2(r.skills),
@@ -4472,7 +4559,7 @@ function parseStringArray2(raw) {
4472
4559
  const values = raw.map((t) => String(t).trim()).filter(Boolean);
4473
4560
  return values.length > 0 ? values : void 0;
4474
4561
  }
4475
- function parseCapabilityKind(raw) {
4562
+ function parseCapabilityKind2(raw) {
4476
4563
  return raw === "observe" || raw === "act" || raw === "verify" ? raw : void 0;
4477
4564
  }
4478
4565
  function parseInputs(p, raw) {
@@ -9888,10 +9975,10 @@ function refreshReportOrFail(ctx, goalId, state, evidenceItems) {
9888
9975
  evidenceItems
9889
9976
  });
9890
9977
  } catch (err) {
9891
- fail(ctx, err instanceof Error ? err.message : String(err));
9978
+ fail2(ctx, err instanceof Error ? err.message : String(err));
9892
9979
  }
9893
9980
  }
9894
- function fail(ctx, reason) {
9981
+ function fail2(ctx, reason) {
9895
9982
  ctx.output.reason = ctx.output.reason ? `${ctx.output.reason}; ${reason}` : reason;
9896
9983
  if (ctx.output.exitCode === 0) ctx.output.exitCode = 99;
9897
9984
  }
@@ -12331,90 +12418,20 @@ var init_ensurePr = __esm({
12331
12418
  }
12332
12419
  });
12333
12420
 
12334
- // src/agencyBoundaryEval.ts
12335
- function evaluateAgencyBoundaries(input) {
12336
- const findings = [];
12337
- const results = input.results ?? [];
12338
- findings.push(evaluateObserveBoundary(input.capabilityKind, results));
12339
- findings.push(evaluateVerifyBoundary(input.capabilityKind, results));
12340
- findings.push(evaluateGoalOwnershipBoundary(results));
12341
- return {
12342
- version: 1,
12343
- status: findings.some((finding) => finding.status === "fail") ? "fail" : "pass",
12344
- ...input.capability ? { capability: input.capability } : {},
12345
- ...input.capabilityKind ? { capabilityKind: input.capabilityKind } : {},
12346
- findings
12347
- };
12348
- }
12349
- function evaluateObserveBoundary(capabilityKind, results) {
12350
- if (capabilityKind !== "observe") {
12351
- return pass("observe-does-not-act", "capability is not observe", { capabilityKind });
12352
- }
12353
- const actionResults = results.filter(resultLooksLikeAction);
12354
- if (actionResults.length === 0) {
12355
- return pass("observe-does-not-act", "observe capability reported facts without action output", {
12356
- resultCount: results.length
12357
- });
12358
- }
12359
- return fail2("observe-does-not-act", "observe capability returned action-shaped output", {
12360
- resultCount: results.length,
12361
- actionResults: actionResults.map(resultSummary)
12362
- });
12363
- }
12364
- function evaluateVerifyBoundary(capabilityKind, results) {
12365
- if (capabilityKind !== "verify") {
12366
- return pass("verify-does-not-fix", "capability is not verify", { capabilityKind });
12367
- }
12368
- const actionResults = results.filter(resultLooksLikeAction);
12369
- if (actionResults.length === 0) {
12370
- return pass("verify-does-not-fix", "verify capability returned verdict evidence without action output", {
12371
- resultCount: results.length
12372
- });
12373
- }
12374
- return fail2("verify-does-not-fix", "verify capability returned fix/change output", {
12375
- resultCount: results.length,
12376
- actionResults: actionResults.map(resultSummary)
12377
- });
12378
- }
12379
- function evaluateGoalOwnershipBoundary(results) {
12380
- const targetBearing = results.filter((result) => result.target?.type === "goal");
12381
- if (targetBearing.length === 0) {
12382
- return pass("capability-does-not-own-goal-progress", "capability output is parent-neutral", {
12383
- resultCount: results.length
12384
- });
12385
- }
12386
- return fail2("capability-does-not-own-goal-progress", "capability output names a goal target", {
12387
- resultCount: results.length,
12388
- targetBearingResults: targetBearing.map(resultSummary)
12389
- });
12390
- }
12391
- function resultLooksLikeAction(result) {
12392
- if (result.status === "changed") return true;
12393
- return Object.keys(result.facts).some((key) => ACTION_FACT_KEYS.has(key));
12394
- }
12395
- function resultSummary(result) {
12396
- return {
12397
- status: result.status,
12398
- summary: result.summary,
12399
- target: result.target,
12400
- actionFactKeys: Object.keys(result.facts).filter((key) => ACTION_FACT_KEYS.has(key))
12401
- };
12421
+ // src/scripts/evaluateAgencyBoundaries.ts
12422
+ function shouldEvaluateAgencyBoundaries(data, profile) {
12423
+ return Boolean(agencyBoundaryCapabilityKind(data, profile));
12402
12424
  }
12403
- function pass(rule, message, evidence) {
12404
- 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;
12405
12429
  }
12406
- function fail2(rule, message, evidence) {
12407
- 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;
12408
12434
  }
12409
- var ACTION_FACT_KEYS;
12410
- var init_agencyBoundaryEval = __esm({
12411
- "src/agencyBoundaryEval.ts"() {
12412
- "use strict";
12413
- ACTION_FACT_KEYS = /* @__PURE__ */ new Set(["changedResources", "createdResources", "actionResult"]);
12414
- }
12415
- });
12416
-
12417
- // src/scripts/evaluateAgencyBoundaries.ts
12418
12435
  function collectResults2(raw, agentResult) {
12419
12436
  const out = [];
12420
12437
  if (Array.isArray(raw)) {
@@ -12434,9 +12451,11 @@ var init_evaluateAgencyBoundaries = __esm({
12434
12451
  init_capabilityResult();
12435
12452
  evaluateAgencyBoundariesScript = async (ctx, profile, agentResult) => {
12436
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);
12437
12456
  const evalResult = evaluateAgencyBoundaries({
12438
- capability: profile.name,
12439
- capabilityKind: profile.capabilityKind,
12457
+ capability,
12458
+ capabilityKind,
12440
12459
  results
12441
12460
  });
12442
12461
  ctx.data.agencyBoundaryEval = evalResult;
@@ -18939,7 +18958,7 @@ async function runExecutable(profileName, input) {
18939
18958
  }
18940
18959
  });
18941
18960
  }
18942
- for (const entry of profile.scripts.postflight) {
18961
+ for (const entry of postflightEntriesForRun(profile, ctx)) {
18943
18962
  const entryLabel = entry.script ?? entry.shell ?? "<unknown>";
18944
18963
  if (shouldBlockMutatingPostflight(entry.script, ctx.output.exitCode)) {
18945
18964
  if (entry.script === "commitAndPush" && ctx.data.commitResult === void 0) {
@@ -19067,6 +19086,30 @@ async function runExecutable(profileName, input) {
19067
19086
  }
19068
19087
  }
19069
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
+ }
19070
19113
  async function runExecutableChain(profileName, input) {
19071
19114
  let result = await runExecutable(profileName, input);
19072
19115
  let chainData = {
@@ -19451,6 +19494,7 @@ var init_executor = __esm({
19451
19494
  init_scripts();
19452
19495
  init_stateWorkspace();
19453
19496
  init_subagents();
19497
+ init_evaluateAgencyBoundaries();
19454
19498
  init_task_artifacts();
19455
19499
  init_tools();
19456
19500
  MUTATING_POSTFLIGHTS = /* @__PURE__ */ new Set([
@@ -19682,6 +19726,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
19682
19726
  if (capabilityContext) {
19683
19727
  preloadedData.capabilitySlug = capabilityContext.slug;
19684
19728
  preloadedData.capabilityTitle = capabilityContext.title;
19729
+ if (capabilityContext.config.capabilityKind) preloadedData.jobCapabilityKind = capabilityContext.config.capabilityKind;
19685
19730
  preloadedData.capabilityIntent = capabilityContext.body;
19686
19731
  preloadedData.dutyIntent = capabilityContext.body;
19687
19732
  preloadedData.jobIntent = capabilityContext.body;
@@ -19767,13 +19812,31 @@ async function runCapabilityWorkflow(parent, workflow, capability, base) {
19767
19812
  ...parsePrNumber5(prUrl) ? { workflowPrNumber: parsePrNumber5(prUrl) } : {}
19768
19813
  };
19769
19814
  if (result.exitCode !== 0 && !canContinueWorkflow(step, outcome)) {
19770
- return {
19815
+ return withWorkflowBoundaryEval(capability, {
19771
19816
  ...result,
19772
19817
  reason: result.reason ?? `workflow ${capability.slug} stopped at step ${index + 1}/${workflow.steps.length}: ${label}`
19773
- };
19818
+ });
19774
19819
  }
19775
19820
  }
19776
- 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
+ };
19777
19840
  }
19778
19841
  function workflowStepToJob(step, parent, chainData) {
19779
19842
  const action = step.action ?? step.capability;
@@ -19915,6 +19978,7 @@ var DEFAULT_INSTANT_AGENT, localJobSeq, InvalidJobError;
19915
19978
  var init_job = __esm({
19916
19979
  "src/job.ts"() {
19917
19980
  "use strict";
19981
+ init_agencyBoundaryEval();
19918
19982
  init_executor();
19919
19983
  init_registry();
19920
19984
  init_workflowDefinitions();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.314",
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",