@kody-ade/kody-engine 0.4.353 → 0.4.354

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 +87 -28
  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.353",
18
+ version: "0.4.354",
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",
@@ -2436,6 +2436,53 @@ var init_registry = __esm({
2436
2436
  }
2437
2437
  });
2438
2438
 
2439
+ // src/trustPolicy.ts
2440
+ function trustSubjectKey(subject) {
2441
+ return `${subject.kind}:${subject.id}`;
2442
+ }
2443
+ function parseTrustMode(rawJson, subject) {
2444
+ return parseTrustModeOverride(rawJson, subject) ?? "ask";
2445
+ }
2446
+ function parseTrustModeOverride(rawJson, subject) {
2447
+ const key = trustSubjectKey(subject);
2448
+ try {
2449
+ const parsed = JSON.parse(rawJson);
2450
+ const rawMode = subject.kind === "capability" ? parsed?.capabilities?.[subject.id]?.mode : parsed?.subjects?.[key]?.mode;
2451
+ if (rawMode === "auto" || rawMode === "ask") return rawMode;
2452
+ return null;
2453
+ } catch {
2454
+ return null;
2455
+ }
2456
+ }
2457
+ function readTrustMode(stateOrRepoSlug, repoSlugOrSubject, maybeSubject) {
2458
+ const mode = typeof stateOrRepoSlug === "string" ? readTrustModeOverride(stateOrRepoSlug, repoSlugOrSubject) : readTrustModeOverride(stateOrRepoSlug, repoSlugOrSubject, maybeSubject);
2459
+ return mode ?? "ask";
2460
+ }
2461
+ function readTrustModeOverride(stateOrRepoSlug, repoSlugOrSubject, maybeSubject) {
2462
+ const state = typeof stateOrRepoSlug === "string" ? void 0 : stateOrRepoSlug;
2463
+ const repoSlug = typeof stateOrRepoSlug === "string" ? stateOrRepoSlug : typeof repoSlugOrSubject === "string" ? repoSlugOrSubject : "";
2464
+ const subject = typeof stateOrRepoSlug === "string" ? repoSlugOrSubject : maybeSubject;
2465
+ if (!subject?.id) return null;
2466
+ try {
2467
+ const loaded = readStateText({ state: state ?? defaultStateForRepoSlug(repoSlug) }, void 0, TRUST_FILE_PATH);
2468
+ return loaded ? parseTrustModeOverride(loaded.content, subject) : null;
2469
+ } catch {
2470
+ return null;
2471
+ }
2472
+ }
2473
+ function defaultStateForRepoSlug(repoSlug) {
2474
+ const [owner, repo] = repoSlug.split("/");
2475
+ return { repo: `${owner}/kody-state`, path: repo ?? repoSlug };
2476
+ }
2477
+ var TRUST_FILE_PATH;
2478
+ var init_trustPolicy = __esm({
2479
+ "src/trustPolicy.ts"() {
2480
+ "use strict";
2481
+ init_stateRepo();
2482
+ TRUST_FILE_PATH = "state/trust.json";
2483
+ }
2484
+ });
2485
+
2439
2486
  // src/capabilityMcp.ts
2440
2487
  var capabilityMcp_exports = {};
2441
2488
  __export(capabilityMcp_exports, {
@@ -2581,28 +2628,14 @@ function readLedger(label) {
2581
2628
  }
2582
2629
  }
2583
2630
  function parseCapabilityTrustMode(rawJson, capabilitySlug) {
2584
- try {
2585
- const parsed = JSON.parse(rawJson);
2586
- return parsed?.capabilities?.[capabilitySlug]?.mode === "auto" ? "auto" : "ask";
2587
- } catch {
2588
- return "ask";
2589
- }
2590
- }
2591
- function defaultStateForRepoSlug(repoSlug) {
2592
- const [owner, repo] = repoSlug.split("/");
2593
- return { repo: `${owner}/kody-state`, path: repo ?? repoSlug };
2631
+ return parseTrustMode(rawJson, { kind: "capability", id: capabilitySlug });
2594
2632
  }
2595
2633
  function readCapabilityTrustMode(stateOrRepoSlug, repoSlugOrCapabilitySlug, maybeCapabilitySlug) {
2596
2634
  const state = typeof stateOrRepoSlug === "string" ? void 0 : stateOrRepoSlug;
2597
2635
  const repoSlug = typeof stateOrRepoSlug === "string" ? stateOrRepoSlug : repoSlugOrCapabilitySlug ?? "";
2598
2636
  const capabilitySlug = typeof stateOrRepoSlug === "string" ? repoSlugOrCapabilitySlug : maybeCapabilitySlug;
2599
2637
  if (!capabilitySlug) return "ask";
2600
- try {
2601
- const loaded = readStateText({ state: state ?? defaultStateForRepoSlug(repoSlug) }, void 0, TRUST_FILE_PATH);
2602
- return loaded ? parseCapabilityTrustMode(loaded.content, capabilitySlug) : "ask";
2603
- } catch {
2604
- return "ask";
2605
- }
2638
+ return readTrustMode(state, repoSlug, { kind: "capability", id: capabilitySlug });
2606
2639
  }
2607
2640
  function readThread(repoSlug, number, limit = 10) {
2608
2641
  const meta = JSON.parse(gh(["api", `repos/${repoSlug}/issues/${number}`]));
@@ -2932,17 +2965,16 @@ function buildCapabilityMcpServer(opts) {
2932
2965
  });
2933
2966
  return { server };
2934
2967
  }
