@kody-ade/kody-engine 0.4.414 → 0.4.415

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 +281 -65
  2. package/package.json +2 -2
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.414",
18
+ version: "0.4.415",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -50,9 +50,9 @@ var init_package = __esm({
50
50
  prepublishOnly: "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
51
51
  },
52
52
  dependencies: {
53
- "@kody-ade/agency-domain": "0.1.1",
54
53
  "@actions/cache": "^6.0.0",
55
54
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
55
+ "@kody-ade/agency-domain": "0.4.0",
56
56
  "@modelcontextprotocol/sdk": "^1.29.0",
57
57
  convex: "^1.17.0",
58
58
  zod: "^4.0.0"
@@ -1990,14 +1990,14 @@ function resolveImplementationCandidates(name, roots = getImplementationRoots())
1990
1990
  function listCapabilityActions(projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
1991
1991
  const seen = /* @__PURE__ */ new Set();
1992
1992
  const out = [];
1993
- const add = (action) => {
1993
+ const add2 = (action) => {
1994
1994
  if (!isSafeName(action.action) || !isSafeName(action.capability) || !isSafeName(action.implementation)) return;
1995
1995
  if (seen.has(action.action)) return;
1996
1996
  seen.add(action.action);
1997
1997
  out.push(action);
1998
1998
  };
1999
- for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder")) add(action);
2000
- for (const action of listBuiltinCapabilityActions(getBuiltinCapabilitiesRoot())) add(action);
1999
+ for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder")) add2(action);
2000
+ for (const action of listBuiltinCapabilityActions(getBuiltinCapabilitiesRoot())) add2(action);
2001
2001
  return out.sort((a, b) => a.action.localeCompare(b.action));
2002
2002
  }
2003
2003
  function resolveCapabilityAction(action, projectCapabilitiesRoot = getProjectCapabilitiesRoot()) {
@@ -2505,6 +2505,22 @@ function createStateBackendFromEnv(env = process.env, client) {
2505
2505
  ...runId ? { runId: requireNonEmpty(runId, "runId") } : {}
2506
2506
  });
2507
2507
  },
2508
+ async createAgencyModelRun(tenantId2, subjectType, subjectId, run, now) {
2509
+ await transport.mutation(anyApi.agencyModel.createRunRecord, {
2510
+ tenantId: requireTenant(tenantId2),
2511
+ subjectType,
2512
+ subjectId: requireNonEmpty(subjectId, "subjectId"),
2513
+ run,
2514
+ now
2515
+ });
2516
+ },
2517
+ async finishAgencyModelRun(tenantId2, run, now) {
2518
+ await transport.mutation(anyApi.agencyModel.finishRunRecord, {
2519
+ tenantId: requireTenant(tenantId2),
2520
+ run,
2521
+ now
2522
+ });
2523
+ },
2508
2524
  async appendRunEvent(tenantId2, runId, goalId, event, time) {
2509
2525
  await transport.mutation(anyApi.runEvents.append, {
2510
2526
  tenantId: requireTenant(tenantId2),
@@ -12969,6 +12985,7 @@ var init_dispatchClassified = __esm({
12969
12985
 
12970
12986
  // src/goal/agencyModelRepository.ts
12971
12987
  import {
12988
+ createAgentDefinition,
12972
12989
  createCapabilityDefinition,
12973
12990
  createGoalDefinition,
12974
12991
  createGoalState,
@@ -12977,7 +12994,8 @@ import {
12977
12994
  createLoopState,
12978
12995
  createOperationDefinition,
12979
12996
  createRunOutput,
12980
- createWorkflowDefinition
12997
+ createWorkflowDefinition,
12998
+ relationshipIssues
12981
12999
  } from "@kody-ade/agency-domain";
12982
13000
  function goalProgressFromOutputs(definition, outputs) {
12983
13001
  const required2 = definition.objective.requiredEvidence;
@@ -12987,28 +13005,65 @@ function goalProgressFromOutputs(definition, outputs) {
12987
13005
  );
12988
13006
  return required2.filter((key) => satisfied.has(key)).length / required2.length;
12989
13007
  }
12990
- function validateAllDefinitions(documents) {
12991
- for (const document of documents) {
12992
- if (document.schemaVersion !== 1) throw new Error(`Unsupported Agency Definition schema: ${document.schemaVersion}`);
12993
- if (document.kind === "intent") createIntentDefinition(document.data);
12994
- else if (document.kind === "operation") createOperationDefinition(document.data);
12995
- else if (document.kind === "goal") createGoalDefinition(document.data);
12996
- else if (document.kind === "loop") createLoopDefinition(document.data);
12997
- else if (document.kind === "workflow") createWorkflowDefinition(document.data);
12998
- else createCapabilityDefinition(document.data);
12999
- }
13000
- }
13001
- function parseManagedDefinition(document) {
13002
- return document.kind === "goal" ? createGoalDefinition(document.data) : createLoopDefinition(document.data);
13003
- }
13004
- function parseState(document, definition) {
13008
+ function parseState(document, definition, kind) {
13005
13009
  if (!document) return null;
13006
13010
  if (document.schemaVersion !== 1) throw new Error(`Unsupported Agency State schema: ${document.schemaVersion}`);
13007
- if (document.kind !== definition.kind || document.definitionId !== definition.recordId) {
13008
- throw new Error(`Agency State does not match Definition: ${definition.recordId}`);
13011
+ if (document.kind !== kind || document.definitionId !== definition.id) {
13012
+ throw new Error(`Agency State does not match Definition: ${definition.id}`);
13009
13013
  }
13010
13014
  return document.kind === "goal" ? createGoalState(document.data) : createLoopState(document.data);
13011
13015
  }
13016
+ function emptyCatalog() {
13017
+ return {
13018
+ intents: /* @__PURE__ */ new Map(),
13019
+ operations: /* @__PURE__ */ new Map(),
13020
+ goals: /* @__PURE__ */ new Map(),
13021
+ loops: /* @__PURE__ */ new Map(),
13022
+ workflows: /* @__PURE__ */ new Map(),
13023
+ capabilities: /* @__PURE__ */ new Map(),
13024
+ agents: /* @__PURE__ */ new Map()
13025
+ };
13026
+ }
13027
+ function addDefinition(catalog, document) {
13028
+ if (document.schemaVersion !== 1) throw new Error(`Unsupported Agency Definition schema: ${document.schemaVersion}`);
13029
+ if (document.kind === "intent") add(catalog.intents, createIntentDefinition(document.data), document.recordId);
13030
+ else if (document.kind === "operation") add(catalog.operations, createOperationDefinition(document.data), document.recordId);
13031
+ else if (document.kind === "goal") add(catalog.goals, createGoalDefinition(document.data), document.recordId);
13032
+ else if (document.kind === "loop") add(catalog.loops, createLoopDefinition(document.data), document.recordId);
13033
+ else if (document.kind === "workflow") add(catalog.workflows, createWorkflowDefinition(document.data), document.recordId);
13034
+ else if (document.kind === "capability") add(catalog.capabilities, createCapabilityDefinition(document.data), document.recordId);
13035
+ else add(catalog.agents, createAgentDefinition(document.data), document.recordId);
13036
+ }
13037
+ function add(collection, definition, revision) {
13038
+ const mutable = collection;
13039
+ if (mutable.has(definition.id)) throw new Error(`Duplicate Agency Definition: ${definition.id}`);
13040
+ mutable.set(definition.id, { definition, revision });
13041
+ }
13042
+ function validateRelationships(catalog) {
13043
+ const relationshipCatalog = {
13044
+ operations: [...catalog.operations.keys()],
13045
+ goals: [...catalog.goals.keys()],
13046
+ workflows: [...catalog.workflows.keys()],
13047
+ capabilities: [...catalog.capabilities.keys()]
13048
+ };
13049
+ const issues = [...catalog.goals.values(), ...catalog.loops.values()].flatMap(
13050
+ ({ definition }) => relationshipIssues(definition, relationshipCatalog).map((issue2) => `${definition.id}: ${issue2}`)
13051
+ );
13052
+ for (const { definition } of catalog.operations.values()) {
13053
+ for (const intentId of definition.intentIds) {
13054
+ if (!catalog.intents.has(intentId)) issues.push(`${definition.id}: Missing Intent "${intentId}"`);
13055
+ }
13056
+ }
13057
+ for (const { definition } of catalog.workflows.values()) {
13058
+ for (const step of definition.steps) {
13059
+ if (!catalog.capabilities.has(step.capabilityRef.id)) {
13060
+ issues.push(`${definition.id}: Missing Capability "${step.capabilityRef.id}"`);
13061
+ }
13062
+ }
13063
+ }
13064
+ if (issues.length > 0) throw new Error(`Invalid Agency relationships:
13065
+ ${issues.join("\n")}`);
13066
+ }
13012
13067
  var AgencyModelRepository;
13013
13068
  var init_agencyModelRepository = __esm({
13014
13069
  "src/goal/agencyModelRepository.ts"() {
@@ -13020,19 +13075,31 @@ var init_agencyModelRepository = __esm({
13020
13075
  }
13021
13076
  backend;
13022
13077
  tenantId;
13023
- async listManagedWork() {
13024
- const documents = await this.backend.listAgencyDefinitions(this.tenantId);
13025
- validateAllDefinitions(documents);
13026
- const managed = documents.filter(
13027
- (document) => document.kind === "goal" || document.kind === "loop"
13028
- );
13078
+ async listManagedWork(catalog) {
13079
+ const definitions = catalog ?? await this.loadCatalog();
13080
+ const managed = [
13081
+ ...Array.from(definitions.goals.values(), ({ definition, revision }) => ({ definition, revision, kind: "goal" })),
13082
+ ...Array.from(definitions.loops.values(), ({ definition, revision }) => ({ definition, revision, kind: "loop" }))
13083
+ ];
13029
13084
  return Promise.all(
13030
- managed.map(async (document) => ({
13031
- definition: parseManagedDefinition(document),
13032
- state: parseState(await this.backend.getAgencyState(this.tenantId, document.recordId), document)
13085
+ managed.map(async (record2) => ({
13086
+ definition: record2.definition,
13087
+ revision: record2.revision,
13088
+ state: parseState(
13089
+ await this.backend.getAgencyState(this.tenantId, record2.definition.id),
13090
+ record2.definition,
13091
+ record2.kind
13092
+ )
13033
13093
  }))
13034
13094
  );
13035
13095
  }
13096
+ async loadCatalog() {
13097
+ const documents = await this.backend.listAgencyDefinitions(this.tenantId);
13098
+ const catalog = emptyCatalog();
13099
+ for (const document of documents) addDefinition(catalog, document);
13100
+ validateRelationships(catalog);
13101
+ return catalog;
13102
+ }
13036
13103
  async saveState(state, kind, updatedAt) {
13037
13104
  const data = kind === "goal" ? createGoalState(state) : createLoopState(state);
13038
13105
  await this.backend.putAgencyState(this.tenantId, state.definitionId, kind, 1, data, updatedAt);
@@ -13117,18 +13184,105 @@ var init_triggerDispatcher = __esm({
13117
13184
  }
13118
13185
  });
13119
13186
 
13187
+ // src/goal/policyResolver.ts
13188
+ import { createHash as createHash2 } from "crypto";
13189
+ function resolveDispatchPolicy(input) {
13190
+ const operation = input.catalog.operations.get(input.owner.definition.operationId);
13191
+ if (!operation) throw new Error(`Dispatch blocked: Operation "${input.owner.definition.operationId}" is unresolved`);
13192
+ if (operation.definition.intentIds.length === 0) {
13193
+ throw new Error(`Dispatch blocked: Operation "${operation.definition.id}" has no Intent`);
13194
+ }
13195
+ const intents = operation.definition.intentIds.map((intentId) => {
13196
+ const intent = input.catalog.intents.get(intentId);
13197
+ if (!intent) throw new Error(`Dispatch blocked: Intent "${intentId}" is unresolved`);
13198
+ return intent;
13199
+ });
13200
+ const policy = mergePolicies(intents.map(({ definition }) => definition.policy));
13201
+ const constraints = intents.flatMap(({ definition }) => definition.constraints);
13202
+ assertAuthorized(policy, constraints, input.target, input.approved === true);
13203
+ const snapshotValue = { policy, constraints };
13204
+ return {
13205
+ snapshot: {
13206
+ hash: createHash2("sha256").update(stableJson(snapshotValue)).digest("hex"),
13207
+ ...snapshotValue
13208
+ },
13209
+ operation,
13210
+ intents,
13211
+ trace: [
13212
+ pinned("trigger" in input.owner.definition ? "loop" : "goal", input.owner),
13213
+ input.target
13214
+ ]
13215
+ };
13216
+ }
13217
+ function mergePolicies(policies) {
13218
+ const approvalOrder = ["none", "risky-actions", "all-actions"];
13219
+ return {
13220
+ approval: policies.reduce(
13221
+ (strictest, policy) => approvalOrder.indexOf(policy.approval) > approvalOrder.indexOf(strictest) ? policy.approval : strictest,
13222
+ "none"
13223
+ ),
13224
+ authority: {
13225
+ allow: intersect(policies.map(({ authority }) => authority.allow)),
13226
+ deny: unique(policies.flatMap(({ authority }) => authority.deny))
13227
+ },
13228
+ budget: {
13229
+ maxRuns: Math.min(...policies.map(({ budget }) => budget.maxRuns)),
13230
+ maxTokens: Math.min(...policies.map(({ budget }) => budget.maxTokens)),
13231
+ maxCostUsd: Math.min(...policies.map(({ budget }) => budget.maxCostUsd)),
13232
+ maxDurationSeconds: Math.min(...policies.map(({ budget }) => budget.maxDurationSeconds))
13233
+ },
13234
+ maxConcurrentRuns: Math.min(...policies.map(({ maxConcurrentRuns }) => maxConcurrentRuns)),
13235
+ riskyActions: unique(policies.flatMap(({ riskyActions }) => riskyActions))
13236
+ };
13237
+ }
13238
+ function assertAuthorized(policy, constraints, target, approved) {
13239
+ const action = `${target.kind}:${target.id}`;
13240
+ const matches = (patterns) => patterns.some((pattern) => pattern === "*" || pattern === target.id || pattern === action);
13241
+ if (matches(policy.authority.deny)) throw new Error(`Dispatch blocked: authority denies "${action}"`);
13242
+ if (!matches(policy.authority.allow)) throw new Error(`Dispatch blocked: authority does not allow "${action}"`);
13243
+ const matchingConstraints = constraints.filter(({ actions }) => matches(actions));
13244
+ const denied = matchingConstraints.find(({ effect }) => effect === "deny");
13245
+ if (denied) throw new Error(`Dispatch blocked by constraint "${denied.id}": ${denied.rule}`);
13246
+ const requiresApproval = policy.approval === "all-actions" || policy.approval === "risky-actions" && matches(policy.riskyActions) || matchingConstraints.some(({ effect }) => effect === "require-approval");
13247
+ if (requiresApproval && !approved) throw new Error(`Dispatch blocked: approval is required for "${action}"`);
13248
+ }
13249
+ function pinned(kind, record2) {
13250
+ return { kind, id: record2.definition.id, revision: record2.revision };
13251
+ }
13252
+ function intersect(groups) {
13253
+ if (groups.length === 0) return [];
13254
+ if (groups.every((group) => group.includes("*"))) return ["*"];
13255
+ const candidates = unique(groups.flatMap((group) => group.filter((item) => item !== "*")));
13256
+ return candidates.filter((candidate) => groups.every((group) => group.includes("*") || group.includes(candidate)));
13257
+ }
13258
+ function unique(values) {
13259
+ return [...new Set(values)].sort();
13260
+ }
13261
+ function stableJson(value) {
13262
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
13263
+ if (value && typeof value === "object") {
13264
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
13265
+ }
13266
+ return JSON.stringify(value);
13267
+ }
13268
+ var init_policyResolver = __esm({
13269
+ "src/goal/policyResolver.ts"() {
13270
+ "use strict";
13271
+ }
13272
+ });
13273
+
13120
13274
  // src/scripts/dispatchAgencyLoops.ts
13121
- import { createLoopState as createLoopState2 } from "@kody-ade/agency-domain";
13275
+ import { randomUUID } from "crypto";
13276
+ import {
13277
+ createLoopState as createLoopState2,
13278
+ createRun
13279
+ } from "@kody-ade/agency-domain";
13122
13280
  async function dispatchAgencyLoopsWith(input) {
13123
13281
  const repository = new AgencyModelRepository(input.backend, input.tenantId);
13124
- const records = await repository.listManagedWork();
13125
- const goals = new Map(
13126
- records.filter(
13127
- (record2) => "executionRef" in record2.definition
13128
- ).map((record2) => [record2.definition.id, record2.definition])
13129
- );
13130
- const loops = records.filter(
13131
- (record2) => "trigger" in record2.definition
13282
+ const catalog = await repository.loadCatalog();
13283
+ const records = await repository.listManagedWork(catalog);
13284
+ const loops = records.flatMap(
13285
+ (record2) => "trigger" in record2.definition ? [{ ...record2, definition: record2.definition, state: record2.state }] : []
13132
13286
  );
13133
13287
  const results = [];
13134
13288
  for (const record2 of loops) {
@@ -13147,6 +13301,27 @@ async function dispatchAgencyLoopsWith(input) {
13147
13301
  results.push({ loopId: record2.definition.id, decision: "skipped", reason: decision.reason });
13148
13302
  continue;
13149
13303
  }
13304
+ let target;
13305
+ let policy;
13306
+ try {
13307
+ target = resolveTarget(record2.definition, catalog);
13308
+ policy = resolveDispatchPolicy({
13309
+ catalog,
13310
+ owner: { definition: record2.definition, revision: record2.revision },
13311
+ target: target.reference
13312
+ });
13313
+ } catch (error) {
13314
+ const reason = error instanceof Error ? error.message : String(error);
13315
+ await input.backend.recordSkippedAgencyDispatch(
13316
+ input.tenantId,
13317
+ decision.idempotencyKey,
13318
+ record2.definition.id,
13319
+ { kind: "skip", reason, scheduledAt: decision.scheduledAt },
13320
+ now
13321
+ );
13322
+ results.push({ loopId: record2.definition.id, decision: "skipped", reason });
13323
+ continue;
13324
+ }
13150
13325
  const leaseUntil = new Date(input.now.getTime() + 15 * 6e4).toISOString();
13151
13326
  const reservation = await input.backend.reserveAgencyDispatch(
13152
13327
  input.tenantId,
@@ -13169,14 +13344,40 @@ async function dispatchAgencyLoopsWith(input) {
13169
13344
  updatedAt: now
13170
13345
  });
13171
13346
  await repository.saveState(runningState, "loop", now);
13347
+ const runId = `run-${randomUUID()}`;
13348
+ const correlationId = `corr-${randomUUID()}`;
13349
+ const activeRun = createRun({
13350
+ id: runId,
13351
+ status: "running",
13352
+ origin: { kind: "loop", id: record2.definition.id, revision: record2.revision },
13353
+ target: target.reference,
13354
+ trace: [policy.trace[0], ...target.intermediate, target.reference],
13355
+ effectivePolicy: policy.snapshot,
13356
+ correlationId,
13357
+ startedAt: now
13358
+ });
13172
13359
  try {
13173
- const output = await input.run(jobForTarget(record2.definition, goals));
13360
+ await input.backend.createAgencyModelRun(
13361
+ input.tenantId,
13362
+ target.reference.kind,
13363
+ target.reference.id,
13364
+ activeRun,
13365
+ now
13366
+ );
13367
+ const output = await input.run(target.job);
13174
13368
  const succeeded = output.exitCode === 0;
13369
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
13370
+ await input.backend.finishAgencyModelRun(
13371
+ input.tenantId,
13372
+ terminalRun(activeRun, succeeded ? "succeeded" : "failed", finishedAt),
13373
+ finishedAt
13374
+ );
13175
13375
  await input.backend.finishAgencyDispatch(
13176
13376
  input.tenantId,
13177
13377
  decision.idempotencyKey,
13178
13378
  succeeded ? "dispatched" : "failed",
13179
- (/* @__PURE__ */ new Date()).toISOString()
13379
+ finishedAt,
13380
+ runId
13180
13381
  );
13181
13382
  await repository.saveState(
13182
13383
  createLoopState2({
@@ -13195,19 +13396,33 @@ async function dispatchAgencyLoopsWith(input) {
13195
13396
  });
13196
13397
  } catch (error) {
13197
13398
  const reason = error instanceof Error ? error.message : String(error);
13198
- await input.backend.finishAgencyDispatch(input.tenantId, decision.idempotencyKey, "failed", (/* @__PURE__ */ new Date()).toISOString());
13399
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
13400
+ await input.backend.finishAgencyModelRun(input.tenantId, terminalRun(activeRun, "failed", finishedAt), finishedAt).catch(() => void 0);
13401
+ await input.backend.finishAgencyDispatch(input.tenantId, decision.idempotencyKey, "failed", finishedAt, runId);
13199
13402
  results.push({ loopId: record2.definition.id, decision: "failed", reason });
13200
13403
  }
13201
13404
  }
13202
13405
  return results;
13203
13406
  }
13204
- function jobForTarget(loop, goals) {
13205
- const target = loop.targetRef.kind === "goal" ? goals.get(loop.targetRef.id)?.executionRef : loop.targetRef;
13206
- if (!target) throw new Error(`Loop target Goal is missing: ${loop.targetRef.id}`);
13207
- if (target.kind === "workflow") {
13208
- return { workflow: target.id, cliArgs: {}, flavor: "scheduled" };
13209
- }
13210
- return { capability: target.id, cliArgs: {}, flavor: "scheduled" };
13407
+ function resolveTarget(loop, catalog) {
13408
+ const goal = loop.targetRef.kind === "goal" ? catalog.goals.get(loop.targetRef.id) : void 0;
13409
+ if (loop.targetRef.kind === "goal" && !goal) throw new Error(`Loop target Goal is missing: ${loop.targetRef.id}`);
13410
+ if (goal && goal.definition.operationId !== loop.operationId) {
13411
+ throw new Error(`Loop and target Goal must belong to the same Operation`);
13412
+ }
13413
+ const target = goal?.definition.executionRef ?? loop.targetRef;
13414
+ if (target.kind === "goal") throw new Error("Nested Goal target is invalid");
13415
+ const record2 = target.kind === "workflow" ? catalog.workflows.get(target.id) : catalog.capabilities.get(target.id);
13416
+ if (!record2) throw new Error(`Loop execution target is missing: ${target.kind}:${target.id}`);
13417
+ const reference = { kind: target.kind, id: target.id, revision: record2.revision };
13418
+ return {
13419
+ reference,
13420
+ intermediate: goal ? [{ kind: "goal", id: goal.definition.id, revision: goal.revision }] : [],
13421
+ job: target.kind === "workflow" ? { workflow: target.id, cliArgs: {}, flavor: "scheduled" } : { capability: target.id, cliArgs: {}, flavor: "scheduled" }
13422
+ };
13423
+ }
13424
+ function terminalRun(active, status, finishedAt) {
13425
+ return createRun({ ...active, status, finishedAt });
13211
13426
  }
13212
13427
  function repositoryTenant(config) {
13213
13428
  const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
@@ -13220,6 +13435,7 @@ var init_dispatchAgencyLoops = __esm({
13220
13435
  "use strict";
13221
13436
  init_agencyModelRepository();
13222
13437
  init_triggerDispatcher();
13438
+ init_policyResolver();
13223
13439
  init_job();
13224
13440
  init_state_backend();
13225
13441
  dispatchAgencyLoops = async (ctx) => {
@@ -15078,9 +15294,9 @@ var init_kodyVariables = __esm({
15078
15294
  });
15079
15295
 
15080
15296
  // src/backendVault.ts
15081
- import { createDecipheriv, createHash as createHash2 } from "crypto";
15297
+ import { createDecipheriv, createHash as createHash3 } from "crypto";
15082
15298
  function cacheKey(owner, repo, masterKey) {
15083
- const keyHash = createHash2("sha256").update(masterKey).digest("hex").slice(0, 16);
15299
+ const keyHash = createHash3("sha256").update(masterKey).digest("hex").slice(0, 16);
15084
15300
  return `${owner}/${repo}:${keyHash}`.toLowerCase();
15085
15301
  }
15086
15302
  function decryptVault(payload, masterKey) {
@@ -15729,7 +15945,7 @@ var init_notifyTerminal = __esm({
15729
15945
  });
15730
15946
 
15731
15947
  // src/scripts/openAgencyModelReviewPr.ts
15732
- import { createHash as createHash3 } from "crypto";
15948
+ import { createHash as createHash4 } from "crypto";
15733
15949
  function parseAgencyModelProposal(raw) {
15734
15950
  const text2 = raw.trim();
15735
15951
  const jsonText = (text2.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i)?.[1] ?? text2).trim();
@@ -15781,7 +15997,7 @@ function normalizeBundleFiles(bundle) {
15781
15997
  });
15782
15998
  }
15783
15999
  function buildProposalId(issueNumber, bundle, sourceLabel) {
15784
- const digest = createHash3("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
16000
+ const digest = createHash4("sha256").update(JSON.stringify({ issueNumber, sourceLabel, title: bundle.title, files: normalizeBundleFiles(bundle) })).digest("hex").slice(0, 16);
15785
16001
  return `issue-${issueNumber}-${digest}`;
15786
16002
  }
15787
16003
  function isDryRun(ctx) {
@@ -17853,9 +18069,9 @@ var init_runFlow = __esm({
17853
18069
  });
17854
18070
 
17855
18071
  // src/scripts/previewBuildHelpers.ts
17856
- import { createDecipheriv as createDecipheriv2, createHash as createHash4, hkdfSync as hkdfSync2 } from "crypto";
18072
+ import { createDecipheriv as createDecipheriv2, createHash as createHash5, hkdfSync as hkdfSync2 } from "crypto";
17857
18073
  function shortHash(s) {
17858
- return createHash4("sha256").update(s).digest("hex").slice(0, 6);
18074
+ return createHash5("sha256").update(s).digest("hex").slice(0, 6);
17859
18075
  }
17860
18076
  function previewAppName(repo, pr) {
17861
18077
  const [owner, name] = repo.split("/");
@@ -17888,7 +18104,7 @@ function formatPreviewComment(args) {
17888
18104
  ].join("\n");
17889
18105
  }
17890
18106
  function defaultImageTag(repo, ref) {
17891
- return createHash4("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
18107
+ return createHash5("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
17892
18108
  }
17893
18109
  var init_previewBuildHelpers = __esm({
17894
18110
  "src/scripts/previewBuildHelpers.ts"() {
@@ -25313,7 +25529,7 @@ init_config();
25313
25529
  init_fetchRepoMcp();
25314
25530
 
25315
25531
  // src/servers/mcpHttpServer.ts
25316
- import { randomUUID } from "crypto";
25532
+ import { randomUUID as randomUUID2 } from "crypto";
25317
25533
  import { createServer as createServer4 } from "http";
25318
25534
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
25319
25535
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -25322,7 +25538,7 @@ function buildMcpHttpServer(opts) {
25322
25538
  const transports = /* @__PURE__ */ new Map();
25323
25539
  for (const route of opts.routes) {
25324
25540
  const transport = new StreamableHTTPServerTransport({
25325
- sessionIdGenerator: () => randomUUID()
25541
+ sessionIdGenerator: () => randomUUID2()
25326
25542
  });
25327
25543
  transports.set(route.path, transport);
25328
25544
  routes.set(route.path, route.name);
@@ -25894,7 +26110,7 @@ init_config();
25894
26110
 
25895
26111
  // src/definition-hydration.ts
25896
26112
  init_state_backend();
25897
- import { createHash as createHash5 } from "crypto";
26113
+ import { createHash as createHash6 } from "crypto";
25898
26114
  import * as fs50 from "fs";
25899
26115
  import * as path51 from "path";
25900
26116
  var SLUG_RE2 = /^[a-z0-9][a-z0-9_-]{0,63}$/;
@@ -25915,7 +26131,7 @@ function normalizeDefinitionBundle(bundle) {
25915
26131
  return { schemaVersion: 1, files };
25916
26132
  }
25917
26133
  function definitionVersion(bundle) {
25918
- return `sha256:${createHash5("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
26134
+ return `sha256:${createHash6("sha256").update(JSON.stringify(normalizeDefinitionBundle(bundle))).digest("hex")}`;
25919
26135
  }
25920
26136
  function verifyDefinition(definition) {
25921
26137
  if (!SLUG_RE2.test(definition.slug)) throw new Error(`invalid definition slug: ${definition.slug}`);
@@ -26016,12 +26232,12 @@ import { createServer as createServer5 } from "http";
26016
26232
 
26017
26233
  // src/pool/agency-loop-tick.ts
26018
26234
  function normalizeRepositories(repositories) {
26019
- const unique = /* @__PURE__ */ new Set();
26235
+ const unique2 = /* @__PURE__ */ new Set();
26020
26236
  for (const raw of repositories) {
26021
26237
  const repo = raw.trim().toLowerCase();
26022
- if (/^[^/\s]+\/[^/\s]+$/.test(repo)) unique.add(repo);
26238
+ if (/^[^/\s]+\/[^/\s]+$/.test(repo)) unique2.add(repo);
26023
26239
  }
26024
- return [...unique].sort();
26240
+ return [...unique2].sort();
26025
26241
  }
26026
26242
  async function runAgencyLoopTick(deps) {
26027
26243
  const repositories = normalizeRepositories(await deps.discover());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.414",
3
+ "version": "0.4.415",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,9 +35,9 @@
35
35
  "prepublishOnly": "pnpm typecheck && vitest run tests/unit tests/int --no-coverage && pnpm build && pnpm verify:package"
36
36
  },
37
37
  "dependencies": {
38
- "@kody-ade/agency-domain": "0.1.1",
39
38
  "@actions/cache": "^6.0.0",
40
39
  "@anthropic-ai/claude-agent-sdk": "0.2.119",
40
+ "@kody-ade/agency-domain": "0.4.0",
41
41
  "@modelcontextprotocol/sdk": "^1.29.0",
42
42
  "convex": "^1.17.0",
43
43
  "zod": "^4.0.0"