@kody-ade/kody-engine 0.4.571 → 0.4.573

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 +458 -421
  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.571",
18
+ version: "0.4.573",
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",
@@ -151,17 +151,23 @@ var init_claudeBinary = __esm({
151
151
  });
152
152
 
153
153
  // src/completionGuard.ts
154
+ import * as path2 from "path";
154
155
  function completionToolCutoffAt(startedAtMs, deadlineAtMs) {
155
156
  const availableMs = Math.max(0, deadlineAtMs - startedAtMs);
156
- const reserveMs = Math.min(MAX_COMPLETION_RESERVE_MS, Math.floor(availableMs / 3));
157
+ const reserveMs = Math.min(MAX_COMPLETION_RESERVE_MS, Math.floor(availableMs / 2));
157
158
  return deadlineAtMs - reserveMs;
158
159
  }
159
- function createCompletionToolGuard(cutoffAtMs, now = Date.now) {
160
- return async () => {
160
+ function createCompletionToolGuard(cutoffAtMs, now = Date.now, requiredOutputPath) {
161
+ return async (input) => {
161
162
  if (now() < cutoffAtMs) return {};
163
+ const toolInput = input?.tool_input;
164
+ const filePath = toolInput && typeof toolInput === "object" && !Array.isArray(toolInput) ? toolInput.file_path : void 0;
165
+ if (requiredOutputPath && input?.tool_name === "Write" && typeof filePath === "string" && path2.resolve(filePath) === path2.resolve(requiredOutputPath)) {
166
+ return {};
167
+ }
162
168
  return {
163
169
  decision: "block",
164
- reason: "The run has entered its reserved completion window. Do not call more tools. Use the evidence and changes already present, state any verification limits clearly, and return your final response now."
170
+ reason: "The run has entered its reserved completion window. Do not call more tools. " + (requiredOutputPath ? `If the required structured result is missing, write only ${requiredOutputPath}. ` : "") + "Use the evidence and changes already present, state any verification limits clearly, and return your final response now."
165
171
  };
166
172
  };
167
173
  }
@@ -169,13 +175,13 @@ var MAX_COMPLETION_RESERVE_MS;
169
175
  var init_completionGuard = __esm({
170
176
  "src/completionGuard.ts"() {
171
177
  "use strict";
172
- MAX_COMPLETION_RESERVE_MS = 10 * 6e4;
178
+ MAX_COMPLETION_RESERVE_MS = 15 * 6e4;
173
179
  }
174
180
  });
175
181
 
176
182
  // src/config.ts
177
183
  import * as fs2 from "fs";
178
- import * as path2 from "path";
184
+ import * as path3 from "path";
179
185
  function parseReasoningEffort(raw) {
180
186
  if (!raw) return null;
181
187
  const v = raw.trim().toLowerCase();
@@ -240,7 +246,7 @@ function needsLitellmProxy(model) {
240
246
  return model.provider !== "claude" && model.provider !== "anthropic";
241
247
  }
242
248
  function loadConfig(projectDir = process.cwd()) {
243
- const configPath = path2.join(projectDir, "kody.config.json");
249
+ const configPath = path3.join(projectDir, "kody.config.json");
244
250
  if (!fs2.existsSync(configPath)) {
245
251
  throw new Error(`kody.config.json not found at ${configPath}`);
246
252
  }
@@ -573,15 +579,15 @@ var init_config = __esm({
573
579
 
574
580
  // src/fileEditGuards.ts
575
581
  import * as fs3 from "fs";
576
- import * as path3 from "path";
582
+ import * as path4 from "path";
577
583
  function createMissingParentWriteGuard(cwd) {
578
584
  return async (input) => {
579
585
  const toolInput = input.tool_input;
580
586
  if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
581
587
  const filePath = toolInput.file_path;
582
588
  if (typeof filePath !== "string" || filePath.length === 0) return {};
583
- const resolvedPath = path3.resolve(cwd, filePath);
584
- if (fs3.existsSync(path3.dirname(resolvedPath))) return {};
589
+ const resolvedPath = path4.resolve(cwd, filePath);
590
+ if (fs3.existsSync(path4.dirname(resolvedPath))) return {};
585
591
  return {
586
592
  decision: "block",
587
593
  reason: `Cannot write ${resolvedPath}: its parent directory does not exist. Locate and edit the real repository source path first. If this task genuinely requires a new directory, create that directory explicitly before writing the file.`
@@ -788,7 +794,7 @@ var init_capability_contract_validation = __esm({
788
794
 
789
795
  // src/outputContractHooks.ts
790
796
  import * as fs4 from "fs";
791
- import * as path4 from "path";
797
+ import * as path5 from "path";
792
798
  function outputContractError(contract) {
793
799
  let value;
794
800
  try {
@@ -807,12 +813,12 @@ function correctionMessage(contract, error) {
807
813
  return `The authoritative output does not match its required contract: ${error}. Please overwrite ${contract.path} with only the required JSON shape before finishing.`;
808
814
  }
809
815
  function createOutputContractPostWriteHook(contract) {
810
- const expectedPath = path4.resolve(contract.path);
816
+ const expectedPath = path5.resolve(contract.path);
811
817
  return async (input) => {
812
818
  const toolInput = input.tool_input;
813
819
  if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
814
820
  const filePath = toolInput.file_path;
815
- if (typeof filePath !== "string" || path4.resolve(filePath) !== expectedPath) return {};
821
+ if (typeof filePath !== "string" || path5.resolve(filePath) !== expectedPath) return {};
816
822
  const error = outputContractError(contract);
817
823
  if (!error) return {};
818
824
  return {
@@ -856,21 +862,21 @@ __export(runtimePaths_exports, {
856
862
  });
857
863
  import { createHash } from "crypto";
858
864
  import * as os2 from "os";
859
- import * as path5 from "path";
865
+ import * as path6 from "path";
860
866
  function runtimeDirForCwd(cwd, ...parts) {
861
- const key = createHash("sha256").update(path5.resolve(cwd)).digest("hex").slice(0, 16);
862
- return path5.join(os2.tmpdir(), "kody-engine", key, ...parts);
867
+ const key = createHash("sha256").update(path6.resolve(cwd)).digest("hex").slice(0, 16);
868
+ return path6.join(os2.tmpdir(), "kody-engine", key, ...parts);
863
869
  }
864
870
  function runtimeStatePath(cwd, ...parts) {
865
871
  const configuredRoot = process.env.KODY_RUNTIME_DIR?.trim();
866
- const base = configuredRoot ? path5.resolve(configuredRoot) : runtimeDirForCwd(cwd);
867
- return path5.join(base, ...parts);
872
+ const base = configuredRoot ? path6.resolve(configuredRoot) : runtimeDirForCwd(cwd);
873
+ return path6.join(base, ...parts);
868
874
  }
869
875
  function agentRunDir(cwd) {
870
876
  return runtimeStatePath(cwd, "agent-runs");
871
877
  }
872
878
  function lastRunLogPath(cwd) {
873
- return path5.join(agentRunDir(cwd), "last-run.jsonl");
879
+ return path6.join(agentRunDir(cwd), "last-run.jsonl");
874
880
  }
875
881
  var init_runtimePaths = __esm({
876
882
  "src/runtimePaths.ts"() {
@@ -881,15 +887,15 @@ var init_runtimePaths = __esm({
881
887
  // src/scripts/buildSyntheticPlugin.ts
882
888
  import * as fs5 from "fs";
883
889
  import * as os3 from "os";
884
- import * as path6 from "path";
890
+ import * as path7 from "path";
885
891
  function getPluginsCatalogRoot() {
886
- const here = path6.dirname(new URL(import.meta.url).pathname);
892
+ const here = path7.dirname(new URL(import.meta.url).pathname);
887
893
  const candidates = [
888
- path6.join(here, "..", "plugins"),
894
+ path7.join(here, "..", "plugins"),
889
895
  // dev: src/scripts → src/plugins
890
- path6.join(here, "..", "..", "plugins"),
896
+ path7.join(here, "..", "..", "plugins"),
891
897
  // built: dist/scripts → dist/plugins
892
- path6.join(here, "..", "..", "src", "plugins")
898
+ path7.join(here, "..", "..", "src", "plugins")
893
899
  // fallback
894
900
  ];
895
901
  for (const c of candidates) {
@@ -900,8 +906,8 @@ function getPluginsCatalogRoot() {
900
906
  function copyDir(src, dst) {
901
907
  fs5.mkdirSync(dst, { recursive: true });
902
908
  for (const ent of fs5.readdirSync(src, { withFileTypes: true })) {
903
- const s = path6.join(src, ent.name);
904
- const d = path6.join(dst, ent.name);
909
+ const s = path7.join(src, ent.name);
910
+ const d = path7.join(dst, ent.name);
905
911
  if (ent.isDirectory()) copyDir(s, d);
906
912
  else if (ent.isFile()) fs5.copyFileSync(s, d);
907
913
  }
@@ -916,35 +922,35 @@ var init_buildSyntheticPlugin = __esm({
916
922
  if (!needsSynthetic) return;
917
923
  const catalog = getPluginsCatalogRoot();
918
924
  const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
919
- const root = path6.join(os3.tmpdir(), `kody-synth-${runId}`);
920
- fs5.mkdirSync(path6.join(root, ".claude-plugin"), { recursive: true });
925
+ const root = path7.join(os3.tmpdir(), `kody-synth-${runId}`);
926
+ fs5.mkdirSync(path7.join(root, ".claude-plugin"), { recursive: true });
921
927
  const resolvePart = (bucket, entry) => {
922
- const local = path6.join(profile.dir, bucket, entry);
928
+ const local = path7.join(profile.dir, bucket, entry);
923
929
  if (fs5.existsSync(local)) return local;
924
- const shared = path6.resolve(profile.dir, "..", "..", "shared", bucket, entry);
930
+ const shared = path7.resolve(profile.dir, "..", "..", "shared", bucket, entry);
925
931
  if (fs5.existsSync(shared)) return shared;
926
- const central = path6.join(catalog, bucket, entry);
932
+ const central = path7.join(catalog, bucket, entry);
927
933
  if (fs5.existsSync(central)) return central;
928
934
  throw new Error(
929
- `buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path6.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
935
+ `buildSyntheticPlugin: ${bucket} entry '${entry}' not found in implementation dir (${profile.dir}/${bucket}/), Store shared assets (${path7.dirname(shared)}/), or catalog (${catalog}/${bucket}/)`
930
936
  );
931
937
  };
932
938
  if (cc.skills.length > 0) {
933
- const dst = path6.join(root, "skills");
939
+ const dst = path7.join(root, "skills");
934
940
  fs5.mkdirSync(dst, { recursive: true });
935
941
  for (const name of cc.skills) {
936
- copyDir(resolvePart("skills", name), path6.join(dst, name));
942
+ copyDir(resolvePart("skills", name), path7.join(dst, name));
937
943
  }
938
944
  }
939
945
  if (cc.commands.length > 0) {
940
- const dst = path6.join(root, "commands");
946
+ const dst = path7.join(root, "commands");
941
947
  fs5.mkdirSync(dst, { recursive: true });
942
948
  for (const name of cc.commands) {
943
- fs5.copyFileSync(resolvePart("commands", `${name}.md`), path6.join(dst, `${name}.md`));
949
+ fs5.copyFileSync(resolvePart("commands", `${name}.md`), path7.join(dst, `${name}.md`));
944
950
  }
945
951
  }
946
952
  if (cc.hooks.length > 0) {
947
- const dst = path6.join(root, "hooks");
953
+ const dst = path7.join(root, "hooks");
948
954
  fs5.mkdirSync(dst, { recursive: true });
949
955
  const merged = { hooks: {} };
950
956
  for (const name of cc.hooks) {
@@ -956,7 +962,7 @@ var init_buildSyntheticPlugin = __esm({
956
962
  merged.hooks[event].push(...entries);
957
963
  }
958
964
  }
959
- fs5.writeFileSync(path6.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
965
+ fs5.writeFileSync(path7.join(dst, "hooks.json"), `${JSON.stringify(merged, null, 2)}
960
966
  `);
961
967
  }
962
968
  const manifest = {
@@ -966,7 +972,7 @@ var init_buildSyntheticPlugin = __esm({
966
972
  };
967
973
  if (cc.skills.length > 0) manifest.skills = ["./skills/"];
968
974
  if (cc.commands.length > 0) manifest.commands = ["./commands/"];
969
- fs5.writeFileSync(path6.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
975
+ fs5.writeFileSync(path7.join(root, ".claude-plugin", "plugin.json"), `${JSON.stringify(manifest, null, 2)}
970
976
  `);
971
977
  ctx.data.syntheticPluginPath = root;
972
978
  };
@@ -975,7 +981,7 @@ var init_buildSyntheticPlugin = __esm({
975
981
 
976
982
  // src/subagents.ts
977
983
  import * as fs6 from "fs";
978
- import * as path7 from "path";
984
+ import * as path8 from "path";
979
985
  async function enforceSubagentModelInheritance(input) {
980
986
  const toolInput = input.tool_input;
981
987
  if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
@@ -1010,11 +1016,11 @@ function splitFrontmatter(raw) {
1010
1016
  return { fm, body: (match[2] ?? "").trim() };
1011
1017
  }
1012
1018
  function resolveAgentFile(profileDir, name) {
1013
- const local = path7.join(profileDir, "agents", `${name}.md`);
1019
+ const local = path8.join(profileDir, "agents", `${name}.md`);
1014
1020
  if (fs6.existsSync(local)) return local;
1015
- const shared = path7.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
1021
+ const shared = path8.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
1016
1022
  if (fs6.existsSync(shared)) return shared;
1017
- const central = path7.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
1023
+ const central = path8.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
1018
1024
  if (fs6.existsSync(central)) return central;
1019
1025
  throw new Error(
1020
1026
  `loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
@@ -1071,7 +1077,7 @@ __export(events_exports, {
1071
1077
  });
1072
1078
  import * as crypto from "crypto";
1073
1079
  import * as fs7 from "fs";
1074
- import * as path8 from "path";
1080
+ import * as path9 from "path";
1075
1081
  function resolveRunId() {
1076
1082
  if (process.env.KODY_RUN_ID) {
1077
1083
  cachedRunId = process.env.KODY_RUN_ID;
@@ -1104,7 +1110,7 @@ function emitEvent(cwd, ev) {
1104
1110
  ...ev
1105
1111
  };
1106
1112
  const file = eventsPath(cwd, runId);
1107
- fs7.mkdirSync(path8.dirname(file), { recursive: true });
1113
+ fs7.mkdirSync(path9.dirname(file), { recursive: true });
1108
1114
  fs7.appendFileSync(file, `${JSON.stringify(fullEvent)}
1109
1115
  `);
1110
1116
  } catch {
@@ -1130,7 +1136,7 @@ function listRuns(cwd) {
1130
1136
  if (!fs7.existsSync(runsDir)) return [];
1131
1137
  return fs7.readdirSync(runsDir).filter((name) => {
1132
1138
  try {
1133
- return fs7.statSync(path8.join(runsDir, name)).isDirectory();
1139
+ return fs7.statSync(path9.join(runsDir, name)).isDirectory();
1134
1140
  } catch {
1135
1141
  return false;
1136
1142
  }
@@ -1171,10 +1177,10 @@ function abortMessage(signal) {
1171
1177
  return reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "verification aborted";
1172
1178
  }
1173
1179
  function runCommand(command, cwd, signal) {
1174
- return new Promise((resolve23) => {
1180
+ return new Promise((resolve24) => {
1175
1181
  const start = Date.now();
1176
1182
  if (signal?.aborted) {
1177
- resolve23({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
1183
+ resolve24({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
1178
1184
  return;
1179
1185
  }
1180
1186
  const child = spawn(command, {
@@ -1212,7 +1218,7 @@ function runCommand(command, cwd, signal) {
1212
1218
  signal?.removeEventListener("abort", onAbort);
1213
1219
  const output = Buffer.concat(buffers).toString("utf-8");
1214
1220
  const tail = [output, extraTail].filter(Boolean).join("\n").slice(-TAIL_CHARS);
1215
- resolve23({ exitCode, durationMs: Date.now() - start, tail });
1221
+ resolve24({ exitCode, durationMs: Date.now() - start, tail });
1216
1222
  };
1217
1223
  const terminate = () => {
1218
1224
  killTree("SIGTERM");
@@ -1541,7 +1547,7 @@ function cmsHeaders(opts) {
1541
1547
  }
1542
1548
  };
1543
1549
  }
1544
- async function callDashboardCms(opts, path58, init = {}) {
1550
+ async function callDashboardCms(opts, path59, init = {}) {
1545
1551
  const baseUrl = dashboardBaseUrl(opts);
1546
1552
  if (!baseUrl) {
1547
1553
  return {
@@ -1553,7 +1559,7 @@ async function callDashboardCms(opts, path58, init = {}) {
1553
1559
  const headerResult = cmsHeaders(opts);
1554
1560
  if (!headerResult.ok) return headerResult;
1555
1561
  try {
1556
- const res = await fetch(`${baseUrl}${path58}`, {
1562
+ const res = await fetch(`${baseUrl}${path59}`, {
1557
1563
  ...init,
1558
1564
  headers: {
1559
1565
  ...headerResult.headers,
@@ -1625,8 +1631,8 @@ function documentArg(value) {
1625
1631
  function normalizeCmsDocumentIdInput(input) {
1626
1632
  const trimmed = stripWrappingQuotes(input.trim());
1627
1633
  const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
1628
- const path58 = parseDocumentPath(withoutQuery);
1629
- return path58 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
1634
+ const path59 = parseDocumentPath(withoutQuery);
1635
+ return path59 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
1630
1636
  }
1631
1637
  function stripWrappingQuotes(value) {
1632
1638
  let current = value;
@@ -1637,9 +1643,9 @@ function stripWrappingQuotes(value) {
1637
1643
  }
1638
1644
  }
1639
1645
  function parseDocumentPath(value) {
1640
- const path58 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
1641
- if (!path58?.includes("/content/entries/")) return null;
1642
- const parts = path58.split("/").filter(Boolean).map(decodePathPart);
1646
+ const path59 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
1647
+ if (!path59?.includes("/content/entries/")) return null;
1648
+ const parts = path59.split("/").filter(Boolean).map(decodePathPart);
1643
1649
  const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
1644
1650
  const idPart = parts[entriesIndex + 3];
1645
1651
  if (!idPart || idPart === "new") return null;
@@ -2085,7 +2091,7 @@ var init_issue = __esm({
2085
2091
 
2086
2092
  // src/capabilityFolders.ts
2087
2093
  import * as fs8 from "fs";
2088
- import * as path9 from "path";
2094
+ import * as path10 from "path";
2089
2095
  function capabilityOutputConditionPaths(config) {
2090
2096
  if (config.outputSchema) {
2091
2097
  return new Set(schemaPropertyPaths(config.outputSchema, "result"));
@@ -2107,35 +2113,35 @@ function listCapabilityFolderSlugs(absDir) {
2107
2113
  } catch {
2108
2114
  return [];
2109
2115
  }
2110
- return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path9.join(absDir, e.name))).map((e) => e.name).sort();
2116
+ return entries.filter((e) => e.isDirectory() && !e.name.startsWith("_") && !e.name.startsWith(".")).filter((e) => isCapabilityFolder(path10.join(absDir, e.name))).map((e) => e.name).sort();
2111
2117
  }
2112
2118
  function isCapabilityFolder(dir) {
2113
2119
  const entries = fs8.readdirSync(dir, { withFileTypes: true });
2114
- const legacyBody = path9.join(dir, CAPABILITY_BODY_FILE);
2120
+ const legacyBody = path10.join(dir, CAPABILITY_BODY_FILE);
2115
2121
  if (fs8.existsSync(legacyBody)) {
2116
2122
  return entries.every(
2117
2123
  (entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
2118
2124
  );
2119
2125
  }
2120
- const canonicalBody = path9.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
2121
- const canonicalDefinition = path9.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2126
+ const canonicalBody = path10.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
2127
+ const canonicalDefinition = path10.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2122
2128
  if (!fs8.existsSync(canonicalBody) || !fs8.existsSync(canonicalDefinition)) return false;
2123
2129
  return entries.every(
2124
2130
  (entry) => entry.name === CANONICAL_CAPABILITY_BODY_FILE || entry.name === CANONICAL_CAPABILITY_DEFINITION_FILE
2125
2131
  );
2126
2132
  }
2127
2133
  function readCapabilityFolder(root, slug) {
2128
- const dir = path9.join(root, slug);
2129
- const legacyBodyPath = path9.join(dir, CAPABILITY_BODY_FILE);
2130
- const canonicalBodyPath = path9.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
2134
+ const dir = path10.join(root, slug);
2135
+ const legacyBodyPath = path10.join(dir, CAPABILITY_BODY_FILE);
2136
+ const canonicalBodyPath = path10.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
2131
2137
  const bodyPath = fs8.existsSync(legacyBodyPath) ? legacyBodyPath : canonicalBodyPath;
2132
- const contractPath = path9.join(dir, CAPABILITY_CONTRACT_FILE);
2138
+ const contractPath = path10.join(dir, CAPABILITY_CONTRACT_FILE);
2133
2139
  if (!fs8.existsSync(bodyPath) || !fs8.statSync(bodyPath).isFile()) return null;
2134
2140
  if (!isCapabilityFolder(dir)) return null;
2135
2141
  try {
2136
2142
  const rawBody = fs8.readFileSync(bodyPath, "utf-8");
2137
2143
  if (bodyPath === canonicalBodyPath) {
2138
- const definitionPath = path9.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2144
+ const definitionPath = path10.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2139
2145
  const definition = JSON.parse(fs8.readFileSync(definitionPath, "utf-8"));
2140
2146
  if (definition.id !== slug || typeof definition.action !== "string") return null;
2141
2147
  const { title: title2, body: body2 } = parseCapabilityBody(rawBody, slug);
@@ -2157,7 +2163,7 @@ function readCapabilityFolder(root, slug) {
2157
2163
  };
2158
2164
  }
2159
2165
  const contract = fs8.existsSync(contractPath) ? parseCapabilityContract(fs8.readFileSync(contractPath, "utf-8")) : void 0;
2160
- if (contract?.execution === "script" && !isRegularFile(path9.join(dir, "tools", "run.sh"))) {
2166
+ if (contract?.execution === "script" && !isRegularFile(path10.join(dir, "tools", "run.sh"))) {
2161
2167
  throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
2162
2168
  }
2163
2169
  const { title, body } = parseCapabilityBody(rawBody, slug);
@@ -2181,6 +2187,7 @@ function readCapabilityFolder(root, slug) {
2181
2187
  },
2182
2188
  rawProfile: contract ? {
2183
2189
  ...contract.execution ? { execution: contract.execution } : {},
2190
+ ...contract.deliveryPolicy ? { deliveryPolicy: contract.deliveryPolicy } : {},
2184
2191
  input: contract.input,
2185
2192
  output: contract.output
2186
2193
  } : {},
@@ -2221,13 +2228,20 @@ function parseCapabilityContract(raw) {
2221
2228
  throw new Error('contract.json requiredSubagents are supported only when execution is "agent"');
2222
2229
  }
2223
2230
  const unsupported = Object.keys(parsed).filter(
2224
- (key) => key !== "execution" && key !== "requirements" && key !== "secrets" && key !== "timeoutMs" && key !== "requiredSubagents" && key !== "input" && key !== "output"
2231
+ (key) => key !== "execution" && key !== "deliveryPolicy" && key !== "requirements" && key !== "secrets" && key !== "timeoutMs" && key !== "requiredSubagents" && key !== "input" && key !== "output"
2225
2232
  );
2226
2233
  if (unsupported.length > 0) {
2227
2234
  throw new Error(`contract.json contains unsupported fields: ${unsupported.join(", ")}`);
2228
2235
  }
2236
+ if (parsed.deliveryPolicy !== void 0 && parsed.deliveryPolicy !== "checkpoint") {
2237
+ throw new Error('contract.json deliveryPolicy must be "checkpoint"');
2238
+ }
2239
+ if (parsed.deliveryPolicy === "checkpoint" && parsed.execution !== "agent") {
2240
+ throw new Error('contract.json deliveryPolicy "checkpoint" is supported only when execution is "agent"');
2241
+ }
2229
2242
  return {
2230
2243
  ...parsed.execution ? { execution: parsed.execution } : {},
2244
+ ...parsed.deliveryPolicy === "checkpoint" ? { deliveryPolicy: "checkpoint" } : {},
2231
2245
  ...requirements ? { requirements } : {},
2232
2246
  ...secrets ? { secrets } : {},
2233
2247
  ...timeoutMs !== void 0 ? { timeoutMs } : {},
@@ -2279,8 +2293,8 @@ function isRegularFile(filePath) {
2279
2293
  function schemaPropertyPaths(schema, prefix) {
2280
2294
  const properties = isPlainObject(schema.properties) ? schema.properties : {};
2281
2295
  return Object.entries(properties).flatMap(([name, property]) => {
2282
- const path58 = `${prefix}.${name}`;
2283
- return isPlainObject(property) ? [path58, ...schemaPropertyPaths(property, path58)] : [path58];
2296
+ const path59 = `${prefix}.${name}`;
2297
+ return isPlainObject(property) ? [path59, ...schemaPropertyPaths(property, path59)] : [path59];
2284
2298
  });
2285
2299
  }
2286
2300
  function parseCapabilityBody(raw, slug) {
@@ -2447,47 +2461,47 @@ var init_capabilityFolders = __esm({
2447
2461
 
2448
2462
  // src/definition-paths.ts
2449
2463
  import * as fs9 from "fs";
2450
- import * as path10 from "path";
2464
+ import * as path11 from "path";
2451
2465
  function definitionsRoot(cwd = process.cwd()) {
2452
2466
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
2453
2467
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2454
- if (override && overrideCwd && path10.resolve(cwd) === path10.resolve(overrideCwd)) {
2455
- return storeCatalogRoot(path10.resolve(override));
2468
+ if (override && overrideCwd && path11.resolve(cwd) === path11.resolve(overrideCwd)) {
2469
+ return storeCatalogRoot(path11.resolve(override));
2456
2470
  }
2457
- const hydrated = path10.join(cwd, ".kody-engine", "definitions");
2471
+ const hydrated = path11.join(cwd, ".kody-engine", "definitions");
2458
2472
  if (fs9.existsSync(hydrated)) return hydrated;
2459
- return override ? storeCatalogRoot(path10.resolve(override)) : hydrated;
2473
+ return override ? storeCatalogRoot(path11.resolve(override)) : hydrated;
2460
2474
  }
2461
2475
  function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
2462
2476
  const root = env.KODY_DEFINITIONS_ROOT?.trim();
2463
2477
  const rootCwd = env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2464
- return Boolean(root && rootCwd && path10.resolve(cwd) === path10.resolve(rootCwd));
2478
+ return Boolean(root && rootCwd && path11.resolve(cwd) === path11.resolve(rootCwd));
2465
2479
  }
2466
2480
  function capabilitiesRoot(cwd = process.cwd()) {
2467
- return storeAssetRoot(cwd, "capabilities") ?? path10.join(definitionsRoot(cwd), "capabilities");
2481
+ return storeAssetRoot(cwd, "capabilities") ?? path11.join(definitionsRoot(cwd), "capabilities");
2468
2482
  }
2469
2483
  function implementationsRoot(cwd = process.cwd()) {
2470
- return path10.join(definitionsRoot(cwd), "implementations");
2484
+ return path11.join(definitionsRoot(cwd), "implementations");
2471
2485
  }
2472
2486
  function agentsRoot(cwd = process.cwd()) {
2473
- return storeAssetRoot(cwd, "agent") ?? path10.join(definitionsRoot(cwd), "agents");
2487
+ return storeAssetRoot(cwd, "agent") ?? path11.join(definitionsRoot(cwd), "agents");
2474
2488
  }
2475
2489
  function storeCatalogRoot(root) {
2476
2490
  const manifest = readStoreManifest(root);
2477
- const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path10.dirname(value));
2478
- return roots.length === 3 && new Set(roots).size === 1 ? path10.join(root, roots[0]) : root;
2491
+ const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path11.dirname(value));
2492
+ return roots.length === 3 && new Set(roots).size === 1 ? path11.join(root, roots[0]) : root;
2479
2493
  }
2480
2494
  function storeAssetRoot(cwd, kind) {
2481
2495
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
2482
2496
  if (!override) return null;
2483
2497
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2484
- if (overrideCwd && path10.resolve(cwd) !== path10.resolve(overrideCwd)) return null;
2485
- const root = path10.resolve(override);
2498
+ if (overrideCwd && path11.resolve(cwd) !== path11.resolve(overrideCwd)) return null;
2499
+ const root = path11.resolve(override);
2486
2500
  const configured = readStoreManifest(root)?.assetRoots?.[kind];
2487
- return typeof configured === "string" && configured.trim() ? path10.join(root, configured) : null;
2501
+ return typeof configured === "string" && configured.trim() ? path11.join(root, configured) : null;
2488
2502
  }
2489
2503
  function readStoreManifest(root) {
2490
- const file = path10.join(root, "kody-store.json");
2504
+ const file = path11.join(root, "kody-store.json");
2491
2505
  if (!fs9.existsSync(file)) return null;
2492
2506
  try {
2493
2507
  return JSON.parse(fs9.readFileSync(file, "utf8"));
@@ -2503,15 +2517,15 @@ var init_definition_paths = __esm({
2503
2517
 
2504
2518
  // src/registry.ts
2505
2519
  import * as fs10 from "fs";
2506
- import * as path11 from "path";
2520
+ import * as path12 from "path";
2507
2521
  function getImplementationsRoot() {
2508
- const here = path11.dirname(new URL(import.meta.url).pathname);
2522
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2509
2523
  const candidates = [
2510
- path11.join(here, "implementations"),
2524
+ path12.join(here, "implementations"),
2511
2525
  // dev: src/
2512
- path11.join(here, "..", "implementations"),
2526
+ path12.join(here, "..", "implementations"),
2513
2527
  // built: dist/bin → dist/implementations
2514
- path11.join(here, "..", "src", "implementations")
2528
+ path12.join(here, "..", "src", "implementations")
2515
2529
  // fallback
2516
2530
  ];
2517
2531
  for (const c of candidates) {
@@ -2520,11 +2534,11 @@ function getImplementationsRoot() {
2520
2534
  return candidates[0];
2521
2535
  }
2522
2536
  function getRuntimeServicesRoot() {
2523
- const here = path11.dirname(new URL(import.meta.url).pathname);
2537
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2524
2538
  const candidates = [
2525
- path11.join(here, "runtime-services"),
2526
- path11.join(here, "..", "runtime-services"),
2527
- path11.join(here, "..", "src", "runtime-services")
2539
+ path12.join(here, "runtime-services"),
2540
+ path12.join(here, "..", "runtime-services"),
2541
+ path12.join(here, "..", "src", "runtime-services")
2528
2542
  ];
2529
2543
  for (const candidate of candidates) {
2530
2544
  if (fs10.existsSync(candidate) && fs10.statSync(candidate).isDirectory()) return candidate;
@@ -2535,13 +2549,13 @@ function getProjectCapabilitiesRoot() {
2535
2549
  return capabilitiesRoot();
2536
2550
  }
2537
2551
  function getBuiltinCapabilitiesRoot() {
2538
- const here = path11.dirname(new URL(import.meta.url).pathname);
2552
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2539
2553
  const candidates = [
2540
- path11.join(here, "capabilities"),
2554
+ path12.join(here, "capabilities"),
2541
2555
  // dev: src/
2542
- path11.join(here, "..", "capabilities"),
2556
+ path12.join(here, "..", "capabilities"),
2543
2557
  // built: dist/bin → dist/capabilities
2544
- path11.join(here, "..", "src", "capabilities")
2558
+ path12.join(here, "..", "src", "capabilities")
2545
2559
  // fallback
2546
2560
  ];
2547
2561
  for (const c of candidates) {
@@ -2685,17 +2699,17 @@ function isSafeName(name) {
2685
2699
  return /^[a-z][a-z0-9-]*$/.test(name) && !name.includes("..");
2686
2700
  }
2687
2701
  function isCapabilityRoot(root) {
2688
- const normalized = path11.normalize(root);
2689
- if (path11.basename(normalized) === "capabilities") return true;
2702
+ const normalized = path12.normalize(root);
2703
+ if (path12.basename(normalized) === "capabilities") return true;
2690
2704
  const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
2691
- return knownRoots.some((candidate) => candidate && path11.normalize(candidate) === normalized);
2705
+ return knownRoots.some((candidate) => candidate && path12.normalize(candidate) === normalized);
2692
2706
  }
2693
2707
  function implementationRuntimePath(root, name) {
2694
- const runtimePath = path11.join(root, name, "runtime.json");
2708
+ const runtimePath = path12.join(root, name, "runtime.json");
2695
2709
  if (fs10.existsSync(runtimePath)) return runtimePath;
2696
- const internalProfilePath = path11.join(root, name, "profile.json");
2710
+ const internalProfilePath = path12.join(root, name, "profile.json");
2697
2711
  if (fs10.existsSync(internalProfilePath)) return internalProfilePath;
2698
- return path11.join(root, name, CAPABILITY_PROFILE_FILE);
2712
+ return path12.join(root, name, CAPABILITY_PROFILE_FILE);
2699
2713
  }
2700
2714
  function isImplementationProfile(profilePath, requireImplementationProfile) {
2701
2715
  if (!requireImplementationProfile) return true;
@@ -3862,7 +3876,7 @@ var init_capabilityMcp = __esm({
3862
3876
  // src/repoWorkspace.ts
3863
3877
  import { spawn as spawn2, spawnSync } from "child_process";
3864
3878
  import * as fs11 from "fs";
3865
- import * as path12 from "path";
3879
+ import * as path13 from "path";
3866
3880
  function buildCloneProcess(repo, token, baseEnv = process.env) {
3867
3881
  const url = `https://github.com/${repo}.git`;
3868
3882
  const env = { ...baseEnv };
@@ -3877,10 +3891,10 @@ function buildCloneProcess(repo, token, baseEnv = process.env) {
3877
3891
  async function resolveAndClone(reposRoot, repo, repoToken, cloneRepo) {
3878
3892
  const name = repo?.trim();
3879
3893
  if (!name || !REPO_RE.test(name)) return null;
3880
- const root = path12.resolve(reposRoot);
3881
- const dir = path12.resolve(root, name);
3882
- if (dir !== root && !dir.startsWith(root + path12.sep)) return null;
3883
- if (fs11.existsSync(path12.join(dir, ".git"))) return dir;
3894
+ const root = path13.resolve(reposRoot);
3895
+ const dir = path13.resolve(root, name);
3896
+ if (dir !== root && !dir.startsWith(root + path13.sep)) return null;
3897
+ if (fs11.existsSync(path13.join(dir, ".git"))) return dir;
3884
3898
  const inflight = repoClones.get(dir);
3885
3899
  if (inflight) {
3886
3900
  await inflight;
@@ -3912,9 +3926,9 @@ var init_repoWorkspace = __esm({
3912
3926
  repoClones = /* @__PURE__ */ new Map();
3913
3927
  GIT_CREDENTIAL_HELPER = `!f() { if [ "$1" = get ] && [ -n "$GITHUB_TOKEN" ]; then printf '%s\\n' username=x-access-token "password=$GITHUB_TOKEN"; fi; }; f`;
3914
3928
  defaultCloneRepo = (repo, token, dir) => {
3915
- fs11.mkdirSync(path12.dirname(dir), { recursive: true });
3929
+ fs11.mkdirSync(path13.dirname(dir), { recursive: true });
3916
3930
  const clone = buildCloneProcess(repo, token);
3917
- return new Promise((resolve23, reject) => {
3931
+ return new Promise((resolve24, reject) => {
3918
3932
  const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
3919
3933
  env: clone.env,
3920
3934
  stdio: "inherit"
@@ -3934,7 +3948,7 @@ var init_repoWorkspace = __esm({
3934
3948
  }
3935
3949
  } catch {
3936
3950
  }
3937
- resolve23();
3951
+ resolve24();
3938
3952
  });
3939
3953
  child.on("error", reject);
3940
3954
  });
@@ -4007,7 +4021,7 @@ var init_fetchRepoMcp = __esm({
4007
4021
 
4008
4022
  // src/agent.ts
4009
4023
  import * as fs12 from "fs";
4010
- import * as path13 from "path";
4024
+ import * as path14 from "path";
4011
4025
  import { query } from "@anthropic-ai/claude-agent-sdk";
4012
4026
  function classifySubtype(subtype) {
4013
4027
  if (!subtype) return "generic_failed";
@@ -4077,7 +4091,7 @@ function buildAgentEnvironment(baseEnv, repoToken, requestEnvironment) {
4077
4091
  async function runAgent(opts) {
4078
4092
  const ndjsonDir = opts.ndjsonDir ?? agentRunDir(opts.cwd);
4079
4093
  fs12.mkdirSync(ndjsonDir, { recursive: true });
4080
- const ndjsonPath = path13.join(ndjsonDir, "last-run.jsonl");
4094
+ const ndjsonPath = path14.join(ndjsonDir, "last-run.jsonl");
4081
4095
  const env = buildAgentEnvironment(process.env, opts.repoToken, opts.environment);
4082
4096
  if (opts.litellmUrl) {
4083
4097
  env.ANTHROPIC_BASE_URL = opts.litellmUrl;
@@ -4085,7 +4099,11 @@ async function runAgent(opts) {
4085
4099
  }
4086
4100
  const startedAt = Date.now();
4087
4101
  const turnTimeoutMs = resolveTurnTimeoutMs(opts);
4088
- const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(completionToolCutoffAt(startedAt, opts.deadlineAtMs)) : null;
4102
+ const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(
4103
+ completionToolCutoffAt(startedAt, opts.deadlineAtMs),
4104
+ Date.now,
4105
+ opts.outputContract?.path
4106
+ ) : null;
4089
4107
  let outcome = "failed";
4090
4108
  let outcomeKind = "generic_failed";
4091
4109
  let errorMessage2;
@@ -4294,10 +4312,10 @@ async function runAgent(opts) {
4294
4312
  let timer;
4295
4313
  let next;
4296
4314
  if (turnTimeoutMs > 0) {
4297
- const timeoutPromise = new Promise((resolve23) => {
4315
+ const timeoutPromise = new Promise((resolve24) => {
4298
4316
  timer = setTimeout(() => {
4299
4317
  timedOut = true;
4300
- resolve23({ done: true, value: void 0 });
4318
+ resolve24({ done: true, value: void 0 });
4301
4319
  }, turnTimeoutMs);
4302
4320
  });
4303
4321
  next = await Promise.race([nextPromise, timeoutPromise]);
@@ -4313,7 +4331,7 @@ async function runAgent(opts) {
4313
4331
  try {
4314
4332
  await Promise.race([
4315
4333
  iterator.return(void 0).catch(() => void 0),
4316
- new Promise((resolve23) => setTimeout(resolve23, 1e4).unref())
4334
+ new Promise((resolve24) => setTimeout(resolve24, 1e4).unref())
4317
4335
  ]);
4318
4336
  } catch {
4319
4337
  }
@@ -4520,7 +4538,7 @@ var init_agent = __esm({
4520
4538
 
4521
4539
  // src/agents.ts
4522
4540
  import * as fs13 from "fs";
4523
- import * as path14 from "path";
4541
+ import * as path15 from "path";
4524
4542
  function stripFrontmatter(raw) {
4525
4543
  const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
4526
4544
  return (match ? match[1] : raw).trim();
@@ -4541,7 +4559,7 @@ function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
4541
4559
  throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
4542
4560
  }
4543
4561
  function resolveAgentFile2(cwd, slug, agentsDir = agentsRoot(cwd)) {
4544
- const localPath = path14.resolve(cwd, agentsDir, `${slug}.md`);
4562
+ const localPath = path15.resolve(cwd, agentsDir, `${slug}.md`);
4545
4563
  if (fs13.existsSync(localPath)) return localPath;
4546
4564
  return localPath;
4547
4565
  }
@@ -4575,7 +4593,7 @@ var init_agents = __esm({
4575
4593
 
4576
4594
  // src/task-artifacts.ts
4577
4595
  import fs14 from "fs";
4578
- import path15 from "path";
4596
+ import path16 from "path";
4579
4597
  import posixPath from "path/posix";
4580
4598
  function prepareTaskArtifactsDir(cwd, taskId) {
4581
4599
  const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -4611,14 +4629,14 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
4611
4629
  "handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
4612
4630
  };
4613
4631
  for (const file of TASK_ARTIFACT_FILES) {
4614
- const full = path15.join(artifacts.absDir, file);
4632
+ const full = path16.join(artifacts.absDir, file);
4615
4633
  if (!fs14.existsSync(full)) fs14.writeFileSync(full, defaults[file], "utf8");
4616
4634
  }
4617
4635
  }
4618
4636
  function verifyTaskArtifacts(absDir) {
4619
4637
  const missing = [];
4620
4638
  for (const name of TASK_ARTIFACT_FILES) {
4621
- const full = path15.join(absDir, name);
4639
+ const full = path16.join(absDir, name);
4622
4640
  try {
4623
4641
  const stat = fs14.statSync(full);
4624
4642
  if (!stat.isFile() || stat.size === 0) missing.push(name);
@@ -4636,7 +4654,7 @@ async function persistTaskArtifactsToState(config, _cwd, artifacts) {
4636
4654
  if (hasStateBackendConfig() && tenantId2) {
4637
4655
  const backend = createStateBackendFromEnv();
4638
4656
  for (const file of TASK_ARTIFACT_FILES) {
4639
- const full = path15.join(artifacts.absDir, file);
4657
+ const full = path16.join(artifacts.absDir, file);
4640
4658
  if (!fs14.existsSync(full)) continue;
4641
4659
  const stat = fs14.statSync(full);
4642
4660
  if (!stat.isFile() || stat.size === 0) continue;
@@ -4949,15 +4967,15 @@ function validateWorkflow(value, options = {}) {
4949
4967
  }
4950
4968
  return issues;
4951
4969
  }
4952
- function validateInputBindings(value, path58, issues, declaredInputs) {
4970
+ function validateInputBindings(value, path59, issues, declaredInputs) {
4953
4971
  if (value === void 0) return;
4954
4972
  const bindings = asRecord(value);
4955
4973
  if (!bindings || Object.keys(bindings).length === 0) {
4956
- issue(issues, "invalid_inputs", path58, "workflow step inputs must contain at least one named mapping");
4974
+ issue(issues, "invalid_inputs", path59, "workflow step inputs must contain at least one named mapping");
4957
4975
  return;
4958
4976
  }
4959
4977
  for (const [name, value2] of Object.entries(bindings)) {
4960
- const bindingPath = `${path58}.${name}`;
4978
+ const bindingPath = `${path59}.${name}`;
4961
4979
  if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(name)) {
4962
4980
  issue(issues, "invalid_input_name", bindingPath, `workflow input name ${name} is invalid`);
4963
4981
  }
@@ -4976,7 +4994,7 @@ function validateInputBindings(value, path58, issues, declaredInputs) {
4976
4994
  }
4977
4995
  }
4978
4996
  }
4979
- function validateInputBindingSources(value, path58, issues, capabilitiesByStep, capabilityOutputs) {
4997
+ function validateInputBindingSources(value, path59, issues, capabilitiesByStep, capabilityOutputs) {
4980
4998
  const bindings = asRecord(value);
4981
4999
  if (!bindings) return;
4982
5000
  for (const [name, rawBinding] of Object.entries(bindings)) {
@@ -4989,7 +5007,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
4989
5007
  issue(
4990
5008
  issues,
4991
5009
  "missing_input_step",
4992
- `${path58}.${name}.from`,
5010
+ `${path59}.${name}.from`,
4993
5011
  `workflow input mapping references missing step ${sourceStep ?? "<none>"}`
4994
5012
  );
4995
5013
  continue;
@@ -5000,7 +5018,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
5000
5018
  issue(
5001
5019
  issues,
5002
5020
  "undeclared_step_output",
5003
- `${path58}.${name}.from`,
5021
+ `${path59}.${name}.from`,
5004
5022
  `workflow input mapping reads ${outputPath}, but step ${sourceStep} does not declare it`
5005
5023
  );
5006
5024
  }
@@ -5009,11 +5027,11 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
5009
5027
  function formatWorkflowValidationIssues(issues) {
5010
5028
  return issues.map((entry) => `${entry.path}: ${entry.message}`);
5011
5029
  }
5012
- function validateDataMatch(value, path58, issues, capabilityOutputs) {
5030
+ function validateDataMatch(value, path59, issues, capabilityOutputs) {
5013
5031
  if (value === void 0) return;
5014
5032
  const match = asRecord(value);
5015
5033
  if (!match || Object.keys(match).length === 0) {
5016
- issue(issues, "invalid_condition", path58, "workflow condition must contain at least one match");
5034
+ issue(issues, "invalid_condition", path59, "workflow condition must contain at least one match");
5017
5035
  return;
5018
5036
  }
5019
5037
  for (const [field, expected] of Object.entries(match)) {
@@ -5021,7 +5039,7 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
5021
5039
  issue(
5022
5040
  issues,
5023
5041
  "invalid_data_path",
5024
- `${path58}.${field}`,
5042
+ `${path59}.${field}`,
5025
5043
  `workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
5026
5044
  );
5027
5045
  }
@@ -5029,12 +5047,12 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
5029
5047
  issue(
5030
5048
  issues,
5031
5049
  "undeclared_result_path",
5032
- `${path58}.${field}`,
5050
+ `${path59}.${field}`,
5033
5051
  `workflow condition reads ${field}, but the source capability does not declare it`
5034
5052
  );
5035
5053
  }
5036
5054
  if (!isComparable(expected)) {
5037
- issue(issues, "invalid_condition_value", `${path58}.${field}`, "workflow condition value must be a JSON scalar");
5055
+ issue(issues, "invalid_condition_value", `${path59}.${field}`, "workflow condition value must be a JSON scalar");
5038
5056
  }
5039
5057
  }
5040
5058
  }
@@ -5058,8 +5076,8 @@ function isJsonValue(value) {
5058
5076
  if (!value || typeof value !== "object") return false;
5059
5077
  return Object.values(value).every(isJsonValue);
5060
5078
  }
5061
- function issue(issues, code, path58, message) {
5062
- issues.push({ code, path: path58, message });
5079
+ function issue(issues, code, path59, message) {
5080
+ issues.push({ code, path: path59, message });
5063
5081
  }
5064
5082
  var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SAFE_INPUT_SOURCE, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
5065
5083
  var init_workflowValidation = __esm({
@@ -5093,7 +5111,7 @@ var init_workflowValidation = __esm({
5093
5111
 
5094
5112
  // src/workflowDefinitions.ts
5095
5113
  import * as fs20 from "fs";
5096
- import * as path21 from "path";
5114
+ import * as path22 from "path";
5097
5115
  function isWorkflowDefinitionId(value) {
5098
5116
  return WORKFLOW_ID_PATTERN.test(value);
5099
5117
  }
@@ -5138,8 +5156,8 @@ function readWorkflowDefinition(_config, cwd, id) {
5138
5156
  const root = cwd ?? process.cwd();
5139
5157
  const relativePath = workflowDefinitionPath(id);
5140
5158
  const candidates = [
5141
- path21.join(root, ".kody-engine", "runtime", relativePath),
5142
- path21.join(definitionsRoot(root), relativePath)
5159
+ path22.join(root, ".kody-engine", "runtime", relativePath),
5160
+ path22.join(definitionsRoot(root), relativePath)
5143
5161
  ];
5144
5162
  for (const filePath of candidates) {
5145
5163
  if (!fs20.existsSync(filePath)) continue;
@@ -5151,7 +5169,7 @@ function readWorkflowDefinition(_config, cwd, id) {
5151
5169
  function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
5152
5170
  return {
5153
5171
  slug: id,
5154
- dir: path21.dirname(source),
5172
+ dir: path22.dirname(source),
5155
5173
  profilePath: source,
5156
5174
  bodyPath: source,
5157
5175
  title: workflow.name,
@@ -5752,7 +5770,7 @@ var init_lifecycles = __esm({
5752
5770
  // src/profile.ts
5753
5771
  import { createHash as createHash3 } from "crypto";
5754
5772
  import * as fs24 from "fs";
5755
- import * as path23 from "path";
5773
+ import * as path24 from "path";
5756
5774
  function loadProfile(profilePath) {
5757
5775
  if (!fs24.existsSync(profilePath)) {
5758
5776
  throw new ProfileError(profilePath, "file not found");
@@ -5771,7 +5789,7 @@ function loadProfile(profilePath) {
5771
5789
  const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
5772
5790
  if (unknownKeys.length > 0) {
5773
5791
  process.stderr.write(
5774
- `[kody profile] ${path23.basename(path23.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
5792
+ `[kody profile] ${path24.basename(path24.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
5775
5793
  `
5776
5794
  );
5777
5795
  }
@@ -5781,7 +5799,7 @@ function loadProfile(profilePath) {
5781
5799
  if (!refPath) {
5782
5800
  throw new ProfileError(profilePath, `capability references unknown implementation '${execRef}'`);
5783
5801
  }
5784
- if (path23.resolve(refPath) === path23.resolve(profilePath)) {
5802
+ if (path24.resolve(refPath) === path24.resolve(profilePath)) {
5785
5803
  } else {
5786
5804
  const base = loadProfile(refPath);
5787
5805
  return {
@@ -5879,8 +5897,8 @@ function loadProfile(profilePath) {
5879
5897
  // Phase 5 in-process handoff opt-in. Default false; containers
5880
5898
  // flip to true after end-to-end verification.
5881
5899
  preloadContext: r.preloadContext === true,
5882
- dir: path23.dirname(profilePath),
5883
- promptTemplates: readPromptTemplates(path23.dirname(profilePath))
5900
+ dir: path24.dirname(profilePath),
5901
+ promptTemplates: readPromptTemplates(path24.dirname(profilePath))
5884
5902
  };
5885
5903
  if (lifecycle) {
5886
5904
  applyLifecycle(profile, profilePath);
@@ -5915,19 +5933,19 @@ function loadProfile(profilePath) {
5915
5933
  return profile;
5916
5934
  }
5917
5935
  function compileRuntimeDocument(runtimePath, document) {
5918
- if (path23.basename(runtimePath) !== "runtime.json") return document;
5936
+ if (path24.basename(runtimePath) !== "runtime.json") return document;
5919
5937
  if (document.adapter !== "kody-engine-profile") {
5920
5938
  throw new ProfileError(runtimePath, "unsupported runtime adapter document");
5921
5939
  }
5922
- const implementationDir = path23.dirname(runtimePath);
5923
- const implementation = readJsonObject(path23.join(implementationDir, "definition.json"), "Implementation definition");
5924
- const definitionsRoot2 = path23.dirname(path23.dirname(implementationDir));
5940
+ const implementationDir = path24.dirname(runtimePath);
5941
+ const implementation = readJsonObject(path24.join(implementationDir, "definition.json"), "Implementation definition");
5942
+ const definitionsRoot2 = path24.dirname(path24.dirname(implementationDir));
5925
5943
  const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
5926
5944
  if (typeof capabilityId !== "string" || !capabilityId) {
5927
5945
  throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
5928
5946
  }
5929
5947
  const capability = readJsonObject(
5930
- path23.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
5948
+ path24.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
5931
5949
  "Capability definition"
5932
5950
  );
5933
5951
  const {
@@ -5988,13 +6006,13 @@ function readPromptTemplates(dir) {
5988
6006
  } catch {
5989
6007
  }
5990
6008
  };
5991
- read(path23.join(dir, "prompt.md"));
5992
- read(path23.join(dir, "capability.md"));
5993
- read(path23.join(dir, "capability.md"));
6009
+ read(path24.join(dir, "prompt.md"));
6010
+ read(path24.join(dir, "capability.md"));
6011
+ read(path24.join(dir, "capability.md"));
5994
6012
  try {
5995
- const promptsDir = path23.join(dir, "prompts");
6013
+ const promptsDir = path24.join(dir, "prompts");
5996
6014
  for (const ent of fs24.readdirSync(promptsDir)) {
5997
- if (ent.endsWith(".md")) read(path23.join(promptsDir, ent));
6015
+ if (ent.endsWith(".md")) read(path24.join(promptsDir, ent));
5998
6016
  }
5999
6017
  } catch {
6000
6018
  }
@@ -6772,11 +6790,11 @@ var init_state = __esm({
6772
6790
 
6773
6791
  // src/prompt.ts
6774
6792
  import * as fs25 from "fs";
6775
- import * as path24 from "path";
6793
+ import * as path25 from "path";
6776
6794
  function loadProjectConventions(projectDir) {
6777
6795
  const out = [];
6778
6796
  for (const rel of CONVENTION_FILES) {
6779
- const abs = path24.join(projectDir, rel);
6797
+ const abs = path25.join(projectDir, rel);
6780
6798
  if (!fs25.existsSync(abs)) continue;
6781
6799
  let content;
6782
6800
  try {
@@ -7016,7 +7034,7 @@ __export(loadMemoryContext_exports, {
7016
7034
  loadMemoryContext: () => loadMemoryContext
7017
7035
  });
7018
7036
  import * as fs26 from "fs";
7019
- import * as path25 from "path";
7037
+ import * as path26 from "path";
7020
7038
  function formatBlockFromBackend(docs) {
7021
7039
  const pages = docs.flatMap((record2) => {
7022
7040
  if (!record2.doc || typeof record2.doc !== "object") return [];
@@ -7050,10 +7068,10 @@ function collectPages(memoryAbs) {
7050
7068
  return;
7051
7069
  }
7052
7070
  const fm = raw.match(/^---\s*\n([\s\S]*?)\n---/);
7053
- const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path25.basename(file, ".md");
7071
+ const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path26.basename(file, ".md");
7054
7072
  const updated = fm?.[1]?.match(/^updated:\s*([0-9T:.+\-Z]+)/m)?.[1]?.trim() ?? "";
7055
7073
  out.push({
7056
- relPath: path25.relative(memoryAbs, file),
7074
+ relPath: path26.relative(memoryAbs, file),
7057
7075
  title,
7058
7076
  updated,
7059
7077
  content: raw.length > PER_PAGE_MAX_BYTES ? raw.slice(0, PER_PAGE_MAX_BYTES) + TRUNCATED_SUFFIX2 : raw,
@@ -7127,7 +7145,7 @@ function walkMd(root, visit) {
7127
7145
  }
7128
7146
  for (const name of names) {
7129
7147
  if (name.startsWith(".")) continue;
7130
- const full = path25.join(dir, name);
7148
+ const full = path26.join(dir, name);
7131
7149
  let stat;
7132
7150
  try {
7133
7151
  stat = fs26.statSync(full);
@@ -7165,7 +7183,7 @@ var init_loadMemoryContext = __esm({
7165
7183
  }
7166
7184
  return;
7167
7185
  }
7168
- const memoryAbs = path25.join(ctx.cwd, MEMORY_DIR_RELATIVE);
7186
+ const memoryAbs = path26.join(ctx.cwd, MEMORY_DIR_RELATIVE);
7169
7187
  if (!fs26.existsSync(memoryAbs)) {
7170
7188
  ctx.data.memoryContext = "";
7171
7189
  return;
@@ -7681,7 +7699,7 @@ import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
7681
7699
  import * as fs28 from "fs";
7682
7700
  import * as net from "net";
7683
7701
  import * as os4 from "os";
7684
- import * as path26 from "path";
7702
+ import * as path27 from "path";
7685
7703
  async function checkLitellmHealth(url) {
7686
7704
  try {
7687
7705
  const response = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3e3) });
@@ -7794,10 +7812,10 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
7794
7812
  const spawnProxy = () => {
7795
7813
  const portMatch = activeUrl.match(/:(\d+)/);
7796
7814
  const port = portMatch ? portMatch[1] : "4000";
7797
- const configPath = path26.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
7815
+ const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
7798
7816
  fs28.writeFileSync(configPath, generateLitellmConfigYaml(model));
7799
7817
  const args = ["--config", configPath, "--port", port];
7800
- const nextLogPath = path26.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
7818
+ const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
7801
7819
  const outFd = fs28.openSync(nextLogPath, "w");
7802
7820
  child = spawn4(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
7803
7821
  fs28.closeSync(outFd);
@@ -7887,17 +7905,17 @@ async function nextAvailableLitellmUrl(url) {
7887
7905
  throw new Error(`no free LiteLLM port found after ${startPort}`);
7888
7906
  }
7889
7907
  function canListen(port, host) {
7890
- return new Promise((resolve23) => {
7908
+ return new Promise((resolve24) => {
7891
7909
  const server = net.createServer();
7892
- server.once("error", () => resolve23(false));
7910
+ server.once("error", () => resolve24(false));
7893
7911
  server.once("listening", () => {
7894
- server.close(() => resolve23(true));
7912
+ server.close(() => resolve24(true));
7895
7913
  });
7896
7914
  server.listen(port, host);
7897
7915
  });
7898
7916
  }
7899
7917
  function readDotenvApiKeys(projectDir) {
7900
- const dotenvPath = path26.join(projectDir, ".env");
7918
+ const dotenvPath = path27.join(projectDir, ".env");
7901
7919
  if (!fs28.existsSync(dotenvPath)) return {};
7902
7920
  const result = {};
7903
7921
  for (const rawLine of fs28.readFileSync(dotenvPath, "utf-8").split("\n")) {
@@ -8560,7 +8578,7 @@ var init_pushWithRetry = __esm({
8560
8578
  // src/commit.ts
8561
8579
  import { execFileSync as execFileSync6 } from "child_process";
8562
8580
  import * as fs29 from "fs";
8563
- import * as path27 from "path";
8581
+ import * as path28 from "path";
8564
8582
  function isGitHubYamlPath(filePath) {
8565
8583
  const normalized = filePath.replace(/^\.\/+/, "");
8566
8584
  return normalized.startsWith(".github/") && /\.ya?ml$/i.test(normalized);
@@ -8602,18 +8620,18 @@ function ensureGitIdentity(cwd) {
8602
8620
  }
8603
8621
  function abortUnfinishedGitOps(cwd) {
8604
8622
  const aborted = [];
8605
- const gitDir = path27.join(cwd ?? process.cwd(), ".git");
8623
+ const gitDir = path28.join(cwd ?? process.cwd(), ".git");
8606
8624
  if (!fs29.existsSync(gitDir)) return aborted;
8607
- if (fs29.existsSync(path27.join(gitDir, "MERGE_HEAD"))) {
8625
+ if (fs29.existsSync(path28.join(gitDir, "MERGE_HEAD"))) {
8608
8626
  if (tryGit(["merge", "--abort"], cwd)) aborted.push("merge");
8609
8627
  }
8610
- if (fs29.existsSync(path27.join(gitDir, "CHERRY_PICK_HEAD"))) {
8628
+ if (fs29.existsSync(path28.join(gitDir, "CHERRY_PICK_HEAD"))) {
8611
8629
  if (tryGit(["cherry-pick", "--abort"], cwd)) aborted.push("cherry-pick");
8612
8630
  }
8613
- if (fs29.existsSync(path27.join(gitDir, "REVERT_HEAD"))) {
8631
+ if (fs29.existsSync(path28.join(gitDir, "REVERT_HEAD"))) {
8614
8632
  if (tryGit(["revert", "--abort"], cwd)) aborted.push("revert");
8615
8633
  }
8616
- if (fs29.existsSync(path27.join(gitDir, "rebase-merge")) || fs29.existsSync(path27.join(gitDir, "rebase-apply"))) {
8634
+ if (fs29.existsSync(path28.join(gitDir, "rebase-merge")) || fs29.existsSync(path28.join(gitDir, "rebase-apply"))) {
8617
8635
  if (tryGit(["rebase", "--abort"], cwd)) aborted.push("rebase");
8618
8636
  }
8619
8637
  try {
@@ -8670,7 +8688,7 @@ function normalizeCommitMessage(raw) {
8670
8688
  function commitAndPush(branch, agentMessage, cwd) {
8671
8689
  const allChanged = listChangedFiles(cwd);
8672
8690
  const allowedFiles = allChanged.filter((f) => !isForbiddenPath(f));
8673
- const mergeHeadExists = fs29.existsSync(path27.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
8691
+ const mergeHeadExists = fs29.existsSync(path28.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
8674
8692
  if (allowedFiles.length === 0 && !mergeHeadExists) {
8675
8693
  return { committed: false, pushed: false, sha: "", message: "" };
8676
8694
  }
@@ -9314,9 +9332,9 @@ import * as fs30 from "fs";
9314
9332
  function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
9315
9333
  const logs = goalRunLogs(data);
9316
9334
  const existing = logs[goalId];
9317
- const path58 = existing?.path ?? goalRunLogPath(goalId, data);
9335
+ const path59 = existing?.path ?? goalRunLogPath(goalId, data);
9318
9336
  logs[goalId] = {
9319
- path: path58,
9337
+ path: path59,
9320
9338
  events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
9321
9339
  };
9322
9340
  }
@@ -9764,7 +9782,7 @@ var init_stateStore = __esm({
9764
9782
 
9765
9783
  // src/goal/targetLoopResolution.ts
9766
9784
  import * as fs31 from "fs";
9767
- import * as path28 from "path";
9785
+ import * as path29 from "path";
9768
9786
  async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
9769
9787
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
9770
9788
  assertSafeGoalId(targetId, "loop target");
@@ -9842,7 +9860,7 @@ function goalInstanceTime(state) {
9842
9860
  return Number.isNaN(parsed) ? 0 : parsed;
9843
9861
  }
9844
9862
  function loadGoalTemplate(cwd, targetId) {
9845
- return readJsonObject2(path28.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
9863
+ return readJsonObject2(path29.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
9846
9864
  }
9847
9865
  function readJsonObject2(filePath) {
9848
9866
  if (!fs31.existsSync(filePath)) return null;
@@ -10193,15 +10211,15 @@ var init_backendStateBackend = __esm({
10193
10211
  this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
10194
10212
  }
10195
10213
  async load(slug) {
10196
- const path58 = stateFilePath(this.jobsDir, slug);
10214
+ const path59 = stateFilePath(this.jobsDir, slug);
10197
10215
  const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
10198
10216
  if (!loaded) {
10199
- return { path: path58, handle: null, state: initialStateEnvelope("seed"), created: true };
10217
+ return { path: path59, handle: null, state: initialStateEnvelope("seed"), created: true };
10200
10218
  }
10201
10219
  if (!isStateEnvelope(loaded.doc)) {
10202
10220
  throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
10203
10221
  }
10204
- return { path: path58, handle: loaded.updatedAt, state: loaded.doc, created: false };
10222
+ return { path: path59, handle: loaded.updatedAt, state: loaded.doc, created: false };
10205
10223
  }
10206
10224
  async save(loaded, next) {
10207
10225
  if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
@@ -10222,7 +10240,7 @@ var init_backendStateBackend = __esm({
10222
10240
 
10223
10241
  // src/scripts/jobState/localFileBackend.ts
10224
10242
  import * as fs32 from "fs";
10225
- import * as path29 from "path";
10243
+ import * as path30 from "path";
10226
10244
  function sanitizeKey(s) {
10227
10245
  return s.replace(/[^A-Za-z0-9._-]/g, "-");
10228
10246
  }
@@ -10278,7 +10296,7 @@ var init_localFileBackend = __esm({
10278
10296
  if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
10279
10297
  this.cwd = opts.cwd;
10280
10298
  this.jobsDir = opts.jobsDir;
10281
- this.absDir = path29.resolve(opts.cwd, opts.jobsDir);
10299
+ this.absDir = path30.resolve(opts.cwd, opts.jobsDir);
10282
10300
  this.owner = opts.owner;
10283
10301
  this.repo = opts.repo;
10284
10302
  this.cache = opts.cache ?? defaultCacheAdapter();
@@ -10338,7 +10356,7 @@ var init_localFileBackend = __esm({
10338
10356
  }
10339
10357
  load(slug) {
10340
10358
  const relPath = stateFilePath(this.jobsDir, slug);
10341
- const absPath = path29.resolve(this.cwd, relPath);
10359
+ const absPath = path30.resolve(this.cwd, relPath);
10342
10360
  if (!fs32.existsSync(absPath)) {
10343
10361
  return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
10344
10362
  }
@@ -10359,8 +10377,8 @@ var init_localFileBackend = __esm({
10359
10377
  if (!loaded.created && isStateUnchanged(loaded.state, next)) {
10360
10378
  return false;
10361
10379
  }
10362
- const absPath = path29.resolve(this.cwd, loaded.path);
10363
- fs32.mkdirSync(path29.dirname(absPath), { recursive: true });
10380
+ const absPath = path30.resolve(this.cwd, loaded.path);
10381
+ fs32.mkdirSync(path30.dirname(absPath), { recursive: true });
10364
10382
  const body = `${JSON.stringify(next, null, 2)}
10365
10383
  `;
10366
10384
  const tmpPath = `${absPath}.${process.pid}.tmp`;
@@ -10397,7 +10415,7 @@ var init_jobState = __esm({
10397
10415
  });
10398
10416
 
10399
10417
  // src/scripts/goalCapabilityScheduling.ts
10400
- import * as path30 from "path";
10418
+ import * as path31 from "path";
10401
10419
  function isCapabilityCadenceGoal(goal, extra) {
10402
10420
  return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
10403
10421
  }
@@ -10453,7 +10471,7 @@ function planTargetLoopSchedule(opts) {
10453
10471
  }
10454
10472
  async function planGoalCapabilitySchedule(opts) {
10455
10473
  const jobsDir = opts.jobsDir ?? capabilitiesRoot(opts.cwd);
10456
- const jobsRoot = path30.resolve(opts.cwd, jobsDir);
10474
+ const jobsRoot = path31.resolve(opts.cwd, jobsDir);
10457
10475
  const now = opts.now ?? /* @__PURE__ */ new Date();
10458
10476
  const at = now.toISOString();
10459
10477
  const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
@@ -12176,6 +12194,11 @@ var init_checkCoverageWithRetry = __esm({
12176
12194
  init_coverage();
12177
12195
  init_prompt();
12178
12196
  checkCoverageWithRetry = async (ctx) => {
12197
+ if (ctx.data.capabilityDeliveryPolicy === "checkpoint") {
12198
+ ctx.data.verificationDeferred = true;
12199
+ ctx.data.coverageMisses = [];
12200
+ return;
12201
+ }
12179
12202
  const reqs = ctx.data.coverageRules ?? [];
12180
12203
  if (reqs.length === 0) {
12181
12204
  ctx.data.coverageMisses = [];
@@ -12270,7 +12293,7 @@ var init_classifyByLabel = __esm({
12270
12293
  // src/scripts/commitAndPush.ts
12271
12294
  import { createHash as createHash5 } from "crypto";
12272
12295
  import * as fs33 from "fs";
12273
- import * as path31 from "path";
12296
+ import * as path32 from "path";
12274
12297
  function sentinelPathForStage(cwd, profileName, workflowExecutionKey) {
12275
12298
  const runId = resolveRunId();
12276
12299
  const executionSuffix = typeof workflowExecutionKey === "string" && workflowExecutionKey.length > 0 ? `-${createHash5("sha256").update(workflowExecutionKey).digest("hex").slice(0, 16)}` : "";
@@ -12354,7 +12377,7 @@ var init_commitAndPush = __esm({
12354
12377
  const result = ctx.data.commitResult;
12355
12378
  if (sentinel && result?.committed) {
12356
12379
  try {
12357
- fs33.mkdirSync(path31.dirname(sentinel), { recursive: true });
12380
+ fs33.mkdirSync(path32.dirname(sentinel), { recursive: true });
12358
12381
  fs33.writeFileSync(
12359
12382
  sentinel,
12360
12383
  JSON.stringify(
@@ -12450,7 +12473,7 @@ var init_commitGoalState = __esm({
12450
12473
 
12451
12474
  // src/scripts/composePrompt.ts
12452
12475
  import * as fs34 from "fs";
12453
- import * as path32 from "path";
12476
+ import * as path33 from "path";
12454
12477
  function fenceUntrusted(value) {
12455
12478
  if (value.trim().length === 0) return value;
12456
12479
  const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
@@ -12574,10 +12597,10 @@ var init_composePrompt = __esm({
12574
12597
  const explicit = ctx.data.promptTemplate;
12575
12598
  const mode = ctx.args.mode;
12576
12599
  const candidates = [
12577
- explicit ? path32.join(profile.dir, explicit) : null,
12578
- mode ? path32.join(profile.dir, "prompts", `${mode}.md`) : null,
12579
- path32.join(profile.dir, "prompt.md"),
12580
- path32.join(profile.dir, "capability.md")
12600
+ explicit ? path33.join(profile.dir, explicit) : null,
12601
+ mode ? path33.join(profile.dir, "prompts", `${mode}.md`) : null,
12602
+ path33.join(profile.dir, "prompt.md"),
12603
+ path33.join(profile.dir, "capability.md")
12581
12604
  ].filter(Boolean);
12582
12605
  let templatePath = "";
12583
12606
  let template = "";
@@ -13337,14 +13360,14 @@ var init_deriveQaScopeFromIssue = __esm({
13337
13360
  import { execFileSync as execFileSync9 } from "child_process";
13338
13361
  import * as fs35 from "fs";
13339
13362
  import * as os5 from "os";
13340
- import * as path33 from "path";
13363
+ import * as path34 from "path";
13341
13364
  var diagMcp;
13342
13365
  var init_diagMcp = __esm({
13343
13366
  "src/scripts/diagMcp.ts"() {
13344
13367
  "use strict";
13345
13368
  diagMcp = async (_ctx) => {
13346
13369
  const home = os5.homedir();
13347
- const cacheDir = path33.join(home, ".cache", "ms-playwright");
13370
+ const cacheDir = path34.join(home, ".cache", "ms-playwright");
13348
13371
  let entries = [];
13349
13372
  try {
13350
13373
  entries = fs35.readdirSync(cacheDir);
@@ -13376,12 +13399,12 @@ var init_diagMcp = __esm({
13376
13399
 
13377
13400
  // src/scripts/frameworkDetectors.ts
13378
13401
  import * as fs36 from "fs";
13379
- import * as path34 from "path";
13402
+ import * as path35 from "path";
13380
13403
  function detectFrameworks(cwd) {
13381
13404
  const out = [];
13382
13405
  let deps = {};
13383
13406
  try {
13384
- const pkg = JSON.parse(fs36.readFileSync(path34.join(cwd, "package.json"), "utf-8"));
13407
+ const pkg = JSON.parse(fs36.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
13385
13408
  deps = { ...pkg.dependencies, ...pkg.devDependencies };
13386
13409
  } catch {
13387
13410
  return out;
@@ -13418,14 +13441,14 @@ function detectFrameworks(cwd) {
13418
13441
  }
13419
13442
  function findFile(cwd, candidates) {
13420
13443
  for (const c of candidates) {
13421
- if (fs36.existsSync(path34.join(cwd, c))) return c;
13444
+ if (fs36.existsSync(path35.join(cwd, c))) return c;
13422
13445
  }
13423
13446
  return null;
13424
13447
  }
13425
13448
  function discoverPayloadCollections(cwd) {
13426
13449
  const out = [];
13427
13450
  for (const dir of COLLECTION_DIRS) {
13428
- const full = path34.join(cwd, dir);
13451
+ const full = path35.join(cwd, dir);
13429
13452
  if (!fs36.existsSync(full)) continue;
13430
13453
  let files;
13431
13454
  try {
@@ -13435,7 +13458,7 @@ function discoverPayloadCollections(cwd) {
13435
13458
  }
13436
13459
  for (const file of files) {
13437
13460
  try {
13438
- const filePath = path34.join(full, file);
13461
+ const filePath = path35.join(full, file);
13439
13462
  const content = fs36.readFileSync(filePath, "utf-8").slice(0, 1e4);
13440
13463
  const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
13441
13464
  if (!slugMatch) continue;
@@ -13450,7 +13473,7 @@ function discoverPayloadCollections(cwd) {
13450
13473
  out.push({
13451
13474
  name,
13452
13475
  slug,
13453
- filePath: path34.relative(cwd, filePath),
13476
+ filePath: path35.relative(cwd, filePath),
13454
13477
  fields: fields.slice(0, 20),
13455
13478
  hasAdmin
13456
13479
  });
@@ -13463,7 +13486,7 @@ function discoverPayloadCollections(cwd) {
13463
13486
  function discoverAdminComponents(cwd, collections) {
13464
13487
  const out = [];
13465
13488
  for (const dir of ADMIN_COMPONENT_DIRS) {
13466
- const full = path34.join(cwd, dir);
13489
+ const full = path35.join(cwd, dir);
13467
13490
  if (!fs36.existsSync(full)) continue;
13468
13491
  let entries;
13469
13492
  try {
@@ -13472,19 +13495,19 @@ function discoverAdminComponents(cwd, collections) {
13472
13495
  continue;
13473
13496
  }
13474
13497
  for (const entry of entries) {
13475
- const entryPath = path34.join(full, entry.name);
13498
+ const entryPath = path35.join(full, entry.name);
13476
13499
  let name;
13477
13500
  let filePath;
13478
13501
  if (entry.isDirectory()) {
13479
13502
  const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
13480
- (f) => fs36.existsSync(path34.join(entryPath, f))
13503
+ (f) => fs36.existsSync(path35.join(entryPath, f))
13481
13504
  );
13482
13505
  if (!indexFile) continue;
13483
13506
  name = entry.name;
13484
- filePath = path34.relative(cwd, path34.join(entryPath, indexFile));
13507
+ filePath = path35.relative(cwd, path35.join(entryPath, indexFile));
13485
13508
  } else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
13486
13509
  name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
13487
- filePath = path34.relative(cwd, entryPath);
13510
+ filePath = path35.relative(cwd, entryPath);
13488
13511
  } else {
13489
13512
  continue;
13490
13513
  }
@@ -13492,7 +13515,7 @@ function discoverAdminComponents(cwd, collections) {
13492
13515
  if (collections) {
13493
13516
  for (const col of collections) {
13494
13517
  try {
13495
- const colContent = fs36.readFileSync(path34.join(cwd, col.filePath), "utf-8");
13518
+ const colContent = fs36.readFileSync(path35.join(cwd, col.filePath), "utf-8");
13496
13519
  if (colContent.includes(name)) {
13497
13520
  usedInCollection = col.slug;
13498
13521
  break;
@@ -13510,7 +13533,7 @@ function scanApiRoutes(cwd) {
13510
13533
  const out = [];
13511
13534
  const appDirs = ["src/app", "app"];
13512
13535
  for (const appDir of appDirs) {
13513
- const apiDir = path34.join(cwd, appDir, "api");
13536
+ const apiDir = path35.join(cwd, appDir, "api");
13514
13537
  if (!fs36.existsSync(apiDir)) continue;
13515
13538
  walkApiRoutes(apiDir, "/api", cwd, out);
13516
13539
  break;
@@ -13527,7 +13550,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13527
13550
  const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
13528
13551
  if (routeFile) {
13529
13552
  try {
13530
- const content = fs36.readFileSync(path34.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
13553
+ const content = fs36.readFileSync(path35.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
13531
13554
  const methods = HTTP_METHODS.filter(
13532
13555
  (m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
13533
13556
  );
@@ -13535,7 +13558,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13535
13558
  out.push({
13536
13559
  path: prefix,
13537
13560
  methods,
13538
- filePath: path34.relative(cwd, path34.join(dir, routeFile.name))
13561
+ filePath: path35.relative(cwd, path35.join(dir, routeFile.name))
13539
13562
  });
13540
13563
  }
13541
13564
  } catch {
@@ -13546,7 +13569,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13546
13569
  if (entry.name === "node_modules" || entry.name === ".next") continue;
13547
13570
  let segment = entry.name;
13548
13571
  if (segment.startsWith("(") && segment.endsWith(")")) {
13549
- walkApiRoutes(path34.join(dir, entry.name), prefix, cwd, out);
13572
+ walkApiRoutes(path35.join(dir, entry.name), prefix, cwd, out);
13550
13573
  continue;
13551
13574
  }
13552
13575
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
@@ -13554,13 +13577,13 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13554
13577
  } else if (segment.startsWith("[") && segment.endsWith("]")) {
13555
13578
  segment = `:${segment.slice(1, -1)}`;
13556
13579
  }
13557
- walkApiRoutes(path34.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
13580
+ walkApiRoutes(path35.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
13558
13581
  }
13559
13582
  }
13560
13583
  function scanEnvVars(cwd) {
13561
13584
  const candidates = [".env.example", ".env.local.example", ".env.template"];
13562
13585
  for (const envFile of candidates) {
13563
- const envPath = path34.join(cwd, envFile);
13586
+ const envPath = path35.join(cwd, envFile);
13564
13587
  if (!fs36.existsSync(envPath)) continue;
13565
13588
  try {
13566
13589
  const content = fs36.readFileSync(envPath, "utf-8");
@@ -13609,7 +13632,7 @@ var init_frameworkDetectors = __esm({
13609
13632
 
13610
13633
  // src/scripts/discoverQaContext.ts
13611
13634
  import * as fs37 from "fs";
13612
- import * as path35 from "path";
13635
+ import * as path36 from "path";
13613
13636
  function runQaDiscovery(cwd) {
13614
13637
  const out = {
13615
13638
  routes: [],
@@ -13640,9 +13663,9 @@ function runQaDiscovery(cwd) {
13640
13663
  }
13641
13664
  function detectDevServer(cwd, out) {
13642
13665
  try {
13643
- const pkg = JSON.parse(fs37.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
13666
+ const pkg = JSON.parse(fs37.readFileSync(path36.join(cwd, "package.json"), "utf-8"));
13644
13667
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13645
- const pm = fs37.existsSync(path35.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs37.existsSync(path35.join(cwd, "yarn.lock")) ? "yarn" : fs37.existsSync(path35.join(cwd, "bun.lockb")) ? "bun" : "npm";
13668
+ const pm = fs37.existsSync(path36.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs37.existsSync(path36.join(cwd, "yarn.lock")) ? "yarn" : fs37.existsSync(path36.join(cwd, "bun.lockb")) ? "bun" : "npm";
13646
13669
  if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
13647
13670
  if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
13648
13671
  else if (allDeps.vite) out.devPort = 5173;
@@ -13652,7 +13675,7 @@ function detectDevServer(cwd, out) {
13652
13675
  function scanFrontendRoutes(cwd, out) {
13653
13676
  const appDirs = ["src/app", "app"];
13654
13677
  for (const appDir of appDirs) {
13655
- const full = path35.join(cwd, appDir);
13678
+ const full = path36.join(cwd, appDir);
13656
13679
  if (!fs37.existsSync(full)) continue;
13657
13680
  walkFrontendRoutes(full, "", out);
13658
13681
  break;
@@ -13678,7 +13701,7 @@ function walkFrontendRoutes(dir, prefix, out) {
13678
13701
  if (entry.name === "node_modules" || entry.name === ".next") continue;
13679
13702
  let segment = entry.name;
13680
13703
  if (segment.startsWith("(") && segment.endsWith(")")) {
13681
- walkFrontendRoutes(path35.join(dir, entry.name), prefix, out);
13704
+ walkFrontendRoutes(path36.join(dir, entry.name), prefix, out);
13682
13705
  continue;
13683
13706
  }
13684
13707
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
@@ -13686,7 +13709,7 @@ function walkFrontendRoutes(dir, prefix, out) {
13686
13709
  } else if (segment.startsWith("[") && segment.endsWith("]")) {
13687
13710
  segment = `:${segment.slice(1, -1)}`;
13688
13711
  }
13689
- walkFrontendRoutes(path35.join(dir, entry.name), `${prefix}/${segment}`, out);
13712
+ walkFrontendRoutes(path36.join(dir, entry.name), `${prefix}/${segment}`, out);
13690
13713
  }
13691
13714
  }
13692
13715
  function detectAuthFiles(cwd, out) {
@@ -13703,13 +13726,13 @@ function detectAuthFiles(cwd, out) {
13703
13726
  "src/app/api/oauth"
13704
13727
  ];
13705
13728
  for (const c of candidates) {
13706
- if (fs37.existsSync(path35.join(cwd, c))) out.authFiles.push(c);
13729
+ if (fs37.existsSync(path36.join(cwd, c))) out.authFiles.push(c);
13707
13730
  }
13708
13731
  }
13709
13732
  function detectRoles(cwd, out) {
13710
13733
  const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
13711
13734
  for (const rp of rolePaths) {
13712
- const dir = path35.join(cwd, rp);
13735
+ const dir = path36.join(cwd, rp);
13713
13736
  if (!fs37.existsSync(dir)) continue;
13714
13737
  let files;
13715
13738
  try {
@@ -13719,7 +13742,7 @@ function detectRoles(cwd, out) {
13719
13742
  }
13720
13743
  for (const f of files) {
13721
13744
  try {
13722
- const content = fs37.readFileSync(path35.join(dir, f), "utf-8").slice(0, 5e3);
13745
+ const content = fs37.readFileSync(path36.join(dir, f), "utf-8").slice(0, 5e3);
13723
13746
  const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
13724
13747
  if (roleMatches) {
13725
13748
  for (const m of roleMatches) {
@@ -13981,7 +14004,7 @@ var init_dispatchClassified = __esm({
13981
14004
 
13982
14005
  // src/loopDefinitions.ts
13983
14006
  import * as fs38 from "fs";
13984
- import * as path36 from "path";
14007
+ import * as path37 from "path";
13985
14008
  function normalizeLoopDefinition(value) {
13986
14009
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
13987
14010
  const raw = value;
@@ -14008,7 +14031,7 @@ function readLoopDefinition(cwd, id) {
14008
14031
  if (!ID.test(id)) return null;
14009
14032
  const roots = loopRoots(cwd);
14010
14033
  for (const root of roots) {
14011
- const filePath = path36.join(root, "loops", id, "loop.json");
14034
+ const filePath = path37.join(root, "loops", id, "loop.json");
14012
14035
  if (!fs38.existsSync(filePath)) continue;
14013
14036
  try {
14014
14037
  const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
@@ -14021,7 +14044,7 @@ function readLoopDefinition(cwd, id) {
14021
14044
  }
14022
14045
  }
14023
14046
  process.stderr.write(
14024
- `[kody] Loop not found: ${id} (${roots.map((root) => path36.join(root, "loops", id, "loop.json")).join(", ")})
14047
+ `[kody] Loop not found: ${id} (${roots.map((root) => path37.join(root, "loops", id, "loop.json")).join(", ")})
14025
14048
  `
14026
14049
  );
14027
14050
  return null;
@@ -14030,11 +14053,11 @@ function listLoopDefinitions(cwd) {
14030
14053
  const roots = loopRoots(cwd);
14031
14054
  const byId = /* @__PURE__ */ new Map();
14032
14055
  for (const root of roots.reverse()) {
14033
- const loopsDir = path36.join(root, "loops");
14056
+ const loopsDir = path37.join(root, "loops");
14034
14057
  if (!fs38.existsSync(loopsDir)) continue;
14035
14058
  for (const id of fs38.readdirSync(loopsDir).sort()) {
14036
14059
  if (!ID.test(id)) continue;
14037
- const filePath = path36.join(loopsDir, id, "loop.json");
14060
+ const filePath = path37.join(loopsDir, id, "loop.json");
14038
14061
  if (!fs38.existsSync(filePath)) continue;
14039
14062
  try {
14040
14063
  const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
@@ -14049,8 +14072,8 @@ function listLoopDefinitions(cwd) {
14049
14072
  }
14050
14073
  function loopRoots(cwd) {
14051
14074
  return [
14052
- path36.join(cwd, ".kody-engine", "runtime"),
14053
- path36.join(cwd, ".kody-engine", "definitions"),
14075
+ path37.join(cwd, ".kody-engine", "runtime"),
14076
+ path37.join(cwd, ".kody-engine", "definitions"),
14054
14077
  definitionsRoot(cwd)
14055
14078
  ].filter((root, index, roots) => roots.indexOf(root) === index);
14056
14079
  }
@@ -14618,6 +14641,9 @@ function setOutcome(ctx, outcome) {
14618
14641
  ctx.output.prUrl = outcome.url;
14619
14642
  }
14620
14643
  }
14644
+ function deliveryCheckpointReason(data) {
14645
+ return data.capabilityDeliveryPolicy === "checkpoint" ? "Repository-wide verification is deferred to pull request CI." : "";
14646
+ }
14621
14647
  function computeFailureReason(ctx) {
14622
14648
  const expectedTests = collectExpectedTests(ctx.data.coverageMisses);
14623
14649
  if (expectedTests.length > 0) return `missing tests: ${expectedTests.join(", ")}`;
@@ -14687,7 +14713,8 @@ var init_ensurePr = __esm({
14687
14713
  setOutcome(ctx, { kind: "skipped", reason: "no branch context (ctx.data.branch missing)" });
14688
14714
  return;
14689
14715
  }
14690
- const failureReason = computeFailureReason(ctx);
14716
+ const checkpointReason = deliveryCheckpointReason(ctx.data);
14717
+ const failureReason = computeFailureReason(ctx) || checkpointReason;
14691
14718
  const isFailure = failureReason.length > 0;
14692
14719
  const changedFiles = ctx.data.changedFiles ?? [];
14693
14720
  const issue2 = ctx.data.issue;
@@ -15329,11 +15356,11 @@ var init_fixFlow = __esm({
15329
15356
 
15330
15357
  // src/workflow-template.ts
15331
15358
  import * as fs39 from "fs";
15332
- import * as path37 from "path";
15359
+ import * as path38 from "path";
15333
15360
  import { fileURLToPath } from "url";
15334
15361
  function loadKodyWorkflowTemplate() {
15335
- const here = path37.dirname(fileURLToPath(import.meta.url));
15336
- const candidates = [path37.resolve(here, "../templates/kody.yml"), path37.resolve(here, "../../templates/kody.yml")];
15362
+ const here = path38.dirname(fileURLToPath(import.meta.url));
15363
+ const candidates = [path38.resolve(here, "../templates/kody.yml"), path38.resolve(here, "../../templates/kody.yml")];
15337
15364
  const source = candidates.find((candidate) => fs39.existsSync(candidate));
15338
15365
  if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
15339
15366
  return fs39.readFileSync(source, "utf8");
@@ -15349,11 +15376,11 @@ var init_workflow_template = __esm({
15349
15376
  // src/scripts/initFlow.ts
15350
15377
  import { execFileSync as execFileSync14 } from "child_process";
15351
15378
  import * as fs40 from "fs";
15352
- import * as path38 from "path";
15379
+ import * as path39 from "path";
15353
15380
  function detectPackageManager(cwd) {
15354
- if (fs40.existsSync(path38.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
15355
- if (fs40.existsSync(path38.join(cwd, "yarn.lock"))) return "yarn";
15356
- if (fs40.existsSync(path38.join(cwd, "bun.lockb"))) return "bun";
15381
+ if (fs40.existsSync(path39.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
15382
+ if (fs40.existsSync(path39.join(cwd, "yarn.lock"))) return "yarn";
15383
+ if (fs40.existsSync(path39.join(cwd, "bun.lockb"))) return "bun";
15357
15384
  return "npm";
15358
15385
  }
15359
15386
  function qualityCommandsFor(pm) {
@@ -15425,7 +15452,7 @@ function performInit(cwd, force) {
15425
15452
  const pm = detectPackageManager(cwd);
15426
15453
  const ownerRepo = detectOwnerRepo(cwd);
15427
15454
  const defaultBranch = defaultBranchFromGit(cwd);
15428
- const configPath = path38.join(cwd, "kody.config.json");
15455
+ const configPath = path39.join(cwd, "kody.config.json");
15429
15456
  if (fs40.existsSync(configPath) && !force) {
15430
15457
  skipped.push("kody.config.json");
15431
15458
  } else {
@@ -15434,8 +15461,8 @@ function performInit(cwd, force) {
15434
15461
  `);
15435
15462
  wrote.push("kody.config.json");
15436
15463
  }
15437
- const workflowDir = path38.join(cwd, ".github", "workflows");
15438
- const workflowPath = path38.join(workflowDir, "kody.yml");
15464
+ const workflowDir = path39.join(cwd, ".github", "workflows");
15465
+ const workflowPath = path39.join(workflowDir, "kody.yml");
15439
15466
  if (fs40.existsSync(workflowPath) && !force) {
15440
15467
  skipped.push(".github/workflows/kody.yml");
15441
15468
  } else {
@@ -15630,13 +15657,13 @@ var init_loadCapabilityState = __esm({
15630
15657
  function isCompanyIntentId(value) {
15631
15658
  return SLUG_RE2.test(value);
15632
15659
  }
15633
- function normalizeCompanyIntent(path58, raw) {
15660
+ function normalizeCompanyIntent(path59, raw) {
15634
15661
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
15635
- throw new Error(`${path58}: intent must be JSON object`);
15662
+ throw new Error(`${path59}: intent must be JSON object`);
15636
15663
  }
15637
15664
  const input = raw;
15638
15665
  const id = stringField4(input.id);
15639
- if (!id || !isCompanyIntentId(id)) throw new Error(`${path58}: invalid intent id`);
15666
+ if (!id || !isCompanyIntentId(id)) throw new Error(`${path59}: invalid intent id`);
15640
15667
  const createdAt = stringField4(input.createdAt) || nowIso();
15641
15668
  const updatedAt = stringField4(input.updatedAt) || createdAt;
15642
15669
  const description = stringField4(input.description);
@@ -15798,7 +15825,7 @@ function retryDelaysMs() {
15798
15825
  }
15799
15826
  function sleep(ms) {
15800
15827
  if (ms <= 0) return Promise.resolve();
15801
- return new Promise((resolve23) => setTimeout(resolve23, ms));
15828
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
15802
15829
  }
15803
15830
  async function fetchGoalStateWithRetry(config, goalId, cwd) {
15804
15831
  let state = await fetchGoalStateAsync(config, goalId, cwd);
@@ -15928,7 +15955,7 @@ var init_loadIssueStateComment = __esm({
15928
15955
 
15929
15956
  // src/scripts/loadJobFromFile.ts
15930
15957
  import * as fs42 from "fs";
15931
- import * as path39 from "path";
15958
+ import * as path40 from "path";
15932
15959
  function parseJobFile(raw, slug) {
15933
15960
  let stripped = raw;
15934
15961
  if (stripped.startsWith("---\n")) {
@@ -15967,10 +15994,10 @@ var init_loadJobFromFile = __esm({
15967
15994
  if (!slug) {
15968
15995
  throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
15969
15996
  }
15970
- const capability = resolveCapabilityFolder(slug, path39.resolve(ctx.cwd, jobsDir));
15997
+ const capability = resolveCapabilityFolder(slug, path40.resolve(ctx.cwd, jobsDir));
15971
15998
  if (!capability) {
15972
15999
  throw new Error(
15973
- `loadJobFromFile: capability folder not found or incomplete: ${path39.resolve(ctx.cwd, jobsDir, slug)}`
16000
+ `loadJobFromFile: capability folder not found or incomplete: ${path40.resolve(ctx.cwd, jobsDir, slug)}`
15974
16001
  );
15975
16002
  }
15976
16003
  const { title, body, config } = capability;
@@ -16066,9 +16093,9 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
16066
16093
 
16067
16094
  // src/scripts/kodyVariables.ts
16068
16095
  import * as fs43 from "fs";
16069
- import * as path40 from "path";
16096
+ import * as path41 from "path";
16070
16097
  function readKodyVariables(cwd) {
16071
- const full = path40.join(cwd, KODY_VARIABLES_REL_PATH);
16098
+ const full = path41.join(cwd, KODY_VARIABLES_REL_PATH);
16072
16099
  let raw;
16073
16100
  try {
16074
16101
  raw = fs43.readFileSync(full, "utf-8");
@@ -16097,7 +16124,7 @@ var init_kodyVariables = __esm({
16097
16124
 
16098
16125
  // src/scripts/loadQaContext.ts
16099
16126
  import * as fs44 from "fs";
16100
- import * as path41 from "path";
16127
+ import * as path42 from "path";
16101
16128
  function parseSlugList(value) {
16102
16129
  const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
16103
16130
  return inner.split(",").map(
@@ -16126,7 +16153,7 @@ function readProfileAgents(raw) {
16126
16153
  return { agent: agent ?? legacy ?? ["kody"], body };
16127
16154
  }
16128
16155
  function readProfile(cwd) {
16129
- const dir = path41.join(cwd, CONTEXT_DIR_REL_PATH);
16156
+ const dir = path42.join(cwd, CONTEXT_DIR_REL_PATH);
16130
16157
  if (!fs44.existsSync(dir)) return "";
16131
16158
  let entries;
16132
16159
  try {
@@ -16137,7 +16164,7 @@ function readProfile(cwd) {
16137
16164
  const blocks = [];
16138
16165
  for (const file of entries) {
16139
16166
  try {
16140
- const raw = fs44.readFileSync(path41.join(dir, file), "utf-8");
16167
+ const raw = fs44.readFileSync(path42.join(dir, file), "utf-8");
16141
16168
  const { agent, body } = readProfileAgents(raw);
16142
16169
  if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
16143
16170
  blocks.push(`## ${file}
@@ -16189,7 +16216,7 @@ var init_loadQaContext = __esm({
16189
16216
  import { randomUUID as randomUUID2 } from "crypto";
16190
16217
  import * as fs45 from "fs";
16191
16218
  import * as os6 from "os";
16192
- import * as path42 from "path";
16219
+ import * as path43 from "path";
16193
16220
  function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
16194
16221
  const subagentFiles = toolFiles.flatMap((file) => {
16195
16222
  const match = /^agents\/([a-z][a-z0-9-]{0,63})\.md$/.exec(file);
@@ -16202,7 +16229,7 @@ function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
16202
16229
  profile.subagentTemplates = {
16203
16230
  ...profile.subagentTemplates ?? {},
16204
16231
  ...Object.fromEntries(
16205
- subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(path42.join(toolRoot, file), "utf-8")])
16232
+ subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(path43.join(toolRoot, file), "utf-8")])
16206
16233
  )
16207
16234
  };
16208
16235
  if (!profile.claudeCode.tools.includes("Agent")) {
@@ -16247,10 +16274,10 @@ function listFiles(root) {
16247
16274
  const files = [];
16248
16275
  const visit = (dir) => {
16249
16276
  for (const entry of fs45.readdirSync(dir, { withFileTypes: true })) {
16250
- const absolute = path42.join(dir, entry.name);
16277
+ const absolute = path43.join(dir, entry.name);
16251
16278
  if (entry.isSymbolicLink()) continue;
16252
16279
  if (entry.isDirectory()) visit(absolute);
16253
- else if (entry.isFile()) files.push(path42.relative(root, absolute));
16280
+ else if (entry.isFile()) files.push(path43.relative(root, absolute));
16254
16281
  }
16255
16282
  };
16256
16283
  visit(root);
@@ -16273,8 +16300,8 @@ var init_loadSimpleCapability = __esm({
16273
16300
  if (!capability) {
16274
16301
  throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
16275
16302
  }
16276
- const toolRoot = path42.join(capability.dir, "tools");
16277
- const skillRoot = path42.join(capability.dir, "skills");
16303
+ const toolRoot = path43.join(capability.dir, "tools");
16304
+ const skillRoot = path43.join(capability.dir, "skills");
16278
16305
  const toolFiles = listFiles(toolRoot);
16279
16306
  const skillFiles = listFiles(skillRoot);
16280
16307
  const parsedInput = parseInput(ctx.args.input);
@@ -16285,6 +16312,9 @@ var init_loadSimpleCapability = __esm({
16285
16312
  ctx.data.jobCapability = slug;
16286
16313
  ctx.data.capabilityInput = input;
16287
16314
  ctx.data.capabilityExecution = capability.contract?.execution ?? "agent";
16315
+ if (capability.contract?.deliveryPolicy) {
16316
+ ctx.data.capabilityDeliveryPolicy = capability.contract.deliveryPolicy;
16317
+ }
16288
16318
  if (capability.contract?.requirements) {
16289
16319
  ctx.data.capabilityRequirements = capability.contract.requirements;
16290
16320
  }
@@ -16299,14 +16329,14 @@ var init_loadSimpleCapability = __esm({
16299
16329
  }
16300
16330
  if (requiredSubagents.length > 0) ctx.data.requiredSubagents = requiredSubagents;
16301
16331
  if (capability.contract?.execution === "script") {
16302
- ctx.data.capabilityScriptPath = path42.join(capability.dir, "tools", "run.sh");
16332
+ ctx.data.capabilityScriptPath = path43.join(capability.dir, "tools", "run.sh");
16303
16333
  ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
16304
16334
  ctx.data.capabilityScriptTimeoutMs = capability.contract.timeoutMs;
16305
16335
  }
16306
16336
  if (capability.config.outputSchema) {
16307
16337
  ctx.data.capabilityOutputSchema = capability.config.outputSchema;
16308
16338
  }
16309
- const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ? path42.join(os6.tmpdir(), `kody-capability-output-${randomUUID2()}.json`) : void 0;
16339
+ const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ? path43.join(os6.tmpdir(), `kody-capability-output-${randomUUID2()}.json`) : void 0;
16310
16340
  if (outputPath) ctx.data.capabilityOutputPath = outputPath;
16311
16341
  ctx.data.capabilityEnvironment = {
16312
16342
  ...capabilityInputEnvironment(input),
@@ -16329,7 +16359,7 @@ var init_loadSimpleCapability = __esm({
16329
16359
  ...skillFiles.flatMap((file) => [
16330
16360
  `### ${file}`,
16331
16361
  "",
16332
- fs45.readFileSync(path42.join(skillRoot, file), "utf-8"),
16362
+ fs45.readFileSync(path43.join(skillRoot, file), "utf-8"),
16333
16363
  ""
16334
16364
  ])
16335
16365
  ] : [],
@@ -16338,7 +16368,7 @@ var init_loadSimpleCapability = __esm({
16338
16368
  "## Tools",
16339
16369
  "",
16340
16370
  "Inspect or run these capability-owned files when needed:",
16341
- ...toolFiles.map((file) => `- ${path42.join(toolRoot, file)}`)
16371
+ ...toolFiles.map((file) => `- ${path43.join(toolRoot, file)}`)
16342
16372
  ] : [],
16343
16373
  "",
16344
16374
  ...capability.config.outputSchema ? [
@@ -16370,7 +16400,7 @@ var init_loadSimpleCapability = __esm({
16370
16400
 
16371
16401
  // src/taskContext.ts
16372
16402
  import * as fs46 from "fs";
16373
- import * as path43 from "path";
16403
+ import * as path44 from "path";
16374
16404
  function buildTaskContext(args) {
16375
16405
  return {
16376
16406
  schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
@@ -16387,7 +16417,7 @@ function persistTaskContext(cwd, ctx) {
16387
16417
  try {
16388
16418
  const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
16389
16419
  fs46.mkdirSync(dir, { recursive: true });
16390
- const file = path43.join(dir, "task-context.json");
16420
+ const file = path44.join(dir, "task-context.json");
16391
16421
  fs46.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
16392
16422
  `);
16393
16423
  return file;
@@ -16815,19 +16845,19 @@ function parseAgencyModelProposal(raw) {
16815
16845
  function normalizeBundleFiles(bundle) {
16816
16846
  const seen = /* @__PURE__ */ new Set();
16817
16847
  return bundle.files.map((file, index) => {
16818
- const path58 = file.path.replace(/^\/+/, "");
16819
- const parts = path58.split("/");
16820
- if (!path58 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
16848
+ const path59 = file.path.replace(/^\/+/, "");
16849
+ const parts = path59.split("/");
16850
+ if (!path59 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
16821
16851
  throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
16822
16852
  }
16823
16853
  if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
16824
- path58
16854
+ path59
16825
16855
  )) {
16826
16856
  throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
16827
16857
  }
16828
- if (seen.has(path58)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path58}`);
16829
- seen.add(path58);
16830
- return { path: path58, content: file.content.replace(/\r\n?/g, "\n") };
16858
+ if (seen.has(path59)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path59}`);
16859
+ seen.add(path59);
16860
+ return { path: path59, content: file.content.replace(/\r\n?/g, "\n") };
16831
16861
  });
16832
16862
  }
16833
16863
  function buildProposalId(issueNumber, bundle, sourceLabel) {
@@ -17871,7 +17901,8 @@ var init_postIssueComment = __esm({
17871
17901
  githubRepo: ctx.config.github?.repo
17872
17902
  });
17873
17903
  postWith(targetType, targetNumber, msg, ctx.cwd);
17874
- if (!isFailure) {
17904
+ const prIsDraft = (prResult?.kind === "created" || prResult?.kind === "updated") && prResult.draft === true;
17905
+ if (!isFailure && !prIsDraft) {
17875
17906
  markPrReadyForReview(ctx, prResult);
17876
17907
  }
17877
17908
  let exitCode = 0;
@@ -17939,7 +17970,7 @@ var init_postResearchComment = __esm({
17939
17970
  // src/scripts/prepareBrowserAuth.ts
17940
17971
  import * as fs48 from "fs";
17941
17972
  import * as os7 from "os";
17942
- import * as path44 from "path";
17973
+ import * as path45 from "path";
17943
17974
  function appendAuthMessage(ctx, message) {
17944
17975
  const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
17945
17976
  ctx.data.qaAuthBlock = current ? `${current}
@@ -17978,9 +18009,9 @@ async function githubJson(url, token) {
17978
18009
  return await response.json();
17979
18010
  }
17980
18011
  function writeKodyStorageState(input) {
17981
- const directory = fs48.mkdtempSync(path44.join(os7.tmpdir(), "kody-browser-auth-"));
18012
+ const directory = fs48.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
17982
18013
  fs48.chmodSync(directory, 448);
17983
- const file = path44.join(directory, "storage-state.json");
18014
+ const file = path45.join(directory, "storage-state.json");
17984
18015
  const now = Date.now();
17985
18016
  const repoEntry = {
17986
18017
  repoUrl: input.repoUrl,
@@ -18239,7 +18270,7 @@ var init_prepareCapabilityDelivery = __esm({
18239
18270
 
18240
18271
  // src/scripts/prepareSimpleCapabilityRuntime.ts
18241
18272
  import { isIP } from "net";
18242
- import * as path45 from "path";
18273
+ import * as path46 from "path";
18243
18274
  function requirementsFrom(ctx) {
18244
18275
  const raw = ctx.data.capabilityRequirements;
18245
18276
  return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -18283,7 +18314,7 @@ function browserRuntime(ctx, requirements) {
18283
18314
  "--allowed-origins",
18284
18315
  origin,
18285
18316
  "--output-dir",
18286
- path45.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
18317
+ path46.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
18287
18318
  ]
18288
18319
  };
18289
18320
  }
@@ -18648,9 +18679,9 @@ function latestResult(raw, agentResult) {
18648
18679
  function recordField4(value) {
18649
18680
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
18650
18681
  }
18651
- function resolveDotted(root, path58) {
18652
- if (!path58) return void 0;
18653
- return path58.split(".").reduce((value, key) => recordField4(value)?.[key], root);
18682
+ function resolveDotted(root, path59) {
18683
+ if (!path59) return void 0;
18684
+ return path59.split(".").reduce((value, key) => recordField4(value)?.[key], root);
18654
18685
  }
18655
18686
  function stringValue5(value) {
18656
18687
  return typeof value === "string" && value.trim() ? value.trim() : null;
@@ -19492,7 +19523,7 @@ var init_previewBuildHelpers = __esm({
19492
19523
  // src/scripts/previewBuildRun.ts
19493
19524
  import { spawn as spawn5 } from "child_process";
19494
19525
  async function runCmd(cmd, args, opts = {}) {
19495
- await new Promise((resolve23, reject) => {
19526
+ await new Promise((resolve24, reject) => {
19496
19527
  const child = spawn5(cmd, args, {
19497
19528
  cwd: opts.cwd,
19498
19529
  env: { ...process.env, ...opts.env ?? {} },
@@ -19504,7 +19535,7 @@ async function runCmd(cmd, args, opts = {}) {
19504
19535
  }
19505
19536
  child.on("error", reject);
19506
19537
  child.on("close", (code) => {
19507
- if (code === 0) resolve23();
19538
+ if (code === 0) resolve24();
19508
19539
  else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
19509
19540
  });
19510
19541
  });
@@ -19576,12 +19607,12 @@ fi
19576
19607
 
19577
19608
  // src/scripts/runPreviewBuild.ts
19578
19609
  import { copyFile, writeFile } from "fs/promises";
19579
- import * as path46 from "path";
19610
+ import * as path47 from "path";
19580
19611
  import { fileURLToPath as fileURLToPath2 } from "url";
19581
19612
  function bundledDockerfilePath(mode) {
19582
- const here = path46.dirname(fileURLToPath2(import.meta.url));
19613
+ const here = path47.dirname(fileURLToPath2(import.meta.url));
19583
19614
  const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
19584
- return path46.join(here, "preview-build-templates", file);
19615
+ return path47.join(here, "preview-build-templates", file);
19585
19616
  }
19586
19617
  function required(name) {
19587
19618
  const v = (process.env[name] ?? "").trim();
@@ -19816,10 +19847,10 @@ var init_runPreviewBuild = __esm({
19816
19847
  console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
19817
19848
  if (Object.keys(buildEnv).length > 0) {
19818
19849
  const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
19819
- await writeFile(path46.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
19850
+ await writeFile(path47.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
19820
19851
  `, "utf8");
19821
19852
  }
19822
- const consumerDockerfile = path46.join(ctx.cwd, "Dockerfile.preview");
19853
+ const consumerDockerfile = path47.join(ctx.cwd, "Dockerfile.preview");
19823
19854
  const { stat } = await import("fs/promises");
19824
19855
  let hasConsumerDockerfile = false;
19825
19856
  try {
@@ -20004,7 +20035,7 @@ var init_tickShellRunner = __esm({
20004
20035
 
20005
20036
  // src/scripts/runScheduledImplementationTick.ts
20006
20037
  import * as fs49 from "fs";
20007
- import * as path47 from "path";
20038
+ import * as path48 from "path";
20008
20039
  var runScheduledImplementationTick;
20009
20040
  var init_runScheduledImplementationTick = __esm({
20010
20041
  "src/scripts/runScheduledImplementationTick.ts"() {
@@ -20025,13 +20056,13 @@ var init_runScheduledImplementationTick = __esm({
20025
20056
  ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
20026
20057
  return;
20027
20058
  }
20028
- const capability = resolveCapabilityFolder(slug, path47.resolve(ctx.cwd, jobsDir));
20059
+ const capability = resolveCapabilityFolder(slug, path48.resolve(ctx.cwd, jobsDir));
20029
20060
  if (!capability) {
20030
20061
  ctx.output.exitCode = 99;
20031
20062
  ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
20032
20063
  return;
20033
20064
  }
20034
- const shellPath = path47.join(profile.dir, shell);
20065
+ const shellPath = path48.join(profile.dir, shell);
20035
20066
  if (!fs49.existsSync(shellPath)) {
20036
20067
  ctx.output.exitCode = 99;
20037
20068
  ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
@@ -20150,7 +20181,7 @@ var init_runSimpleCapabilityScript = __esm({
20150
20181
 
20151
20182
  // src/scripts/runTickScript.ts
20152
20183
  import * as fs51 from "fs";
20153
- import * as path48 from "path";
20184
+ import * as path49 from "path";
20154
20185
  var runTickScript;
20155
20186
  var init_runTickScript = __esm({
20156
20187
  "src/scripts/runTickScript.ts"() {
@@ -20170,10 +20201,10 @@ var init_runTickScript = __esm({
20170
20201
  ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
20171
20202
  return;
20172
20203
  }
20173
- const capability = readCapabilityFolder(path48.resolve(ctx.cwd, jobsDir), slug);
20204
+ const capability = readCapabilityFolder(path49.resolve(ctx.cwd, jobsDir), slug);
20174
20205
  if (!capability) {
20175
20206
  ctx.output.exitCode = 99;
20176
- ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path48.resolve(ctx.cwd, jobsDir, slug)}`;
20207
+ ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path49.resolve(ctx.cwd, jobsDir, slug)}`;
20177
20208
  return;
20178
20209
  }
20179
20210
  const tickScript = capability.config.tickScript;
@@ -20182,7 +20213,7 @@ var init_runTickScript = __esm({
20182
20213
  ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
20183
20214
  return;
20184
20215
  }
20185
- const scriptPath = path48.isAbsolute(tickScript) ? tickScript : path48.join(ctx.cwd, tickScript);
20216
+ const scriptPath = path49.isAbsolute(tickScript) ? tickScript : path49.join(ctx.cwd, tickScript);
20186
20217
  if (!fs51.existsSync(scriptPath)) {
20187
20218
  ctx.output.exitCode = 99;
20188
20219
  ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
@@ -20465,7 +20496,7 @@ var init_syncFlow = __esm({
20465
20496
  });
20466
20497
 
20467
20498
  // src/scripts/validateAgencyModelProposal.ts
20468
- import * as path49 from "path";
20499
+ import * as path50 from "path";
20469
20500
  function validateModelBundle(bundle, expectedKind, options = {}) {
20470
20501
  const failures = [];
20471
20502
  validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
@@ -20783,7 +20814,7 @@ var init_validateAgencyModelProposal = __esm({
20783
20814
  const bundle = parseAgencyModelProposal(raw);
20784
20815
  const expectedKind = readExpectedModelKind(args);
20785
20816
  const failures = validateModelBundle(bundle, expectedKind, {
20786
- capabilityRoot: path49.join(ctx.cwd, ".kody", "capabilities")
20817
+ capabilityRoot: path50.join(ctx.cwd, ".kody", "capabilities")
20787
20818
  });
20788
20819
  if (failures.length > 0) {
20789
20820
  throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
@@ -20846,7 +20877,7 @@ function stripAnsi2(s) {
20846
20877
  return s.replace(ANSI_RE2, "");
20847
20878
  }
20848
20879
  function runCommand2(command, cwd) {
20849
- return new Promise((resolve23) => {
20880
+ return new Promise((resolve24) => {
20850
20881
  const child = spawn6(command, {
20851
20882
  cwd,
20852
20883
  shell: true,
@@ -20873,11 +20904,11 @@ function runCommand2(command, cwd) {
20873
20904
  }, TEST_TIMEOUT_MS);
20874
20905
  child.on("exit", (code) => {
20875
20906
  clearTimeout(timer);
20876
- resolve23({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
20907
+ resolve24({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
20877
20908
  });
20878
20909
  child.on("error", (err) => {
20879
20910
  clearTimeout(timer);
20880
- resolve23({ exitCode: -1, output: err.message });
20911
+ resolve24({ exitCode: -1, output: err.message });
20881
20912
  });
20882
20913
  });
20883
20914
  }
@@ -20996,6 +21027,12 @@ var init_verifyWithRetry = __esm({
20996
21027
  init_prompt();
20997
21028
  init_verify();
20998
21029
  verifyWithRetry = async (ctx) => {
21030
+ if (ctx.data.capabilityDeliveryPolicy === "checkpoint") {
21031
+ ctx.data.verificationDeferred = true;
21032
+ delete ctx.data.verifyOk;
21033
+ delete ctx.data.verifyReason;
21034
+ return;
21035
+ }
20999
21036
  await runVerify(ctx);
21000
21037
  if (ctx.data.verifyOk !== false) return;
21001
21038
  if (ctx.abortSignal?.aborted) {
@@ -21291,21 +21328,21 @@ function lineStream(stream) {
21291
21328
  tryDeliver();
21292
21329
  });
21293
21330
  return {
21294
- next: (timeoutMs) => new Promise((resolve23) => {
21331
+ next: (timeoutMs) => new Promise((resolve24) => {
21295
21332
  if (queue.length > 0) {
21296
- resolve23(queue.shift());
21333
+ resolve24(queue.shift());
21297
21334
  return;
21298
21335
  }
21299
21336
  if (ended) {
21300
- resolve23(null);
21337
+ resolve24(null);
21301
21338
  return;
21302
21339
  }
21303
- waiter = resolve23;
21340
+ waiter = resolve24;
21304
21341
  const t = setTimeout(
21305
21342
  () => {
21306
- if (waiter === resolve23) {
21343
+ if (waiter === resolve24) {
21307
21344
  waiter = null;
21308
- resolve23(null);
21345
+ resolve24(null);
21309
21346
  }
21310
21347
  },
21311
21348
  Math.max(0, timeoutMs)
@@ -21707,15 +21744,15 @@ var init_scripts = __esm({
21707
21744
 
21708
21745
  // src/stateWorkspace.ts
21709
21746
  import * as fs53 from "fs";
21710
- import * as path50 from "path";
21747
+ import * as path51 from "path";
21711
21748
  function tenantId(config) {
21712
21749
  const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
21713
21750
  const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
21714
21751
  return owner && repo ? `${owner}/${repo}` : null;
21715
21752
  }
21716
21753
  function writeRuntimeFile(cwd, relativePath, content) {
21717
- const target = path50.join(cwd, RUNTIME_ROOT, relativePath);
21718
- fs53.mkdirSync(path50.dirname(target), { recursive: true });
21754
+ const target = path51.join(cwd, RUNTIME_ROOT, relativePath);
21755
+ fs53.mkdirSync(path51.dirname(target), { recursive: true });
21719
21756
  fs53.writeFileSync(target, content, "utf8");
21720
21757
  }
21721
21758
  function record(value) {
@@ -21781,10 +21818,10 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
21781
21818
  throw new Error("Kody backend access is required for runtime workspace documents");
21782
21819
  return;
21783
21820
  }
21784
- const key = `${path50.resolve(cwd)}|${tenant}`;
21821
+ const key = `${path51.resolve(cwd)}|${tenant}`;
21785
21822
  if (hydratedWorkspaces.has(key)) return;
21786
21823
  const backend = backendOverride ?? createStateBackendFromEnv();
21787
- const root = path50.join(cwd, RUNTIME_ROOT);
21824
+ const root = path51.join(cwd, RUNTIME_ROOT);
21788
21825
  fs53.rmSync(root, { recursive: true, force: true });
21789
21826
  await Promise.all([
21790
21827
  hydratePrefix(backend, tenant, cwd, "context:"),
@@ -21801,7 +21838,7 @@ var init_stateWorkspace = __esm({
21801
21838
  "src/stateWorkspace.ts"() {
21802
21839
  "use strict";
21803
21840
  init_state_backend();
21804
- RUNTIME_ROOT = path50.join(".kody-engine", "runtime");
21841
+ RUNTIME_ROOT = path51.join(".kody-engine", "runtime");
21805
21842
  hydratedWorkspaces = /* @__PURE__ */ new Set();
21806
21843
  }
21807
21844
  });
@@ -21874,7 +21911,7 @@ var init_tools = __esm({
21874
21911
  import { spawn as spawn8 } from "child_process";
21875
21912
  import * as fs54 from "fs";
21876
21913
  import * as os8 from "os";
21877
- import * as path51 from "path";
21914
+ import * as path52 from "path";
21878
21915
  function isMutatingPostflight(scriptName) {
21879
21916
  return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
21880
21917
  }
@@ -22131,7 +22168,7 @@ async function runImplementation(profileName, input) {
22131
22168
  const reason = input.abortController.signal.reason;
22132
22169
  throw reason instanceof Error ? reason : new Error("agent invocation aborted");
22133
22170
  }
22134
- const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path51.isAbsolute(p) ? p : path51.resolve(profile.dir, p)).filter((p) => p.length > 0);
22171
+ const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path52.isAbsolute(p) ? p : path52.resolve(profile.dir, p)).filter((p) => p.length > 0);
22135
22172
  const syntheticPath = ctx.data.syntheticPluginPath;
22136
22173
  const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
22137
22174
  const agents = loadSubagents(profile);
@@ -22613,13 +22650,13 @@ function clearStampedLifecycleLabels(profile, ctx) {
22613
22650
  function resolveProfilePath(profileName, cwd = process.cwd()) {
22614
22651
  const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
22615
22652
  if (found) return found;
22616
- const here = path51.dirname(new URL(import.meta.url).pathname);
22653
+ const here = path52.dirname(new URL(import.meta.url).pathname);
22617
22654
  const candidates = [
22618
- path51.join(here, "implementations", profileName, "profile.json"),
22655
+ path52.join(here, "implementations", profileName, "profile.json"),
22619
22656
  // same-dir sibling (dev)
22620
- path51.join(here, "..", "implementations", profileName, "profile.json"),
22657
+ path52.join(here, "..", "implementations", profileName, "profile.json"),
22621
22658
  // up one (prod: dist/bin → dist/implementations)
22622
- path51.join(here, "..", "src", "implementations", profileName, "profile.json")
22659
+ path52.join(here, "..", "src", "implementations", profileName, "profile.json")
22623
22660
  // fallback
22624
22661
  ];
22625
22662
  for (const c of candidates) {
@@ -22738,7 +22775,7 @@ function resolveShellTimeoutMs(entry) {
22738
22775
  }
22739
22776
  async function runShellEntry(entry, ctx, profile) {
22740
22777
  const shellName = entry.shell;
22741
- const shellPath = path51.join(profile.dir, shellName);
22778
+ const shellPath = path52.join(profile.dir, shellName);
22742
22779
  if (!fs54.existsSync(shellPath)) {
22743
22780
  ctx.skipAgent = true;
22744
22781
  ctx.output.exitCode = 99;
@@ -22746,7 +22783,7 @@ async function runShellEntry(entry, ctx, profile) {
22746
22783
  return;
22747
22784
  }
22748
22785
  const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
22749
- const outputFile = path51.join(
22786
+ const outputFile = path52.join(
22750
22787
  os8.tmpdir(),
22751
22788
  `kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
22752
22789
  );
@@ -22776,14 +22813,14 @@ async function runShellEntry(entry, ctx, profile) {
22776
22813
  let killTimer;
22777
22814
  let escalateTimer;
22778
22815
  const result = await new Promise(
22779
- (resolve23) => {
22816
+ (resolve24) => {
22780
22817
  let settled = false;
22781
22818
  const settle = (code, signal, spawnErr) => {
22782
22819
  if (settled) return;
22783
22820
  settled = true;
22784
22821
  if (killTimer) clearTimeout(killTimer);
22785
22822
  if (escalateTimer) clearTimeout(escalateTimer);
22786
- resolve23({ code, signal, spawnErr });
22823
+ resolve24({ code, signal, spawnErr });
22787
22824
  };
22788
22825
  child.on("error", (err) => settle(null, null, err));
22789
22826
  child.on("close", (code, signal) => settle(code, signal));
@@ -23828,11 +23865,11 @@ function exhaustedWorkflowTransitions(step, data, counts) {
23828
23865
  }
23829
23866
  function workflowResultConditionPaths(transitions) {
23830
23867
  return transitions.flatMap(
23831
- (transition) => Object.keys(transition.when ?? {}).filter((path58) => path58.startsWith("result."))
23868
+ (transition) => Object.keys(transition.when ?? {}).filter((path59) => path59.startsWith("result."))
23832
23869
  );
23833
23870
  }
23834
23871
  function conditionMatches(condition, context) {
23835
- return Object.entries(condition).every(([path58, expected]) => valueMatches(resolveDottedPath2(context, path58), expected));
23872
+ return Object.entries(condition).every(([path59, expected]) => valueMatches(resolveDottedPath2(context, path59), expected));
23836
23873
  }
23837
23874
  function withWorkflowBoundaryEval(capability, result) {
23838
23875
  const capabilityKind = capability.config.capabilityKind;
@@ -24307,7 +24344,7 @@ function translateOpenAISseToBrain(opts) {
24307
24344
 
24308
24345
  // src/servers/brain-serve.ts
24309
24346
  import { createServer as createServer2 } from "http";
24310
- import * as path54 from "path";
24347
+ import * as path55 from "path";
24311
24348
 
24312
24349
  // src/chat/loop.ts
24313
24350
  init_agent();
@@ -24316,12 +24353,12 @@ init_config();
24316
24353
  init_registry();
24317
24354
  init_task_artifacts();
24318
24355
  import * as fs18 from "fs";
24319
- import * as path19 from "path";
24356
+ import * as path20 from "path";
24320
24357
 
24321
24358
  // src/chat/attachments.ts
24322
24359
  init_runtimePaths();
24323
24360
  import * as fs15 from "fs";
24324
- import * as path16 from "path";
24361
+ import * as path17 from "path";
24325
24362
  var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
24326
24363
  var EXT_BY_MIME = {
24327
24364
  "image/png": "png",
@@ -24357,7 +24394,7 @@ function prepareAttachments(turns, cwd, sessionId) {
24357
24394
  fs15.mkdirSync(dir, { recursive: true });
24358
24395
  dirEnsured = true;
24359
24396
  }
24360
- const filePath = path16.join(dir, `${imageCounter}.${extFor(mime)}`);
24397
+ const filePath = path17.join(dir, `${imageCounter}.${extFor(mime)}`);
24361
24398
  fs15.writeFileSync(filePath, Buffer.from(data, "base64"));
24362
24399
  imageCounter += 1;
24363
24400
  imagePaths.push(filePath);
@@ -24376,7 +24413,7 @@ function prepareAttachments(turns, cwd, sessionId) {
24376
24413
  // src/chat/codex-app-server.ts
24377
24414
  import { spawn as spawn3 } from "child_process";
24378
24415
  import * as fs16 from "fs";
24379
- import * as path17 from "path";
24416
+ import * as path18 from "path";
24380
24417
  import { createInterface } from "readline";
24381
24418
  function codexThreadStartParams(args) {
24382
24419
  return {
@@ -24461,9 +24498,9 @@ var CodexAppServerClient = class {
24461
24498
  await this.request("thread/resume", { threadId });
24462
24499
  }
24463
24500
  async runTurn(args) {
24464
- await new Promise((resolve23, reject) => {
24501
+ await new Promise((resolve24, reject) => {
24465
24502
  this.process.turnWaiters.set(args.threadId, {
24466
- resolve: resolve23,
24503
+ resolve: resolve24,
24467
24504
  reject,
24468
24505
  onNotification: args.onNotification,
24469
24506
  queue: Promise.resolve()
@@ -24480,8 +24517,8 @@ var CodexAppServerClient = class {
24480
24517
  }
24481
24518
  request(method, params) {
24482
24519
  const id = this.process.nextId++;
24483
- return new Promise((resolve23, reject) => {
24484
- this.process.pending.set(id, { resolve: resolve23, reject });
24520
+ return new Promise((resolve24, reject) => {
24521
+ this.process.pending.set(id, { resolve: resolve24, reject });
24485
24522
  this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
24486
24523
  `);
24487
24524
  });
@@ -24547,7 +24584,7 @@ var CodexAppServerClient = class {
24547
24584
  };
24548
24585
  var clients = /* @__PURE__ */ new Map();
24549
24586
  function threadMapPath(cwd) {
24550
- return path17.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
24587
+ return path18.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
24551
24588
  }
24552
24589
  function readThreadMap(cwd) {
24553
24590
  try {
@@ -24564,7 +24601,7 @@ function readThreadMap(cwd) {
24564
24601
  }
24565
24602
  function writeThreadMap(cwd, map) {
24566
24603
  const file = threadMapPath(cwd);
24567
- fs16.mkdirSync(path17.dirname(file), { recursive: true });
24604
+ fs16.mkdirSync(path18.dirname(file), { recursive: true });
24568
24605
  fs16.writeFileSync(file, `${JSON.stringify(map, null, 2)}
24569
24606
  `);
24570
24607
  }
@@ -24656,7 +24693,7 @@ async function runCodexChatTurn(args) {
24656
24693
 
24657
24694
  // src/chat/events.ts
24658
24695
  import * as fs17 from "fs";
24659
- import * as path18 from "path";
24696
+ import * as path19 from "path";
24660
24697
  import posixPath2 from "path/posix";
24661
24698
  var BackendEventSink = class {
24662
24699
  constructor(append, tenantId2, sessionId) {
@@ -24672,7 +24709,7 @@ var BackendEventSink = class {
24672
24709
  }
24673
24710
  };
24674
24711
  function eventsFilePath(cwd, sessionId) {
24675
- return path18.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
24712
+ return path19.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
24676
24713
  }
24677
24714
  var FileSink = class {
24678
24715
  constructor(file) {
@@ -24680,7 +24717,7 @@ var FileSink = class {
24680
24717
  }
24681
24718
  file;
24682
24719
  async emit(event) {
24683
- fs17.mkdirSync(path18.dirname(this.file), { recursive: true });
24720
+ fs17.mkdirSync(path19.dirname(this.file), { recursive: true });
24684
24721
  fs17.appendFileSync(this.file, `${JSON.stringify(event)}
24685
24722
  `);
24686
24723
  }
@@ -25068,7 +25105,7 @@ async function runChatTurn(opts) {
25068
25105
  quiet: opts.quiet,
25069
25106
  additionalDirectories: [
25070
25107
  taskArtifactsPaths.absDir,
25071
- ...Array.from(new Set(imagePaths.map((p2) => path19.dirname(p2))))
25108
+ ...Array.from(new Set(imagePaths.map((p2) => path20.dirname(p2))))
25072
25109
  ],
25073
25110
  systemPromptAppend: systemPrompt,
25074
25111
  ...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
@@ -25256,7 +25293,7 @@ async function emit(sink, type, sessionId, suffix, payload) {
25256
25293
  var MEMORY_INDEX_REL = ".kody-engine/runtime/memory/INDEX.md";
25257
25294
  var MAX_INDEX_BYTES = 8e3;
25258
25295
  function readMemoryIndexBlock(cwd) {
25259
- const indexPath = path19.join(cwd, MEMORY_INDEX_REL);
25296
+ const indexPath = path20.join(cwd, MEMORY_INDEX_REL);
25260
25297
  let raw;
25261
25298
  try {
25262
25299
  raw = fs18.readFileSync(indexPath, "utf-8");
@@ -25279,7 +25316,7 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
25279
25316
  var CONTEXT_DIR_REL = ".kody-engine/runtime/context";
25280
25317
  var MAX_CONTEXT_BYTES = 12e3;
25281
25318
  function readContextBlock(cwd) {
25282
- const dir = path19.join(cwd, CONTEXT_DIR_REL);
25319
+ const dir = path20.join(cwd, CONTEXT_DIR_REL);
25283
25320
  let files;
25284
25321
  try {
25285
25322
  files = fs18.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
@@ -25289,7 +25326,7 @@ function readContextBlock(cwd) {
25289
25326
  const sections = [];
25290
25327
  for (const file of files) {
25291
25328
  try {
25292
- const content = fs18.readFileSync(path19.join(dir, file), "utf-8").trim();
25329
+ const content = fs18.readFileSync(path20.join(dir, file), "utf-8").trim();
25293
25330
  if (content) sections.push(`### ${file.replace(/\.md$/, "")}
25294
25331
 
25295
25332
  ${content}`);
@@ -25315,7 +25352,7 @@ var SYSTEM_PROMPT_OVERRIDE_REL = ".kody-engine/runtime/system-prompt.md";
25315
25352
  function readSystemPromptOverride(cwd) {
25316
25353
  let raw;
25317
25354
  try {
25318
- raw = fs18.readFileSync(path19.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
25355
+ raw = fs18.readFileSync(path20.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
25319
25356
  } catch {
25320
25357
  return null;
25321
25358
  }
@@ -25323,7 +25360,7 @@ function readSystemPromptOverride(cwd) {
25323
25360
  return trimmed.length > 0 ? trimmed : null;
25324
25361
  }
25325
25362
  function readInstructionsBlock(cwd) {
25326
- const instructionsPath = path19.join(cwd, INSTRUCTIONS_REL);
25363
+ const instructionsPath = path20.join(cwd, INSTRUCTIONS_REL);
25327
25364
  let raw;
25328
25365
  try {
25329
25366
  raw = fs18.readFileSync(instructionsPath, "utf-8");
@@ -25361,10 +25398,10 @@ function resolveBrainDriver(runtime) {
25361
25398
 
25362
25399
  // src/chat/session.ts
25363
25400
  import * as fs19 from "fs";
25364
- import * as path20 from "path";
25401
+ import * as path21 from "path";
25365
25402
  import posixPath3 from "path/posix";
25366
25403
  function sessionFilePath(cwd, sessionId) {
25367
- return path20.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
25404
+ return path21.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
25368
25405
  }
25369
25406
  function readSession(file) {
25370
25407
  if (!fs19.existsSync(file)) return [];
@@ -25392,7 +25429,7 @@ init_state_backend();
25392
25429
  init_workflowDefinitions();
25393
25430
  import { createHash as createHash2 } from "crypto";
25394
25431
  import * as fs21 from "fs";
25395
- import * as path22 from "path";
25432
+ import * as path23 from "path";
25396
25433
  var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
25397
25434
  var REPOSITORY_OWNED_NAMESPACES = ["loops"];
25398
25435
  function assertSafeDefinitionPath(filePath) {
@@ -25424,8 +25461,8 @@ function verifyDefinition(definition) {
25424
25461
  }
25425
25462
  function writeBundle(root, bundle) {
25426
25463
  for (const [filePath, contents] of Object.entries(bundle.files)) {
25427
- const target = path22.join(root, filePath);
25428
- fs21.mkdirSync(path22.dirname(target), { recursive: true });
25464
+ const target = path23.join(root, filePath);
25465
+ fs21.mkdirSync(path23.dirname(target), { recursive: true });
25429
25466
  fs21.writeFileSync(target, contents, "utf8");
25430
25467
  }
25431
25468
  }
@@ -25434,22 +25471,22 @@ function writeDefinition(root, kind, definition) {
25434
25471
  if (kind === "agent") {
25435
25472
  const raw = bundle.files["agent.md"];
25436
25473
  if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
25437
- fs21.writeFileSync(path22.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25474
+ fs21.writeFileSync(path23.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25438
25475
  return;
25439
25476
  }
25440
25477
  if (kind === "goal") {
25441
- writeBundle(path22.join(root, "goals", definition.slug), bundle);
25478
+ writeBundle(path23.join(root, "goals", definition.slug), bundle);
25442
25479
  return;
25443
25480
  }
25444
25481
  if (kind === "implementation") {
25445
- writeBundle(path22.join(root, "implementations", definition.slug), bundle);
25482
+ writeBundle(path23.join(root, "implementations", definition.slug), bundle);
25446
25483
  return;
25447
25484
  }
25448
25485
  if (kind === "asset") {
25449
- writeBundle(path22.join(root, "shared"), bundle);
25486
+ writeBundle(path23.join(root, "shared"), bundle);
25450
25487
  return;
25451
25488
  }
25452
- writeBundle(path22.join(root, "capabilities", definition.slug), bundle);
25489
+ writeBundle(path23.join(root, "capabilities", definition.slug), bundle);
25453
25490
  }
25454
25491
  function writeWorkflow(root, document) {
25455
25492
  const workflow = normalizeWorkflowDefinition(document.definition);
@@ -25457,28 +25494,28 @@ function writeWorkflow(root, document) {
25457
25494
  const contents = `${JSON.stringify(workflow, null, 2)}
25458
25495
  `;
25459
25496
  const bundle = { schemaVersion: 1, files: { "workflow.json": contents } };
25460
- const target = path22.join(root, workflowDefinitionPath(document.workflowId));
25461
- fs21.mkdirSync(path22.dirname(target), { recursive: true });
25497
+ const target = path23.join(root, workflowDefinitionPath(document.workflowId));
25498
+ fs21.mkdirSync(path23.dirname(target), { recursive: true });
25462
25499
  fs21.writeFileSync(target, contents, "utf8");
25463
25500
  return definitionVersion(bundle);
25464
25501
  }
25465
25502
  function preserveRepositoryDefinitions(root, staging) {
25466
25503
  for (const namespace of REPOSITORY_OWNED_NAMESPACES) {
25467
- const source = path22.join(root, namespace);
25504
+ const source = path23.join(root, namespace);
25468
25505
  if (!fs21.existsSync(source)) continue;
25469
- fs21.cpSync(source, path22.join(staging, namespace), { recursive: true });
25506
+ fs21.cpSync(source, path23.join(staging, namespace), { recursive: true });
25470
25507
  }
25471
25508
  }
25472
25509
  async function hydrateDefinitions(options) {
25473
- const root = path22.join(options.cwd, ".kody-engine", "definitions");
25510
+ const root = path23.join(options.cwd, ".kody-engine", "definitions");
25474
25511
  const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
25475
25512
  fs21.rmSync(staging, { recursive: true, force: true });
25476
- fs21.mkdirSync(path22.join(staging, "agents"), { recursive: true });
25477
- fs21.mkdirSync(path22.join(staging, "capabilities"), { recursive: true });
25478
- fs21.mkdirSync(path22.join(staging, "goals"), { recursive: true });
25479
- fs21.mkdirSync(path22.join(staging, "implementations"), { recursive: true });
25480
- fs21.mkdirSync(path22.join(staging, "shared"), { recursive: true });
25481
- fs21.mkdirSync(path22.join(staging, "workflows"), { recursive: true });
25513
+ fs21.mkdirSync(path23.join(staging, "agents"), { recursive: true });
25514
+ fs21.mkdirSync(path23.join(staging, "capabilities"), { recursive: true });
25515
+ fs21.mkdirSync(path23.join(staging, "goals"), { recursive: true });
25516
+ fs21.mkdirSync(path23.join(staging, "implementations"), { recursive: true });
25517
+ fs21.mkdirSync(path23.join(staging, "shared"), { recursive: true });
25518
+ fs21.mkdirSync(path23.join(staging, "workflows"), { recursive: true });
25482
25519
  try {
25483
25520
  const [capabilities, agents, goals, implementations, assets, workflows] = await Promise.all([
25484
25521
  options.backend.listDefinitions(options.tenantId, "capability"),
@@ -25519,7 +25556,7 @@ async function hydrateDefinitions(options) {
25519
25556
  hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
25520
25557
  versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
25521
25558
  };
25522
- fs21.writeFileSync(path22.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25559
+ fs21.writeFileSync(path23.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25523
25560
  `, "utf8");
25524
25561
  fs21.rmSync(root, { recursive: true, force: true });
25525
25562
  fs21.renameSync(staging, root);
@@ -25548,7 +25585,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
25548
25585
  // src/kody-cli.ts
25549
25586
  import { execFileSync as execFileSync24 } from "child_process";
25550
25587
  import * as fs55 from "fs";
25551
- import * as path52 from "path";
25588
+ import * as path53 from "path";
25552
25589
 
25553
25590
  // src/app-auth.ts
25554
25591
  import { createSign } from "crypto";
@@ -26350,9 +26387,9 @@ async function resolveAuthToken(env = process.env) {
26350
26387
  return void 0;
26351
26388
  }
26352
26389
  function detectPackageManager2(cwd) {
26353
- if (fs55.existsSync(path52.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
26354
- if (fs55.existsSync(path52.join(cwd, "yarn.lock"))) return "yarn";
26355
- if (fs55.existsSync(path52.join(cwd, "bun.lockb"))) return "bun";
26390
+ if (fs55.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
26391
+ if (fs55.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
26392
+ if (fs55.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
26356
26393
  return "npm";
26357
26394
  }
26358
26395
  function shouldChainScheduledWatch(match) {
@@ -26485,7 +26522,7 @@ async function runCi(argv) {
26485
26522
  return 0;
26486
26523
  }
26487
26524
  const args = parseCiArgs(argv);
26488
- const cwd = args.cwd ? path52.resolve(args.cwd) : process.cwd();
26525
+ const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
26489
26526
  try {
26490
26527
  const n = unpackAllSecrets();
26491
26528
  if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
@@ -26969,7 +27006,7 @@ init_repoWorkspace();
26969
27006
  // src/scripts/brainTurnLog.ts
26970
27007
  init_runtimePaths();
26971
27008
  import * as fs56 from "fs";
26972
- import * as path53 from "path";
27009
+ import * as path54 from "path";
26973
27010
  import posixPath4 from "path/posix";
26974
27011
  var live = /* @__PURE__ */ new Map();
26975
27012
  function brainEventsFilePath(dir, chatId) {
@@ -27016,7 +27053,7 @@ function beginTurn(dir, chatId) {
27016
27053
  };
27017
27054
  live.set(chatId, state);
27018
27055
  const p = brainEventsFilePath(dir, chatId);
27019
- fs56.mkdirSync(path53.dirname(p), { recursive: true });
27056
+ fs56.mkdirSync(path54.dirname(p), { recursive: true });
27020
27057
  return (event) => {
27021
27058
  state.seq += 1;
27022
27059
  const rec = { seq: state.seq, turn, ts: Date.now(), event };
@@ -27154,17 +27191,17 @@ function authOk(req, expected) {
27154
27191
  return false;
27155
27192
  }
27156
27193
  function readJsonBody(req) {
27157
- return new Promise((resolve23, reject) => {
27194
+ return new Promise((resolve24, reject) => {
27158
27195
  const chunks = [];
27159
27196
  req.on("data", (c) => chunks.push(c));
27160
27197
  req.on("end", () => {
27161
27198
  const raw = Buffer.concat(chunks).toString("utf-8");
27162
27199
  if (!raw.trim()) {
27163
- resolve23({});
27200
+ resolve24({});
27164
27201
  return;
27165
27202
  }
27166
27203
  try {
27167
- resolve23(JSON.parse(raw));
27204
+ resolve24(JSON.parse(raw));
27168
27205
  } catch (err) {
27169
27206
  reject(err instanceof Error ? err : new Error(String(err)));
27170
27207
  }
@@ -27456,7 +27493,7 @@ function buildServer(opts) {
27456
27493
  const runTurn = opts.runTurn ?? runChatTurn;
27457
27494
  const createStore = opts.createStore ?? createSessionStore;
27458
27495
  const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
27459
- const reposRoot = opts.reposRoot ?? path54.join(path54.dirname(path54.resolve(opts.cwd)), "repos");
27496
+ const reposRoot = opts.reposRoot ?? path55.join(path55.dirname(path55.resolve(opts.cwd)), "repos");
27460
27497
  return createServer2(async (req, res) => {
27461
27498
  if (!req.method || !req.url) {
27462
27499
  sendJson(res, 400, { error: "bad request" });
@@ -27537,11 +27574,11 @@ async function brainServe(opts) {
27537
27574
  litellmUrl,
27538
27575
  driver
27539
27576
  });
27540
- await new Promise((resolve23) => {
27577
+ await new Promise((resolve24) => {
27541
27578
  server.listen(port, "0.0.0.0", () => {
27542
27579
  process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
27543
27580
  `);
27544
- resolve23();
27581
+ resolve24();
27545
27582
  });
27546
27583
  });
27547
27584
  const shutdown = (signal) => {
@@ -27796,14 +27833,14 @@ async function startBrainProxy(opts) {
27796
27833
  const { httpServer, handler } = buildBrainProxy(opts);
27797
27834
  const port = opts.port ?? 0;
27798
27835
  const host = opts.host ?? "127.0.0.1";
27799
- await new Promise((resolve23) => httpServer.listen(port, host, () => resolve23()));
27836
+ await new Promise((resolve24) => httpServer.listen(port, host, () => resolve24()));
27800
27837
  const addr = httpServer.address();
27801
27838
  return {
27802
27839
  httpServer,
27803
27840
  port: addr.port,
27804
27841
  url: `http://${host}:${addr.port}`,
27805
- stop: () => new Promise((resolve23) => {
27806
- httpServer.close(() => resolve23());
27842
+ stop: () => new Promise((resolve24) => {
27843
+ httpServer.close(() => resolve24());
27807
27844
  }),
27808
27845
  handler
27809
27846
  };
@@ -27953,23 +27990,23 @@ function buildMcpHttpServer(opts) {
27953
27990
  httpServer,
27954
27991
  routes,
27955
27992
  port,
27956
- stop: () => new Promise((resolve23) => {
27993
+ stop: () => new Promise((resolve24) => {
27957
27994
  let pending = transports.size;
27958
27995
  if (pending === 0) {
27959
- httpServer.close(() => resolve23());
27996
+ httpServer.close(() => resolve24());
27960
27997
  return;
27961
27998
  }
27962
27999
  for (const transport of transports.values()) {
27963
28000
  void transport.close().finally(() => {
27964
28001
  pending--;
27965
- if (pending === 0) httpServer.close(() => resolve23());
28002
+ if (pending === 0) httpServer.close(() => resolve24());
27966
28003
  });
27967
28004
  }
27968
28005
  })
27969
28006
  };
27970
28007
  }
27971
28008
  function listenMcpHttpServer(server, host = "127.0.0.1") {
27972
- return new Promise((resolve23, reject) => {
28009
+ return new Promise((resolve24, reject) => {
27973
28010
  server.httpServer.once("error", reject);
27974
28011
  server.httpServer.listen(server.port, host, () => {
27975
28012
  server.httpServer.off("error", reject);
@@ -27977,7 +28014,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
27977
28014
  if (addr && typeof addr === "object") {
27978
28015
  server.port = addr.port;
27979
28016
  }
27980
- resolve23();
28017
+ resolve24();
27981
28018
  });
27982
28019
  });
27983
28020
  }
@@ -28060,7 +28097,7 @@ async function loadConfigSafe() {
28060
28097
  }
28061
28098
 
28062
28099
  // src/chat-cli.ts
28063
- import * as path55 from "path";
28100
+ import * as path56 from "path";
28064
28101
 
28065
28102
  // src/chat/inbox.ts
28066
28103
  import { execFileSync as execFileSync25 } from "child_process";
@@ -28127,7 +28164,7 @@ async function waitForNextUserMessage(opts) {
28127
28164
  }
28128
28165
  }
28129
28166
  function sleep3(ms) {
28130
- return new Promise((resolve23) => setTimeout(resolve23, ms));
28167
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
28131
28168
  }
28132
28169
  function currentBranch(cwd) {
28133
28170
  try {
@@ -28351,7 +28388,7 @@ async function runChat(argv) {
28351
28388
  ${CHAT_HELP}`);
28352
28389
  return 64;
28353
28390
  }
28354
- const cwd = args.cwd ? path55.resolve(args.cwd) : process.cwd();
28391
+ const cwd = args.cwd ? path56.resolve(args.cwd) : process.cwd();
28355
28392
  const sessionId = args.sessionId;
28356
28393
  const runRequest = readRunRequestFromEnv();
28357
28394
  if (runRequest && "request" in runRequest) {
@@ -28478,7 +28515,7 @@ init_registry();
28478
28515
 
28479
28516
  // src/servers/brain-terminal-agent.ts
28480
28517
  init_repoWorkspace();
28481
- import * as path57 from "path";
28518
+ import * as path58 from "path";
28482
28519
  import { createInterface as createInterface2 } from "readline";
28483
28520
 
28484
28521
  // src/terminal/brain-terminal-session.ts
@@ -28792,10 +28829,10 @@ var BrainTerminalSessionAgent = class {
28792
28829
  // src/terminal/brain-terminal-adapters.ts
28793
28830
  import { createHash as createHash10, randomBytes as randomBytes2 } from "crypto";
28794
28831
  import { mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
28795
- import * as path56 from "path";
28832
+ import * as path57 from "path";
28796
28833
  import { spawn as spawn9 } from "child_process";
28797
28834
  function runTerminalCommand(command, args, input) {
28798
- return new Promise((resolve23, reject) => {
28835
+ return new Promise((resolve24, reject) => {
28799
28836
  const child = spawn9(command, args, { stdio: ["pipe", "pipe", "pipe"] });
28800
28837
  const stdout = [];
28801
28838
  const stderr = [];
@@ -28803,7 +28840,7 @@ function runTerminalCommand(command, args, input) {
28803
28840
  child.stderr.on("data", (chunk) => stderr.push(chunk));
28804
28841
  child.on("error", reject);
28805
28842
  child.on("close", (code) => {
28806
- resolve23({
28843
+ resolve24({
28807
28844
  code: code ?? 1,
28808
28845
  stdout: Buffer.concat(stdout).toString("utf8"),
28809
28846
  stderr: Buffer.concat(stderr).toString("utf8")
@@ -28827,7 +28864,7 @@ var FileBrainTerminalMetadataStore = class {
28827
28864
  }
28828
28865
  root;
28829
28866
  file(id) {
28830
- return path56.join(this.root, `${storeKey(id)}.json`);
28867
+ return path57.join(this.root, `${storeKey(id)}.json`);
28831
28868
  }
28832
28869
  async read(id) {
28833
28870
  try {
@@ -28948,8 +28985,8 @@ async function brainTerminalAgent(options) {
28948
28985
  const input = options.input ?? process.stdin;
28949
28986
  const output = options.output ?? process.stdout;
28950
28987
  const error = options.error ?? process.stderr;
28951
- const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() || path57.join(path57.dirname(path57.resolve(options.cwd)), "repos");
28952
- const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() || path57.join(path57.dirname(reposRoot), ".kody", "terminal-sessions");
28988
+ const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() || path58.join(path58.dirname(path58.resolve(options.cwd)), "repos");
28989
+ const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() || path58.join(path58.dirname(reposRoot), ".kody", "terminal-sessions");
28953
28990
  const agent = new BrainTerminalSessionAgent({
28954
28991
  store: new FileBrainTerminalMetadataStore(stateRoot),
28955
28992
  runtime: new TmuxBrainTerminalRuntime()
@@ -29116,8 +29153,8 @@ var FlyClient = class {
29116
29153
  get fetch() {
29117
29154
  return this.opts.fetchImpl ?? fetch;
29118
29155
  }
29119
- async call(path58, init = {}) {
29120
- const res = await this.fetch(`${FLY_API_BASE}${path58}`, {
29156
+ async call(path59, init = {}) {
29157
+ const res = await this.fetch(`${FLY_API_BASE}${path59}`, {
29121
29158
  method: init.method ?? "GET",
29122
29159
  headers: {
29123
29160
  Authorization: `Bearer ${this.opts.token}`,
@@ -29128,7 +29165,7 @@ var FlyClient = class {
29128
29165
  if (res.status === 404 && init.allow404) return null;
29129
29166
  if (!res.ok) {
29130
29167
  const text2 = await res.text().catch(() => "");
29131
- throw new Error(`Fly API ${res.status} on ${path58}: ${text2.slice(0, 200) || res.statusText}`);
29168
+ throw new Error(`Fly API ${res.status} on ${path59}: ${text2.slice(0, 200) || res.statusText}`);
29132
29169
  }
29133
29170
  if (res.status === 204) return null;
29134
29171
  const raw = await res.text();
@@ -29641,14 +29678,14 @@ function sendJson2(res, status, body) {
29641
29678
  res.end(JSON.stringify(body));
29642
29679
  }
29643
29680
  function readJsonBody2(req) {
29644
- return new Promise((resolve23, reject) => {
29681
+ return new Promise((resolve24, reject) => {
29645
29682
  const chunks = [];
29646
29683
  req.on("data", (c) => chunks.push(c));
29647
29684
  req.on("end", () => {
29648
29685
  const raw = Buffer.concat(chunks).toString("utf-8");
29649
- if (!raw.trim()) return resolve23({});
29686
+ if (!raw.trim()) return resolve24({});
29650
29687
  try {
29651
- resolve23(JSON.parse(raw));
29688
+ resolve24(JSON.parse(raw));
29652
29689
  } catch (err) {
29653
29690
  reject(err instanceof Error ? err : new Error(String(err)));
29654
29691
  }
@@ -29802,10 +29839,10 @@ async function poolServe() {
29802
29839
  }
29803
29840
  });
29804
29841
  const apiHost = process.env.POOL_API_HOST ?? "::";
29805
- await new Promise((resolve23) => {
29842
+ await new Promise((resolve24) => {
29806
29843
  server.listen(apiPort, apiHost, () => {
29807
29844
  log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
29808
- resolve23();
29845
+ resolve24();
29809
29846
  });
29810
29847
  });
29811
29848
  if (loopTickEnabled) void runLoopTick();
@@ -29845,17 +29882,17 @@ function authOk2(req, expected) {
29845
29882
  return false;
29846
29883
  }
29847
29884
  function readJsonBody3(req) {
29848
- return new Promise((resolve23, reject) => {
29885
+ return new Promise((resolve24, reject) => {
29849
29886
  const chunks = [];
29850
29887
  req.on("data", (c) => chunks.push(c));
29851
29888
  req.on("end", () => {
29852
29889
  const raw = Buffer.concat(chunks).toString("utf-8");
29853
29890
  if (!raw.trim()) {
29854
- resolve23({});
29891
+ resolve24({});
29855
29892
  return;
29856
29893
  }
29857
29894
  try {
29858
- resolve23(JSON.parse(raw));
29895
+ resolve24(JSON.parse(raw));
29859
29896
  } catch (err) {
29860
29897
  reject(err instanceof Error ? err : new Error(String(err)));
29861
29898
  }
@@ -29930,13 +29967,13 @@ async function defaultRunJob(job) {
29930
29967
  ...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
29931
29968
  ...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
29932
29969
  };
29933
- const run = (cmd, args, cwd) => new Promise((resolve23) => {
29970
+ const run = (cmd, args, cwd) => new Promise((resolve24) => {
29934
29971
  const child = spawn10(cmd, args, { stdio: "inherit", env: childEnv, cwd });
29935
- child.on("exit", (code) => resolve23(code ?? 0));
29972
+ child.on("exit", (code) => resolve24(code ?? 0));
29936
29973
  child.on("error", (err) => {
29937
29974
  process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
29938
29975
  `);
29939
- resolve23(1);
29976
+ resolve24(1);
29940
29977
  });
29941
29978
  });
29942
29979
  process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
@@ -30012,11 +30049,11 @@ async function runnerServe() {
30012
30049
  const port = Number(process.env.PORT ?? DEFAULT_PORT2);
30013
30050
  const server = buildServer2({ apiKey });
30014
30051
  const host = process.env.RUNNER_HOST ?? "::";
30015
- await new Promise((resolve23) => {
30052
+ await new Promise((resolve24) => {
30016
30053
  server.listen(port, host, () => {
30017
30054
  process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
30018
30055
  `);
30019
- resolve23();
30056
+ resolve24();
30020
30057
  });
30021
30058
  });
30022
30059
  const shutdown = (signal) => {
@@ -30085,14 +30122,14 @@ async function serve(opts) {
30085
30122
  `);
30086
30123
  const args = ["--dangerously-skip-permissions", "--model", model.model];
30087
30124
  const child = spawn11("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
30088
- const exitCode = await new Promise((resolve23) => {
30089
- child.on("exit", (code) => resolve23(code ?? 0));
30125
+ const exitCode = await new Promise((resolve24) => {
30126
+ child.on("exit", (code) => resolve24(code ?? 0));
30090
30127
  child.on("error", (err) => {
30091
30128
  process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
30092
30129
  `);
30093
30130
  process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
30094
30131
  `);
30095
- resolve23(1);
30132
+ resolve24(1);
30096
30133
  });
30097
30134
  });
30098
30135
  killProxy();