2935
- var FAIL_CONCLUSIONS, RUNNING_STATUSES, TRUST_FILE_PATH, THREAD_BODY_MAX, CHECK_FAIL_CONCLUSIONS, DEFAULT_IGNORE_CHECKS, trackMarker, commentMarker, GATE_EXEMPT_CAPABILITIES, CAPABILITY_MCP_TOOL_NAMES;
2968
+ var FAIL_CONCLUSIONS, RUNNING_STATUSES, THREAD_BODY_MAX, CHECK_FAIL_CONCLUSIONS, DEFAULT_IGNORE_CHECKS, trackMarker, commentMarker, GATE_EXEMPT_CAPABILITIES, CAPABILITY_MCP_TOOL_NAMES;
2936
2969
  var init_capabilityMcp = __esm({
2937
2970
  "src/capabilityMcp.ts"() {
2938
2971
  "use strict";
2939
2972
  init_dashboardCmsMcp();
2940
2973
  init_issue();
2941
2974
  init_registry();
2942
- init_stateRepo();
2975
+ init_trustPolicy();
2943
2976
  FAIL_CONCLUSIONS = /* @__PURE__ */ new Set(["FAILURE", "TIMED_OUT", "ACTION_REQUIRED", "STARTUP_FAILURE", "CANCELLED"]);
2944
2977
  RUNNING_STATUSES = /* @__PURE__ */ new Set(["IN_PROGRESS", "QUEUED", "PENDING", "WAITING", "REQUESTED"]);
2945
- TRUST_FILE_PATH = "state/trust.json";
2946
2978
  THREAD_BODY_MAX = 4e3;
2947
2979
  CHECK_FAIL_CONCLUSIONS = /* @__PURE__ */ new Set(["FAILURE", "TIMED_OUT", "STARTUP_FAILURE", "ACTION_REQUIRED"]);
2948
2980
  DEFAULT_IGNORE_CHECKS = ["run", "kody", "capability-tick", "agent-ask", "chat"];
@@ -9335,14 +9367,16 @@ function scalarFacts(facts) {
9335
9367
  )
9336
9368
  );
9337
9369
  }
9338
- function autonomyBlockReason(ctx, goalId, goal, dispatch2) {
9370
+ function autonomyBlockReason(ctx, goalId, goal, goalState, dispatch2) {
9339
9371
  if (ctx.data.jobForce === true) return null;
9340
- if (goal.runWithoutApproval !== true) {
9372
+ const selfMode = firstTrustOverride(ctx, subjectCandidates(managedModelSubjectKind(goal), goalId, goalState));
9373
+ if (selfMode === "ask" || selfMode !== "auto" && goal.runWithoutApproval !== true) {
9341
9374
  return `Run without approval is off for ${managedModelKind(goal)} ${goalId}`;
9342
9375
  }
9343
9376
  if (dispatch2.workflow) {
9344
- const workflow = readWorkflowDefinition(ctx.config, ctx.cwd, dispatch2.workflow);
9345
- if (workflow && workflow.runWithoutApproval !== true) {
9377
+ const workflowMode = firstTrustOverride(ctx, [{ kind: "workflow", id: dispatch2.workflow }]);
9378
+ const workflow = workflowMode === "auto" ? null : readWorkflowDefinition(ctx.config, ctx.cwd, dispatch2.workflow);
9379
+ if (workflowMode === "ask" || workflowMode !== "auto" && workflow && workflow.runWithoutApproval !== true) {
9346
9380
  return `Run without approval is off for workflow ${dispatch2.workflow}`;
9347
9381
  }
9348
9382
  }
@@ -9350,7 +9384,8 @@ function autonomyBlockReason(ctx, goalId, goal, dispatch2) {
9350
9384
  if (targetGoal && targetGoal !== goalId) {
9351
9385
  const target = fetchGoalState(ctx.config, targetGoal, ctx.cwd);
9352
9386
  const targetManaged = target ? managedGoalFromState(expandManagedGoalState(target)) : null;
9353
- if (targetManaged && targetManaged.runWithoutApproval !== true) {
9387
+ const targetMode = targetManaged ? firstTrustOverride(ctx, subjectCandidates(managedModelSubjectKind(targetManaged), targetGoal, target)) : null;
9388
+ if (targetMode === "ask" || targetMode !== "auto" && targetManaged && targetManaged.runWithoutApproval !== true) {
9354
9389
  return `Run without approval is off for goal ${targetGoal}`;
9355
9390
  }
9356
9391
  }
@@ -9359,6 +9394,29 @@ function autonomyBlockReason(ctx, goalId, goal, dispatch2) {
9359
9394
  function managedModelKind(goal) {
9360
9395
  return goal.loopTarget || goal.schedule ? "Loop" : "Goal";
9361
9396
  }
9397
+ function managedModelSubjectKind(goal) {
9398
+ return managedModelKind(goal) === "Loop" ? "loop" : "goal";
9399
+ }
9400
+ function subjectCandidates(kind, id, state) {
9401
+ const ids = /* @__PURE__ */ new Set();
9402
+ ids.add(id);
9403
+ if (state?.extra) {
9404
+ for (const key of ["sourceTemplate", "templateId", "template"]) {
9405
+ const value = state.extra[key];
9406
+ if (typeof value === "string" && value.trim()) ids.add(value.trim());
9407
+ }
9408
+ }
9409
+ return [...ids].map((candidate) => ({ kind, id: candidate }));
9410
+ }
9411
+ function firstTrustOverride(ctx, subjects) {
9412
+ if (!ctx.config.state) return null;
9413
+ const repoSlug = ctx.config.github?.owner && ctx.config.github?.repo ? `${ctx.config.github.owner}/${ctx.config.github.repo}` : "";
9414
+ for (const subject of subjects) {
9415
+ const mode = readTrustModeOverride(ctx.config.state, repoSlug, subject);
9416
+ if (mode) return mode;
9417
+ }
9418
+ return null;
9419
+ }
9362
9420
  function stageAutonomyBlocked(data, goalId, goal, goalState, reason) {
9363
9421
  stageGoalRunLogEvent(data, goalId, {
9364
9422
  source: "goal-manager",
@@ -9550,6 +9608,7 @@ var init_advanceManagedGoal = __esm({
9550
9608
  init_targetLoopResolution();
9551
9609
  init_typeDefinitions();
9552
9610
  init_issue();
9611
+ init_trustPolicy();
9553
9612
  init_workflowDefinitions();
9554
9613
  init_goalCapabilityScheduling();
9555
9614
  advanceManagedGoal = async (ctx) => {
@@ -9645,7 +9704,7 @@ var init_advanceManagedGoal = __esm({
9645
9704
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
9646
9705
  goal.raw.extra.scheduleState = decision2.scheduleState;
9647
9706
  ctx.data.managedGoalDecision = decision2;
9648
- const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, decision2.dispatch) : null;
9707
+ const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
9649
9708
  if (autonomyBlock) {
9650
9709
  stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
9651
9710
  ctx.output.reason = autonomyBlock;
@@ -9707,7 +9766,7 @@ var init_advanceManagedGoal = __esm({
9707
9766
  goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
9708
9767
  goal.raw.extra.scheduleState = decision2.scheduleState;
9709
9768
  ctx.data.managedGoalDecision = decision2;
9710
- const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, decision2.dispatch) : null;
9769
+ const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, goal.raw, decision2.dispatch) : null;
9711
9770
  if (autonomyBlock) {
9712
9771
  stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
9713
9772
  ctx.output.reason = autonomyBlock;
@@ -9772,7 +9831,7 @@ var init_advanceManagedGoal = __esm({
9772
9831
  ...decision.implementation ? { implementation: decision.implementation } : {},
9773
9832
  cliArgs: decision.cliArgs
9774
9833
  };
9775
- const autonomyBlock = autonomyBlockReason(ctx, goal.id, managed, planned);
9834
+ const autonomyBlock = autonomyBlockReason(ctx, goal.id, managed, goal.raw, planned);
9776
9835
  if (autonomyBlock) {
9777
9836
  stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
9778
9837
  ctx.output.reason = autonomyBlock;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.353",
3
+ "version": "0.4.354",
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",