@kody-ade/kody-engine 0.4.570 → 0.4.572

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 +483 -436
  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.570",
18
+ version: "0.4.572",
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",
@@ -150,9 +150,38 @@ var init_claudeBinary = __esm({
150
150
  }
151
151
  });
152
152
 
153
+ // src/completionGuard.ts
154
+ import * as path2 from "path";
155
+ function completionToolCutoffAt(startedAtMs, deadlineAtMs) {
156
+ const availableMs = Math.max(0, deadlineAtMs - startedAtMs);
157
+ const reserveMs = Math.min(MAX_COMPLETION_RESERVE_MS, Math.floor(availableMs / 2));
158
+ return deadlineAtMs - reserveMs;
159
+ }
160
+ function createCompletionToolGuard(cutoffAtMs, now = Date.now, requiredOutputPath) {
161
+ return async (input) => {
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
+ }
168
+ return {
169
+ decision: "block",
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."
171
+ };
172
+ };
173
+ }
174
+ var MAX_COMPLETION_RESERVE_MS;
175
+ var init_completionGuard = __esm({
176
+ "src/completionGuard.ts"() {
177
+ "use strict";
178
+ MAX_COMPLETION_RESERVE_MS = 15 * 6e4;
179
+ }
180
+ });
181
+
153
182
  // src/config.ts
154
183
  import * as fs2 from "fs";
155
- import * as path2 from "path";
184
+ import * as path3 from "path";
156
185
  function parseReasoningEffort(raw) {
157
186
  if (!raw) return null;
158
187
  const v = raw.trim().toLowerCase();
@@ -217,7 +246,7 @@ function needsLitellmProxy(model) {
217
246
  return model.provider !== "claude" && model.provider !== "anthropic";
218
247
  }
219
248
  function loadConfig(projectDir = process.cwd()) {
220
- const configPath = path2.join(projectDir, "kody.config.json");
249
+ const configPath = path3.join(projectDir, "kody.config.json");
221
250
  if (!fs2.existsSync(configPath)) {
222
251
  throw new Error(`kody.config.json not found at ${configPath}`);
223
252
  }
@@ -548,6 +577,29 @@ var init_config = __esm({
548
577
  }
549
578
  });
550
579
 
580
+ // src/fileEditGuards.ts
581
+ import * as fs3 from "fs";
582
+ import * as path4 from "path";
583
+ function createMissingParentWriteGuard(cwd) {
584
+ return async (input) => {
585
+ const toolInput = input.tool_input;
586
+ if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
587
+ const filePath = toolInput.file_path;
588
+ if (typeof filePath !== "string" || filePath.length === 0) return {};
589
+ const resolvedPath = path4.resolve(cwd, filePath);
590
+ if (fs3.existsSync(path4.dirname(resolvedPath))) return {};
591
+ return {
592
+ decision: "block",
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.`
594
+ };
595
+ };
596
+ }
597
+ var init_fileEditGuards = __esm({
598
+ "src/fileEditGuards.ts"() {
599
+ "use strict";
600
+ }
601
+ });
602
+
551
603
  // src/format.ts
552
604
  function renderEvent(msg, opts = {}) {
553
605
  if (opts.quiet) {
@@ -669,29 +721,6 @@ var init_format = __esm({
669
721
  }
670
722
  });
671
723
 
672
- // src/fileEditGuards.ts
673
- import * as fs3 from "fs";
674
- import * as path3 from "path";
675
- function createMissingParentWriteGuard(cwd) {
676
- return async (input) => {
677
- const toolInput = input.tool_input;
678
- if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
679
- const filePath = toolInput.file_path;
680
- if (typeof filePath !== "string" || filePath.length === 0) return {};
681
- const resolvedPath = path3.resolve(cwd, filePath);
682
- if (fs3.existsSync(path3.dirname(resolvedPath))) return {};
683
- return {
684
- decision: "block",
685
- 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.`
686
- };
687
- };
688
- }
689
- var init_fileEditGuards = __esm({
690
- "src/fileEditGuards.ts"() {
691
- "use strict";
692
- }
693
- });
694
-
695
724
  // src/agency/capability-contract-validation.ts
696
725
  import Ajv from "ajv";
697
726
  function createCapabilityContractValueValidator(compile) {
@@ -765,7 +794,7 @@ var init_capability_contract_validation = __esm({
765
794
 
766
795
  // src/outputContractHooks.ts
767
796
  import * as fs4 from "fs";
768
- import * as path4 from "path";
797
+ import * as path5 from "path";
769
798
  function outputContractError(contract) {
770
799
  let value;
771
800
  try {
@@ -784,12 +813,12 @@ function correctionMessage(contract, error) {
784
813
  return `The authoritative output does not match its required contract: ${error}. Please overwrite ${contract.path} with only the required JSON shape before finishing.`;
785
814
  }
786
815
  function createOutputContractPostWriteHook(contract) {
787
- const expectedPath = path4.resolve(contract.path);
816
+ const expectedPath = path5.resolve(contract.path);
788
817
  return async (input) => {
789
818
  const toolInput = input.tool_input;
790
819
  if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
791
820
  const filePath = toolInput.file_path;
792
- if (typeof filePath !== "string" || path4.resolve(filePath) !== expectedPath) return {};
821
+ if (typeof filePath !== "string" || path5.resolve(filePath) !== expectedPath) return {};
793
822
  const error = outputContractError(contract);
794
823
  if (!error) return {};
795
824
  return {
@@ -833,21 +862,21 @@ __export(runtimePaths_exports, {
833
862
  });
834
863
  import { createHash } from "crypto";
835
864
  import * as os2 from "os";
836
- import * as path5 from "path";
865
+ import * as path6 from "path";
837
866
  function runtimeDirForCwd(cwd, ...parts) {
838
- const key = createHash("sha256").update(path5.resolve(cwd)).digest("hex").slice(0, 16);
839
- 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);
840
869
  }
841
870
  function runtimeStatePath(cwd, ...parts) {
842
871
  const configuredRoot = process.env.KODY_RUNTIME_DIR?.trim();
843
- const base = configuredRoot ? path5.resolve(configuredRoot) : runtimeDirForCwd(cwd);
844
- return path5.join(base, ...parts);
872
+ const base = configuredRoot ? path6.resolve(configuredRoot) : runtimeDirForCwd(cwd);
873
+ return path6.join(base, ...parts);
845
874
  }
846
875
  function agentRunDir(cwd) {
847
876
  return runtimeStatePath(cwd, "agent-runs");
848
877
  }
849
878
  function lastRunLogPath(cwd) {
850
- return path5.join(agentRunDir(cwd), "last-run.jsonl");
879
+ return path6.join(agentRunDir(cwd), "last-run.jsonl");
851
880
  }
852
881
  var init_runtimePaths = __esm({
853
882
  "src/runtimePaths.ts"() {
@@ -858,15 +887,15 @@ var init_runtimePaths = __esm({
858
887
  // src/scripts/buildSyntheticPlugin.ts
859
888
  import * as fs5 from "fs";
860
889
  import * as os3 from "os";
861
- import * as path6 from "path";
890
+ import * as path7 from "path";
862
891
  function getPluginsCatalogRoot() {
863
- const here = path6.dirname(new URL(import.meta.url).pathname);
892
+ const here = path7.dirname(new URL(import.meta.url).pathname);
864
893
  const candidates = [
865
- path6.join(here, "..", "plugins"),
894
+ path7.join(here, "..", "plugins"),
866
895
  // dev: src/scripts → src/plugins
867
- path6.join(here, "..", "..", "plugins"),
896
+ path7.join(here, "..", "..", "plugins"),
868
897
  // built: dist/scripts → dist/plugins
869
- path6.join(here, "..", "..", "src", "plugins")
898
+ path7.join(here, "..", "..", "src", "plugins")
870
899
  // fallback
871
900
  ];
872
901
  for (const c of candidates) {
@@ -877,8 +906,8 @@ function getPluginsCatalogRoot() {
877
906
  function copyDir(src, dst) {
878
907
  fs5.mkdirSync(dst, { recursive: true });
879
908
  for (const ent of fs5.readdirSync(src, { withFileTypes: true })) {
880
- const s = path6.join(src, ent.name);
881
- const d = path6.join(dst, ent.name);
909
+ const s = path7.join(src, ent.name);
910
+ const d = path7.join(dst, ent.name);
882
911
  if (ent.isDirectory()) copyDir(s, d);
883
912
  else if (ent.isFile()) fs5.copyFileSync(s, d);
884
913
  }
@@ -893,35 +922,35 @@ var init_buildSyntheticPlugin = __esm({
893
922
  if (!needsSynthetic) return;
894
923
  const catalog = getPluginsCatalogRoot();
895
924
  const runId = `${profile.name}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
896
- const root = path6.join(os3.tmpdir(), `kody-synth-${runId}`);
897
- 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 });
898
927
  const resolvePart = (bucket, entry) => {
899
- const local = path6.join(profile.dir, bucket, entry);
928
+ const local = path7.join(profile.dir, bucket, entry);
900
929
  if (fs5.existsSync(local)) return local;
901
- const shared = path6.resolve(profile.dir, "..", "..", "shared", bucket, entry);
930
+ const shared = path7.resolve(profile.dir, "..", "..", "shared", bucket, entry);
902
931
  if (fs5.existsSync(shared)) return shared;
903
- const central = path6.join(catalog, bucket, entry);
932
+ const central = path7.join(catalog, bucket, entry);
904
933
  if (fs5.existsSync(central)) return central;
905
934
  throw new Error(
906
- `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}/)`
907
936
  );
908
937
  };
909
938
  if (cc.skills.length > 0) {
910
- const dst = path6.join(root, "skills");
939
+ const dst = path7.join(root, "skills");
911
940
  fs5.mkdirSync(dst, { recursive: true });
912
941
  for (const name of cc.skills) {
913
- copyDir(resolvePart("skills", name), path6.join(dst, name));
942
+ copyDir(resolvePart("skills", name), path7.join(dst, name));
914
943
  }
915
944
  }
916
945
  if (cc.commands.length > 0) {
917
- const dst = path6.join(root, "commands");
946
+ const dst = path7.join(root, "commands");
918
947
  fs5.mkdirSync(dst, { recursive: true });
919
948
  for (const name of cc.commands) {
920
- fs5.copyFileSync(resolvePart("commands", `${name}.md`), path6.join(dst, `${name}.md`));
949
+ fs5.copyFileSync(resolvePart("commands", `${name}.md`), path7.join(dst, `${name}.md`));
921
950
  }
922
951
  }
923
952
  if (cc.hooks.length > 0) {
924
- const dst = path6.join(root, "hooks");
953
+ const dst = path7.join(root, "hooks");
925
954
  fs5.mkdirSync(dst, { recursive: true });
926
955
  const merged = { hooks: {} };
927
956
  for (const name of cc.hooks) {
@@ -933,7 +962,7 @@ var init_buildSyntheticPlugin = __esm({
933
962
  merged.hooks[event].push(...entries);
934
963
  }
935
964
  }
936
- 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)}
937
966
  `);
938
967
  }
939
968
  const manifest = {
@@ -943,7 +972,7 @@ var init_buildSyntheticPlugin = __esm({
943
972
  };
944
973
  if (cc.skills.length > 0) manifest.skills = ["./skills/"];
945
974
  if (cc.commands.length > 0) manifest.commands = ["./commands/"];
946
- 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)}
947
976
  `);
948
977
  ctx.data.syntheticPluginPath = root;
949
978
  };
@@ -952,7 +981,7 @@ var init_buildSyntheticPlugin = __esm({
952
981
 
953
982
  // src/subagents.ts
954
983
  import * as fs6 from "fs";
955
- import * as path7 from "path";
984
+ import * as path8 from "path";
956
985
  async function enforceSubagentModelInheritance(input) {
957
986
  const toolInput = input.tool_input;
958
987
  if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) return {};
@@ -987,11 +1016,11 @@ function splitFrontmatter(raw) {
987
1016
  return { fm, body: (match[2] ?? "").trim() };
988
1017
  }
989
1018
  function resolveAgentFile(profileDir, name) {
990
- const local = path7.join(profileDir, "agents", `${name}.md`);
1019
+ const local = path8.join(profileDir, "agents", `${name}.md`);
991
1020
  if (fs6.existsSync(local)) return local;
992
- const shared = path7.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
1021
+ const shared = path8.resolve(profileDir, "..", "..", "shared", "agents", `${name}.md`);
993
1022
  if (fs6.existsSync(shared)) return shared;
994
- const central = path7.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
1023
+ const central = path8.join(getPluginsCatalogRoot(), "agents", `${name}.md`);
995
1024
  if (fs6.existsSync(central)) return central;
996
1025
  throw new Error(
997
1026
  `loadSubagents: agent '${name}' not found in ${profileDir}/agents/, hydrated shared assets, or engine catalog`
@@ -1048,7 +1077,7 @@ __export(events_exports, {
1048
1077
  });
1049
1078
  import * as crypto from "crypto";
1050
1079
  import * as fs7 from "fs";
1051
- import * as path8 from "path";
1080
+ import * as path9 from "path";
1052
1081
  function resolveRunId() {
1053
1082
  if (process.env.KODY_RUN_ID) {
1054
1083
  cachedRunId = process.env.KODY_RUN_ID;
@@ -1081,7 +1110,7 @@ function emitEvent(cwd, ev) {
1081
1110
  ...ev
1082
1111
  };
1083
1112
  const file = eventsPath(cwd, runId);
1084
- fs7.mkdirSync(path8.dirname(file), { recursive: true });
1113
+ fs7.mkdirSync(path9.dirname(file), { recursive: true });
1085
1114
  fs7.appendFileSync(file, `${JSON.stringify(fullEvent)}
1086
1115
  `);
1087
1116
  } catch {
@@ -1107,7 +1136,7 @@ function listRuns(cwd) {
1107
1136
  if (!fs7.existsSync(runsDir)) return [];
1108
1137
  return fs7.readdirSync(runsDir).filter((name) => {
1109
1138
  try {
1110
- return fs7.statSync(path8.join(runsDir, name)).isDirectory();
1139
+ return fs7.statSync(path9.join(runsDir, name)).isDirectory();
1111
1140
  } catch {
1112
1141
  return false;
1113
1142
  }
@@ -1148,10 +1177,10 @@ function abortMessage(signal) {
1148
1177
  return reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "verification aborted";
1149
1178
  }
1150
1179
  function runCommand(command, cwd, signal) {
1151
- return new Promise((resolve23) => {
1180
+ return new Promise((resolve24) => {
1152
1181
  const start = Date.now();
1153
1182
  if (signal?.aborted) {
1154
- resolve23({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
1183
+ resolve24({ exitCode: -1, durationMs: 0, tail: abortMessage(signal) });
1155
1184
  return;
1156
1185
  }
1157
1186
  const child = spawn(command, {
@@ -1189,7 +1218,7 @@ function runCommand(command, cwd, signal) {
1189
1218
  signal?.removeEventListener("abort", onAbort);
1190
1219
  const output = Buffer.concat(buffers).toString("utf-8");
1191
1220
  const tail = [output, extraTail].filter(Boolean).join("\n").slice(-TAIL_CHARS);
1192
- resolve23({ exitCode, durationMs: Date.now() - start, tail });
1221
+ resolve24({ exitCode, durationMs: Date.now() - start, tail });
1193
1222
  };
1194
1223
  const terminate = () => {
1195
1224
  killTree("SIGTERM");
@@ -1518,7 +1547,7 @@ function cmsHeaders(opts) {
1518
1547
  }
1519
1548
  };
1520
1549
  }
1521
- async function callDashboardCms(opts, path58, init = {}) {
1550
+ async function callDashboardCms(opts, path59, init = {}) {
1522
1551
  const baseUrl = dashboardBaseUrl(opts);
1523
1552
  if (!baseUrl) {
1524
1553
  return {
@@ -1530,7 +1559,7 @@ async function callDashboardCms(opts, path58, init = {}) {
1530
1559
  const headerResult = cmsHeaders(opts);
1531
1560
  if (!headerResult.ok) return headerResult;
1532
1561
  try {
1533
- const res = await fetch(`${baseUrl}${path58}`, {
1562
+ const res = await fetch(`${baseUrl}${path59}`, {
1534
1563
  ...init,
1535
1564
  headers: {
1536
1565
  ...headerResult.headers,
@@ -1602,8 +1631,8 @@ function documentArg(value) {
1602
1631
  function normalizeCmsDocumentIdInput(input) {
1603
1632
  const trimmed = stripWrappingQuotes(input.trim());
1604
1633
  const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? trimmed;
1605
- const path58 = parseDocumentPath(withoutQuery);
1606
- return path58 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
1634
+ const path59 = parseDocumentPath(withoutQuery);
1635
+ return path59 ?? parseDocumentIdSegment(withoutQuery) ?? withoutQuery;
1607
1636
  }
1608
1637
  function stripWrappingQuotes(value) {
1609
1638
  let current = value;
@@ -1614,9 +1643,9 @@ function stripWrappingQuotes(value) {
1614
1643
  }
1615
1644
  }
1616
1645
  function parseDocumentPath(value) {
1617
- const path58 = value.startsWith("http://") || value.startsWith("https://") ? urlPathname(value) : value;
1618
- if (!path58?.includes("/content/entries/")) return null;
1619
- 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);
1620
1649
  const entriesIndex = parts.findIndex((part, index) => part === "content" && parts[index + 1] === "entries");
1621
1650
  const idPart = parts[entriesIndex + 3];
1622
1651
  if (!idPart || idPart === "new") return null;
@@ -2062,7 +2091,7 @@ var init_issue = __esm({
2062
2091
 
2063
2092
  // src/capabilityFolders.ts
2064
2093
  import * as fs8 from "fs";
2065
- import * as path9 from "path";
2094
+ import * as path10 from "path";
2066
2095
  function capabilityOutputConditionPaths(config) {
2067
2096
  if (config.outputSchema) {
2068
2097
  return new Set(schemaPropertyPaths(config.outputSchema, "result"));
@@ -2084,35 +2113,35 @@ function listCapabilityFolderSlugs(absDir) {
2084
2113
  } catch {
2085
2114
  return [];
2086
2115
  }
2087
- 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();
2088
2117
  }
2089
2118
  function isCapabilityFolder(dir) {
2090
2119
  const entries = fs8.readdirSync(dir, { withFileTypes: true });
2091
- const legacyBody = path9.join(dir, CAPABILITY_BODY_FILE);
2120
+ const legacyBody = path10.join(dir, CAPABILITY_BODY_FILE);
2092
2121
  if (fs8.existsSync(legacyBody)) {
2093
2122
  return entries.every(
2094
2123
  (entry) => entry.name === CAPABILITY_BODY_FILE || entry.name === CAPABILITY_CONTRACT_FILE || entry.isDirectory() && (entry.name === "skills" || entry.name === "tools")
2095
2124
  );
2096
2125
  }
2097
- const canonicalBody = path9.join(dir, CANONICAL_CAPABILITY_BODY_FILE);
2098
- 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);
2099
2128
  if (!fs8.existsSync(canonicalBody) || !fs8.existsSync(canonicalDefinition)) return false;
2100
2129
  return entries.every(
2101
2130
  (entry) => entry.name === CANONICAL_CAPABILITY_BODY_FILE || entry.name === CANONICAL_CAPABILITY_DEFINITION_FILE
2102
2131
  );
2103
2132
  }
2104
2133
  function readCapabilityFolder(root, slug) {
2105
- const dir = path9.join(root, slug);
2106
- const legacyBodyPath = path9.join(dir, CAPABILITY_BODY_FILE);
2107
- 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);
2108
2137
  const bodyPath = fs8.existsSync(legacyBodyPath) ? legacyBodyPath : canonicalBodyPath;
2109
- const contractPath = path9.join(dir, CAPABILITY_CONTRACT_FILE);
2138
+ const contractPath = path10.join(dir, CAPABILITY_CONTRACT_FILE);
2110
2139
  if (!fs8.existsSync(bodyPath) || !fs8.statSync(bodyPath).isFile()) return null;
2111
2140
  if (!isCapabilityFolder(dir)) return null;
2112
2141
  try {
2113
2142
  const rawBody = fs8.readFileSync(bodyPath, "utf-8");
2114
2143
  if (bodyPath === canonicalBodyPath) {
2115
- const definitionPath = path9.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2144
+ const definitionPath = path10.join(dir, CANONICAL_CAPABILITY_DEFINITION_FILE);
2116
2145
  const definition = JSON.parse(fs8.readFileSync(definitionPath, "utf-8"));
2117
2146
  if (definition.id !== slug || typeof definition.action !== "string") return null;
2118
2147
  const { title: title2, body: body2 } = parseCapabilityBody(rawBody, slug);
@@ -2134,7 +2163,7 @@ function readCapabilityFolder(root, slug) {
2134
2163
  };
2135
2164
  }
2136
2165
  const contract = fs8.existsSync(contractPath) ? parseCapabilityContract(fs8.readFileSync(contractPath, "utf-8")) : void 0;
2137
- if (contract?.execution === "script" && !isRegularFile(path9.join(dir, "tools", "run.sh"))) {
2166
+ if (contract?.execution === "script" && !isRegularFile(path10.join(dir, "tools", "run.sh"))) {
2138
2167
  throw new Error('script-backed Capability requires a regular "tools/run.sh" file');
2139
2168
  }
2140
2169
  const { title, body } = parseCapabilityBody(rawBody, slug);
@@ -2256,8 +2285,8 @@ function isRegularFile(filePath) {
2256
2285
  function schemaPropertyPaths(schema, prefix) {
2257
2286
  const properties = isPlainObject(schema.properties) ? schema.properties : {};
2258
2287
  return Object.entries(properties).flatMap(([name, property]) => {
2259
- const path58 = `${prefix}.${name}`;
2260
- return isPlainObject(property) ? [path58, ...schemaPropertyPaths(property, path58)] : [path58];
2288
+ const path59 = `${prefix}.${name}`;
2289
+ return isPlainObject(property) ? [path59, ...schemaPropertyPaths(property, path59)] : [path59];
2261
2290
  });
2262
2291
  }
2263
2292
  function parseCapabilityBody(raw, slug) {
@@ -2424,47 +2453,47 @@ var init_capabilityFolders = __esm({
2424
2453
 
2425
2454
  // src/definition-paths.ts
2426
2455
  import * as fs9 from "fs";
2427
- import * as path10 from "path";
2456
+ import * as path11 from "path";
2428
2457
  function definitionsRoot(cwd = process.cwd()) {
2429
2458
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
2430
2459
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2431
- if (override && overrideCwd && path10.resolve(cwd) === path10.resolve(overrideCwd)) {
2432
- return storeCatalogRoot(path10.resolve(override));
2460
+ if (override && overrideCwd && path11.resolve(cwd) === path11.resolve(overrideCwd)) {
2461
+ return storeCatalogRoot(path11.resolve(override));
2433
2462
  }
2434
- const hydrated = path10.join(cwd, ".kody-engine", "definitions");
2463
+ const hydrated = path11.join(cwd, ".kody-engine", "definitions");
2435
2464
  if (fs9.existsSync(hydrated)) return hydrated;
2436
- return override ? storeCatalogRoot(path10.resolve(override)) : hydrated;
2465
+ return override ? storeCatalogRoot(path11.resolve(override)) : hydrated;
2437
2466
  }
2438
2467
  function hasExplicitDefinitionsRoot(cwd = process.cwd(), env = process.env) {
2439
2468
  const root = env.KODY_DEFINITIONS_ROOT?.trim();
2440
2469
  const rootCwd = env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2441
- return Boolean(root && rootCwd && path10.resolve(cwd) === path10.resolve(rootCwd));
2470
+ return Boolean(root && rootCwd && path11.resolve(cwd) === path11.resolve(rootCwd));
2442
2471
  }
2443
2472
  function capabilitiesRoot(cwd = process.cwd()) {
2444
- return storeAssetRoot(cwd, "capabilities") ?? path10.join(definitionsRoot(cwd), "capabilities");
2473
+ return storeAssetRoot(cwd, "capabilities") ?? path11.join(definitionsRoot(cwd), "capabilities");
2445
2474
  }
2446
2475
  function implementationsRoot(cwd = process.cwd()) {
2447
- return path10.join(definitionsRoot(cwd), "implementations");
2476
+ return path11.join(definitionsRoot(cwd), "implementations");
2448
2477
  }
2449
2478
  function agentsRoot(cwd = process.cwd()) {
2450
- return storeAssetRoot(cwd, "agent") ?? path10.join(definitionsRoot(cwd), "agents");
2479
+ return storeAssetRoot(cwd, "agent") ?? path11.join(definitionsRoot(cwd), "agents");
2451
2480
  }
2452
2481
  function storeCatalogRoot(root) {
2453
2482
  const manifest = readStoreManifest(root);
2454
- const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path10.dirname(value));
2455
- return roots.length === 3 && new Set(roots).size === 1 ? path10.join(root, roots[0]) : root;
2483
+ const roots = ["capabilities", "workflows", "loops"].map((kind) => manifest?.assetRoots?.[kind]).filter((value) => typeof value === "string" && Boolean(value.trim())).map((value) => path11.dirname(value));
2484
+ return roots.length === 3 && new Set(roots).size === 1 ? path11.join(root, roots[0]) : root;
2456
2485
  }
2457
2486
  function storeAssetRoot(cwd, kind) {
2458
2487
  const override = process.env.KODY_DEFINITIONS_ROOT?.trim();
2459
2488
  if (!override) return null;
2460
2489
  const overrideCwd = process.env.KODY_DEFINITIONS_ROOT_CWD?.trim();
2461
- if (overrideCwd && path10.resolve(cwd) !== path10.resolve(overrideCwd)) return null;
2462
- const root = path10.resolve(override);
2490
+ if (overrideCwd && path11.resolve(cwd) !== path11.resolve(overrideCwd)) return null;
2491
+ const root = path11.resolve(override);
2463
2492
  const configured = readStoreManifest(root)?.assetRoots?.[kind];
2464
- return typeof configured === "string" && configured.trim() ? path10.join(root, configured) : null;
2493
+ return typeof configured === "string" && configured.trim() ? path11.join(root, configured) : null;
2465
2494
  }
2466
2495
  function readStoreManifest(root) {
2467
- const file = path10.join(root, "kody-store.json");
2496
+ const file = path11.join(root, "kody-store.json");
2468
2497
  if (!fs9.existsSync(file)) return null;
2469
2498
  try {
2470
2499
  return JSON.parse(fs9.readFileSync(file, "utf8"));
@@ -2480,15 +2509,15 @@ var init_definition_paths = __esm({
2480
2509
 
2481
2510
  // src/registry.ts
2482
2511
  import * as fs10 from "fs";
2483
- import * as path11 from "path";
2512
+ import * as path12 from "path";
2484
2513
  function getImplementationsRoot() {
2485
- const here = path11.dirname(new URL(import.meta.url).pathname);
2514
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2486
2515
  const candidates = [
2487
- path11.join(here, "implementations"),
2516
+ path12.join(here, "implementations"),
2488
2517
  // dev: src/
2489
- path11.join(here, "..", "implementations"),
2518
+ path12.join(here, "..", "implementations"),
2490
2519
  // built: dist/bin → dist/implementations
2491
- path11.join(here, "..", "src", "implementations")
2520
+ path12.join(here, "..", "src", "implementations")
2492
2521
  // fallback
2493
2522
  ];
2494
2523
  for (const c of candidates) {
@@ -2497,11 +2526,11 @@ function getImplementationsRoot() {
2497
2526
  return candidates[0];
2498
2527
  }
2499
2528
  function getRuntimeServicesRoot() {
2500
- const here = path11.dirname(new URL(import.meta.url).pathname);
2529
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2501
2530
  const candidates = [
2502
- path11.join(here, "runtime-services"),
2503
- path11.join(here, "..", "runtime-services"),
2504
- path11.join(here, "..", "src", "runtime-services")
2531
+ path12.join(here, "runtime-services"),
2532
+ path12.join(here, "..", "runtime-services"),
2533
+ path12.join(here, "..", "src", "runtime-services")
2505
2534
  ];
2506
2535
  for (const candidate of candidates) {
2507
2536
  if (fs10.existsSync(candidate) && fs10.statSync(candidate).isDirectory()) return candidate;
@@ -2512,13 +2541,13 @@ function getProjectCapabilitiesRoot() {
2512
2541
  return capabilitiesRoot();
2513
2542
  }
2514
2543
  function getBuiltinCapabilitiesRoot() {
2515
- const here = path11.dirname(new URL(import.meta.url).pathname);
2544
+ const here = path12.dirname(new URL(import.meta.url).pathname);
2516
2545
  const candidates = [
2517
- path11.join(here, "capabilities"),
2546
+ path12.join(here, "capabilities"),
2518
2547
  // dev: src/
2519
- path11.join(here, "..", "capabilities"),
2548
+ path12.join(here, "..", "capabilities"),
2520
2549
  // built: dist/bin → dist/capabilities
2521
- path11.join(here, "..", "src", "capabilities")
2550
+ path12.join(here, "..", "src", "capabilities")
2522
2551
  // fallback
2523
2552
  ];
2524
2553
  for (const c of candidates) {
@@ -2662,17 +2691,17 @@ function isSafeName(name) {
2662
2691
  return /^[a-z][a-z0-9-]*$/.test(name) && !name.includes("..");
2663
2692
  }
2664
2693
  function isCapabilityRoot(root) {
2665
- const normalized = path11.normalize(root);
2666
- if (path11.basename(normalized) === "capabilities") return true;
2694
+ const normalized = path12.normalize(root);
2695
+ if (path12.basename(normalized) === "capabilities") return true;
2667
2696
  const knownRoots = [getProjectCapabilitiesRoot(), getBuiltinCapabilitiesRoot()];
2668
- return knownRoots.some((candidate) => candidate && path11.normalize(candidate) === normalized);
2697
+ return knownRoots.some((candidate) => candidate && path12.normalize(candidate) === normalized);
2669
2698
  }
2670
2699
  function implementationRuntimePath(root, name) {
2671
- const runtimePath = path11.join(root, name, "runtime.json");
2700
+ const runtimePath = path12.join(root, name, "runtime.json");
2672
2701
  if (fs10.existsSync(runtimePath)) return runtimePath;
2673
- const internalProfilePath = path11.join(root, name, "profile.json");
2702
+ const internalProfilePath = path12.join(root, name, "profile.json");
2674
2703
  if (fs10.existsSync(internalProfilePath)) return internalProfilePath;
2675
- return path11.join(root, name, CAPABILITY_PROFILE_FILE);
2704
+ return path12.join(root, name, CAPABILITY_PROFILE_FILE);
2676
2705
  }
2677
2706
  function isImplementationProfile(profilePath, requireImplementationProfile) {
2678
2707
  if (!requireImplementationProfile) return true;
@@ -3839,7 +3868,7 @@ var init_capabilityMcp = __esm({
3839
3868
  // src/repoWorkspace.ts
3840
3869
  import { spawn as spawn2, spawnSync } from "child_process";
3841
3870
  import * as fs11 from "fs";
3842
- import * as path12 from "path";
3871
+ import * as path13 from "path";
3843
3872
  function buildCloneProcess(repo, token, baseEnv = process.env) {
3844
3873
  const url = `https://github.com/${repo}.git`;
3845
3874
  const env = { ...baseEnv };
@@ -3854,10 +3883,10 @@ function buildCloneProcess(repo, token, baseEnv = process.env) {
3854
3883
  async function resolveAndClone(reposRoot, repo, repoToken, cloneRepo) {
3855
3884
  const name = repo?.trim();
3856
3885
  if (!name || !REPO_RE.test(name)) return null;
3857
- const root = path12.resolve(reposRoot);
3858
- const dir = path12.resolve(root, name);
3859
- if (dir !== root && !dir.startsWith(root + path12.sep)) return null;
3860
- if (fs11.existsSync(path12.join(dir, ".git"))) return dir;
3886
+ const root = path13.resolve(reposRoot);
3887
+ const dir = path13.resolve(root, name);
3888
+ if (dir !== root && !dir.startsWith(root + path13.sep)) return null;
3889
+ if (fs11.existsSync(path13.join(dir, ".git"))) return dir;
3861
3890
  const inflight = repoClones.get(dir);
3862
3891
  if (inflight) {
3863
3892
  await inflight;
@@ -3889,9 +3918,9 @@ var init_repoWorkspace = __esm({
3889
3918
  repoClones = /* @__PURE__ */ new Map();
3890
3919
  GIT_CREDENTIAL_HELPER = `!f() { if [ "$1" = get ] && [ -n "$GITHUB_TOKEN" ]; then printf '%s\\n' username=x-access-token "password=$GITHUB_TOKEN"; fi; }; f`;
3891
3920
  defaultCloneRepo = (repo, token, dir) => {
3892
- fs11.mkdirSync(path12.dirname(dir), { recursive: true });
3921
+ fs11.mkdirSync(path13.dirname(dir), { recursive: true });
3893
3922
  const clone = buildCloneProcess(repo, token);
3894
- return new Promise((resolve23, reject) => {
3923
+ return new Promise((resolve24, reject) => {
3895
3924
  const child = spawn2("git", ["clone", "--depth=1", clone.url, dir], {
3896
3925
  env: clone.env,
3897
3926
  stdio: "inherit"
@@ -3911,7 +3940,7 @@ var init_repoWorkspace = __esm({
3911
3940
  }
3912
3941
  } catch {
3913
3942
  }
3914
- resolve23();
3943
+ resolve24();
3915
3944
  });
3916
3945
  child.on("error", reject);
3917
3946
  });
@@ -3984,7 +4013,7 @@ var init_fetchRepoMcp = __esm({
3984
4013
 
3985
4014
  // src/agent.ts
3986
4015
  import * as fs12 from "fs";
3987
- import * as path13 from "path";
4016
+ import * as path14 from "path";
3988
4017
  import { query } from "@anthropic-ai/claude-agent-sdk";
3989
4018
  function classifySubtype(subtype) {
3990
4019
  if (!subtype) return "generic_failed";
@@ -4054,7 +4083,7 @@ function buildAgentEnvironment(baseEnv, repoToken, requestEnvironment) {
4054
4083
  async function runAgent(opts) {
4055
4084
  const ndjsonDir = opts.ndjsonDir ?? agentRunDir(opts.cwd);
4056
4085
  fs12.mkdirSync(ndjsonDir, { recursive: true });
4057
- const ndjsonPath = path13.join(ndjsonDir, "last-run.jsonl");
4086
+ const ndjsonPath = path14.join(ndjsonDir, "last-run.jsonl");
4058
4087
  const env = buildAgentEnvironment(process.env, opts.repoToken, opts.environment);
4059
4088
  if (opts.litellmUrl) {
4060
4089
  env.ANTHROPIC_BASE_URL = opts.litellmUrl;
@@ -4062,6 +4091,11 @@ async function runAgent(opts) {
4062
4091
  }
4063
4092
  const startedAt = Date.now();
4064
4093
  const turnTimeoutMs = resolveTurnTimeoutMs(opts);
4094
+ const completionGuard = typeof opts.deadlineAtMs === "number" ? createCompletionToolGuard(
4095
+ completionToolCutoffAt(startedAt, opts.deadlineAtMs),
4096
+ Date.now,
4097
+ opts.outputContract?.path
4098
+ ) : null;
4065
4099
  let outcome = "failed";
4066
4100
  let outcomeKind = "generic_failed";
4067
4101
  let errorMessage2;
@@ -4106,6 +4140,11 @@ async function runAgent(opts) {
4106
4140
  env,
4107
4141
  hooks: {
4108
4142
  PreToolUse: [
4143
+ ...completionGuard ? [
4144
+ {
4145
+ hooks: [completionGuard]
4146
+ }
4147
+ ] : [],
4109
4148
  {
4110
4149
  matcher: "Agent",
4111
4150
  hooks: [enforceSubagentModelInheritance]
@@ -4229,11 +4268,13 @@ async function runAgent(opts) {
4229
4268
  } else if (typeof opts.maxThinkingTokens === "number" && opts.maxThinkingTokens > 0) {
4230
4269
  queryOptions.maxThinkingTokens = opts.maxThinkingTokens;
4231
4270
  }
4232
- if (typeof opts.systemPromptAppend === "string" && opts.systemPromptAppend.length > 0) {
4271
+ const completionNotice = completionGuard ? "Work within the enforced run time. Tool access closes before the hard deadline to reserve time for a final response. When that happens, stop using tools and finish immediately." : null;
4272
+ const systemPromptAppend = [opts.systemPromptAppend, completionNotice].filter((value) => typeof value === "string" && value.length > 0).join("\n\n");
4273
+ if (systemPromptAppend.length > 0) {
4233
4274
  const systemPrompt = {
4234
4275
  type: "preset",
4235
4276
  preset: "claude_code",
4236
- append: opts.systemPromptAppend
4277
+ append: systemPromptAppend
4237
4278
  };
4238
4279
  if (opts.cacheable) systemPrompt.excludeDynamicSections = true;
4239
4280
  queryOptions.systemPrompt = systemPrompt;
@@ -4263,10 +4304,10 @@ async function runAgent(opts) {
4263
4304
  let timer;
4264
4305
  let next;
4265
4306
  if (turnTimeoutMs > 0) {
4266
- const timeoutPromise = new Promise((resolve23) => {
4307
+ const timeoutPromise = new Promise((resolve24) => {
4267
4308
  timer = setTimeout(() => {
4268
4309
  timedOut = true;
4269
- resolve23({ done: true, value: void 0 });
4310
+ resolve24({ done: true, value: void 0 });
4270
4311
  }, turnTimeoutMs);
4271
4312
  });
4272
4313
  next = await Promise.race([nextPromise, timeoutPromise]);
@@ -4282,7 +4323,7 @@ async function runAgent(opts) {
4282
4323
  try {
4283
4324
  await Promise.race([
4284
4325
  iterator.return(void 0).catch(() => void 0),
4285
- new Promise((resolve23) => setTimeout(resolve23, 1e4).unref())
4326
+ new Promise((resolve24) => setTimeout(resolve24, 1e4).unref())
4286
4327
  ]);
4287
4328
  } catch {
4288
4329
  }
@@ -4463,9 +4504,10 @@ var init_agent = __esm({
4463
4504
  "src/agent.ts"() {
4464
4505
  "use strict";
4465
4506
  init_claudeBinary();
4507
+ init_completionGuard();
4466
4508
  init_config();
4467
- init_format();
4468
4509
  init_fileEditGuards();
4510
+ init_format();
4469
4511
  init_outputContractHooks();
4470
4512
  init_runtimePaths();
4471
4513
  init_subagents();
@@ -4488,7 +4530,7 @@ var init_agent = __esm({
4488
4530
 
4489
4531
  // src/agents.ts
4490
4532
  import * as fs13 from "fs";
4491
- import * as path14 from "path";
4533
+ import * as path15 from "path";
4492
4534
  function stripFrontmatter(raw) {
4493
4535
  const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
4494
4536
  return (match ? match[1] : raw).trim();
@@ -4509,7 +4551,7 @@ function loadAgentIdentity(cwd, slug, agentsDir = agentsRoot(cwd)) {
4509
4551
  throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
4510
4552
  }
4511
4553
  function resolveAgentFile2(cwd, slug, agentsDir = agentsRoot(cwd)) {
4512
- const localPath = path14.resolve(cwd, agentsDir, `${slug}.md`);
4554
+ const localPath = path15.resolve(cwd, agentsDir, `${slug}.md`);
4513
4555
  if (fs13.existsSync(localPath)) return localPath;
4514
4556
  return localPath;
4515
4557
  }
@@ -4543,7 +4585,7 @@ var init_agents = __esm({
4543
4585
 
4544
4586
  // src/task-artifacts.ts
4545
4587
  import fs14 from "fs";
4546
- import path15 from "path";
4588
+ import path16 from "path";
4547
4589
  import posixPath from "path/posix";
4548
4590
  function prepareTaskArtifactsDir(cwd, taskId) {
4549
4591
  const safeId = String(taskId).replace(/[^a-zA-Z0-9._-]/g, "_");
@@ -4579,14 +4621,14 @@ function initializeTaskArtifacts(artifacts, metadata = { taskType: "job" }) {
4579
4621
  "handoff-notes.md": "Baseline handoff: the agent did not provide additional notes.\n"
4580
4622
  };
4581
4623
  for (const file of TASK_ARTIFACT_FILES) {
4582
- const full = path15.join(artifacts.absDir, file);
4624
+ const full = path16.join(artifacts.absDir, file);
4583
4625
  if (!fs14.existsSync(full)) fs14.writeFileSync(full, defaults[file], "utf8");
4584
4626
  }
4585
4627
  }
4586
4628
  function verifyTaskArtifacts(absDir) {
4587
4629
  const missing = [];
4588
4630
  for (const name of TASK_ARTIFACT_FILES) {
4589
- const full = path15.join(absDir, name);
4631
+ const full = path16.join(absDir, name);
4590
4632
  try {
4591
4633
  const stat = fs14.statSync(full);
4592
4634
  if (!stat.isFile() || stat.size === 0) missing.push(name);
@@ -4604,7 +4646,7 @@ async function persistTaskArtifactsToState(config, _cwd, artifacts) {
4604
4646
  if (hasStateBackendConfig() && tenantId2) {
4605
4647
  const backend = createStateBackendFromEnv();
4606
4648
  for (const file of TASK_ARTIFACT_FILES) {
4607
- const full = path15.join(artifacts.absDir, file);
4649
+ const full = path16.join(artifacts.absDir, file);
4608
4650
  if (!fs14.existsSync(full)) continue;
4609
4651
  const stat = fs14.statSync(full);
4610
4652
  if (!stat.isFile() || stat.size === 0) continue;
@@ -4917,15 +4959,15 @@ function validateWorkflow(value, options = {}) {
4917
4959
  }
4918
4960
  return issues;
4919
4961
  }
4920
- function validateInputBindings(value, path58, issues, declaredInputs) {
4962
+ function validateInputBindings(value, path59, issues, declaredInputs) {
4921
4963
  if (value === void 0) return;
4922
4964
  const bindings = asRecord(value);
4923
4965
  if (!bindings || Object.keys(bindings).length === 0) {
4924
- issue(issues, "invalid_inputs", path58, "workflow step inputs must contain at least one named mapping");
4966
+ issue(issues, "invalid_inputs", path59, "workflow step inputs must contain at least one named mapping");
4925
4967
  return;
4926
4968
  }
4927
4969
  for (const [name, value2] of Object.entries(bindings)) {
4928
- const bindingPath = `${path58}.${name}`;
4970
+ const bindingPath = `${path59}.${name}`;
4929
4971
  if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(name)) {
4930
4972
  issue(issues, "invalid_input_name", bindingPath, `workflow input name ${name} is invalid`);
4931
4973
  }
@@ -4944,7 +4986,7 @@ function validateInputBindings(value, path58, issues, declaredInputs) {
4944
4986
  }
4945
4987
  }
4946
4988
  }
4947
- function validateInputBindingSources(value, path58, issues, capabilitiesByStep, capabilityOutputs) {
4989
+ function validateInputBindingSources(value, path59, issues, capabilitiesByStep, capabilityOutputs) {
4948
4990
  const bindings = asRecord(value);
4949
4991
  if (!bindings) return;
4950
4992
  for (const [name, rawBinding] of Object.entries(bindings)) {
@@ -4957,7 +4999,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
4957
4999
  issue(
4958
5000
  issues,
4959
5001
  "missing_input_step",
4960
- `${path58}.${name}.from`,
5002
+ `${path59}.${name}.from`,
4961
5003
  `workflow input mapping references missing step ${sourceStep ?? "<none>"}`
4962
5004
  );
4963
5005
  continue;
@@ -4968,7 +5010,7 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
4968
5010
  issue(
4969
5011
  issues,
4970
5012
  "undeclared_step_output",
4971
- `${path58}.${name}.from`,
5013
+ `${path59}.${name}.from`,
4972
5014
  `workflow input mapping reads ${outputPath}, but step ${sourceStep} does not declare it`
4973
5015
  );
4974
5016
  }
@@ -4977,11 +5019,11 @@ function validateInputBindingSources(value, path58, issues, capabilitiesByStep,
4977
5019
  function formatWorkflowValidationIssues(issues) {
4978
5020
  return issues.map((entry) => `${entry.path}: ${entry.message}`);
4979
5021
  }
4980
- function validateDataMatch(value, path58, issues, capabilityOutputs) {
5022
+ function validateDataMatch(value, path59, issues, capabilityOutputs) {
4981
5023
  if (value === void 0) return;
4982
5024
  const match = asRecord(value);
4983
5025
  if (!match || Object.keys(match).length === 0) {
4984
- issue(issues, "invalid_condition", path58, "workflow condition must contain at least one match");
5026
+ issue(issues, "invalid_condition", path59, "workflow condition must contain at least one match");
4985
5027
  return;
4986
5028
  }
4987
5029
  for (const [field, expected] of Object.entries(match)) {
@@ -4989,7 +5031,7 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
4989
5031
  issue(
4990
5032
  issues,
4991
5033
  "invalid_data_path",
4992
- `${path58}.${field}`,
5034
+ `${path59}.${field}`,
4993
5035
  `workflow condition must read from facts, evidence, artifacts, result, workflow, or lastOutcome`
4994
5036
  );
4995
5037
  }
@@ -4997,12 +5039,12 @@ function validateDataMatch(value, path58, issues, capabilityOutputs) {
4997
5039
  issue(
4998
5040
  issues,
4999
5041
  "undeclared_result_path",
5000
- `${path58}.${field}`,
5042
+ `${path59}.${field}`,
5001
5043
  `workflow condition reads ${field}, but the source capability does not declare it`
5002
5044
  );
5003
5045
  }
5004
5046
  if (!isComparable(expected)) {
5005
- issue(issues, "invalid_condition_value", `${path58}.${field}`, "workflow condition value must be a JSON scalar");
5047
+ issue(issues, "invalid_condition_value", `${path59}.${field}`, "workflow condition value must be a JSON scalar");
5006
5048
  }
5007
5049
  }
5008
5050
  }
@@ -5026,8 +5068,8 @@ function isJsonValue(value) {
5026
5068
  if (!value || typeof value !== "object") return false;
5027
5069
  return Object.values(value).every(isJsonValue);
5028
5070
  }
5029
- function issue(issues, code, path58, message) {
5030
- issues.push({ code, path: path58, message });
5071
+ function issue(issues, code, path59, message) {
5072
+ issues.push({ code, path: path59, message });
5031
5073
  }
5032
5074
  var SAFE_NAME, SAFE_STEP_ID, SAFE_DATA_PATH, SAFE_INPUT_SOURCE, SUPPORTED_STEP_FIELDS, SUPPORTED_TRANSITION_FIELDS;
5033
5075
  var init_workflowValidation = __esm({
@@ -5061,7 +5103,7 @@ var init_workflowValidation = __esm({
5061
5103
 
5062
5104
  // src/workflowDefinitions.ts
5063
5105
  import * as fs20 from "fs";
5064
- import * as path21 from "path";
5106
+ import * as path22 from "path";
5065
5107
  function isWorkflowDefinitionId(value) {
5066
5108
  return WORKFLOW_ID_PATTERN.test(value);
5067
5109
  }
@@ -5106,8 +5148,8 @@ function readWorkflowDefinition(_config, cwd, id) {
5106
5148
  const root = cwd ?? process.cwd();
5107
5149
  const relativePath = workflowDefinitionPath(id);
5108
5150
  const candidates = [
5109
- path21.join(root, ".kody-engine", "runtime", relativePath),
5110
- path21.join(definitionsRoot(root), relativePath)
5151
+ path22.join(root, ".kody-engine", "runtime", relativePath),
5152
+ path22.join(definitionsRoot(root), relativePath)
5111
5153
  ];
5112
5154
  for (const filePath of candidates) {
5113
5155
  if (!fs20.existsSync(filePath)) continue;
@@ -5119,7 +5161,7 @@ function readWorkflowDefinition(_config, cwd, id) {
5119
5161
  function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
5120
5162
  return {
5121
5163
  slug: id,
5122
- dir: path21.dirname(source),
5164
+ dir: path22.dirname(source),
5123
5165
  profilePath: source,
5124
5166
  bodyPath: source,
5125
5167
  title: workflow.name,
@@ -5720,7 +5762,7 @@ var init_lifecycles = __esm({
5720
5762
  // src/profile.ts
5721
5763
  import { createHash as createHash3 } from "crypto";
5722
5764
  import * as fs24 from "fs";
5723
- import * as path23 from "path";
5765
+ import * as path24 from "path";
5724
5766
  function loadProfile(profilePath) {
5725
5767
  if (!fs24.existsSync(profilePath)) {
5726
5768
  throw new ProfileError(profilePath, "file not found");
@@ -5739,7 +5781,7 @@ function loadProfile(profilePath) {
5739
5781
  const unknownKeys = Object.keys(r).filter((k) => !KNOWN_PROFILE_KEYS.has(k));
5740
5782
  if (unknownKeys.length > 0) {
5741
5783
  process.stderr.write(
5742
- `[kody profile] ${path23.basename(path23.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
5784
+ `[kody profile] ${path24.basename(path24.dirname(profilePath))}: unknown top-level keys ignored: ${unknownKeys.join(", ")}
5743
5785
  `
5744
5786
  );
5745
5787
  }
@@ -5749,7 +5791,7 @@ function loadProfile(profilePath) {
5749
5791
  if (!refPath) {
5750
5792
  throw new ProfileError(profilePath, `capability references unknown implementation '${execRef}'`);
5751
5793
  }
5752
- if (path23.resolve(refPath) === path23.resolve(profilePath)) {
5794
+ if (path24.resolve(refPath) === path24.resolve(profilePath)) {
5753
5795
  } else {
5754
5796
  const base = loadProfile(refPath);
5755
5797
  return {
@@ -5847,8 +5889,8 @@ function loadProfile(profilePath) {
5847
5889
  // Phase 5 in-process handoff opt-in. Default false; containers
5848
5890
  // flip to true after end-to-end verification.
5849
5891
  preloadContext: r.preloadContext === true,
5850
- dir: path23.dirname(profilePath),
5851
- promptTemplates: readPromptTemplates(path23.dirname(profilePath))
5892
+ dir: path24.dirname(profilePath),
5893
+ promptTemplates: readPromptTemplates(path24.dirname(profilePath))
5852
5894
  };
5853
5895
  if (lifecycle) {
5854
5896
  applyLifecycle(profile, profilePath);
@@ -5883,19 +5925,19 @@ function loadProfile(profilePath) {
5883
5925
  return profile;
5884
5926
  }
5885
5927
  function compileRuntimeDocument(runtimePath, document) {
5886
- if (path23.basename(runtimePath) !== "runtime.json") return document;
5928
+ if (path24.basename(runtimePath) !== "runtime.json") return document;
5887
5929
  if (document.adapter !== "kody-engine-profile") {
5888
5930
  throw new ProfileError(runtimePath, "unsupported runtime adapter document");
5889
5931
  }
5890
- const implementationDir = path23.dirname(runtimePath);
5891
- const implementation = readJsonObject(path23.join(implementationDir, "definition.json"), "Implementation definition");
5892
- const definitionsRoot2 = path23.dirname(path23.dirname(implementationDir));
5932
+ const implementationDir = path24.dirname(runtimePath);
5933
+ const implementation = readJsonObject(path24.join(implementationDir, "definition.json"), "Implementation definition");
5934
+ const definitionsRoot2 = path24.dirname(path24.dirname(implementationDir));
5893
5935
  const capabilityId = implementation.capabilityRef && typeof implementation.capabilityRef === "object" && !Array.isArray(implementation.capabilityRef) ? implementation.capabilityRef.id : void 0;
5894
5936
  if (typeof capabilityId !== "string" || !capabilityId) {
5895
5937
  throw new ProfileError(runtimePath, "Implementation capabilityRef is invalid");
5896
5938
  }
5897
5939
  const capability = readJsonObject(
5898
- path23.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
5940
+ path24.join(definitionsRoot2, "capabilities", capabilityId, "definition.json"),
5899
5941
  "Capability definition"
5900
5942
  );
5901
5943
  const {
@@ -5956,13 +5998,13 @@ function readPromptTemplates(dir) {
5956
5998
  } catch {
5957
5999
  }
5958
6000
  };
5959
- read(path23.join(dir, "prompt.md"));
5960
- read(path23.join(dir, "capability.md"));
5961
- read(path23.join(dir, "capability.md"));
6001
+ read(path24.join(dir, "prompt.md"));
6002
+ read(path24.join(dir, "capability.md"));
6003
+ read(path24.join(dir, "capability.md"));
5962
6004
  try {
5963
- const promptsDir = path23.join(dir, "prompts");
6005
+ const promptsDir = path24.join(dir, "prompts");
5964
6006
  for (const ent of fs24.readdirSync(promptsDir)) {
5965
- if (ent.endsWith(".md")) read(path23.join(promptsDir, ent));
6007
+ if (ent.endsWith(".md")) read(path24.join(promptsDir, ent));
5966
6008
  }
5967
6009
  } catch {
5968
6010
  }
@@ -6740,11 +6782,11 @@ var init_state = __esm({
6740
6782
 
6741
6783
  // src/prompt.ts
6742
6784
  import * as fs25 from "fs";
6743
- import * as path24 from "path";
6785
+ import * as path25 from "path";
6744
6786
  function loadProjectConventions(projectDir) {
6745
6787
  const out = [];
6746
6788
  for (const rel of CONVENTION_FILES) {
6747
- const abs = path24.join(projectDir, rel);
6789
+ const abs = path25.join(projectDir, rel);
6748
6790
  if (!fs25.existsSync(abs)) continue;
6749
6791
  let content;
6750
6792
  try {
@@ -6984,7 +7026,7 @@ __export(loadMemoryContext_exports, {
6984
7026
  loadMemoryContext: () => loadMemoryContext
6985
7027
  });
6986
7028
  import * as fs26 from "fs";
6987
- import * as path25 from "path";
7029
+ import * as path26 from "path";
6988
7030
  function formatBlockFromBackend(docs) {
6989
7031
  const pages = docs.flatMap((record2) => {
6990
7032
  if (!record2.doc || typeof record2.doc !== "object") return [];
@@ -7018,10 +7060,10 @@ function collectPages(memoryAbs) {
7018
7060
  return;
7019
7061
  }
7020
7062
  const fm = raw.match(/^---\s*\n([\s\S]*?)\n---/);
7021
- const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path25.basename(file, ".md");
7063
+ const title = fm?.[1]?.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path26.basename(file, ".md");
7022
7064
  const updated = fm?.[1]?.match(/^updated:\s*([0-9T:.+\-Z]+)/m)?.[1]?.trim() ?? "";
7023
7065
  out.push({
7024
- relPath: path25.relative(memoryAbs, file),
7066
+ relPath: path26.relative(memoryAbs, file),
7025
7067
  title,
7026
7068
  updated,
7027
7069
  content: raw.length > PER_PAGE_MAX_BYTES ? raw.slice(0, PER_PAGE_MAX_BYTES) + TRUNCATED_SUFFIX2 : raw,
@@ -7095,7 +7137,7 @@ function walkMd(root, visit) {
7095
7137
  }
7096
7138
  for (const name of names) {
7097
7139
  if (name.startsWith(".")) continue;
7098
- const full = path25.join(dir, name);
7140
+ const full = path26.join(dir, name);
7099
7141
  let stat;
7100
7142
  try {
7101
7143
  stat = fs26.statSync(full);
@@ -7133,7 +7175,7 @@ var init_loadMemoryContext = __esm({
7133
7175
  }
7134
7176
  return;
7135
7177
  }
7136
- const memoryAbs = path25.join(ctx.cwd, MEMORY_DIR_RELATIVE);
7178
+ const memoryAbs = path26.join(ctx.cwd, MEMORY_DIR_RELATIVE);
7137
7179
  if (!fs26.existsSync(memoryAbs)) {
7138
7180
  ctx.data.memoryContext = "";
7139
7181
  return;
@@ -7649,7 +7691,7 @@ import { execFileSync as execFileSync4, spawn as spawn4 } from "child_process";
7649
7691
  import * as fs28 from "fs";
7650
7692
  import * as net from "net";
7651
7693
  import * as os4 from "os";
7652
- import * as path26 from "path";
7694
+ import * as path27 from "path";
7653
7695
  async function checkLitellmHealth(url) {
7654
7696
  try {
7655
7697
  const response = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3e3) });
@@ -7762,10 +7804,10 @@ async function startLitellmIfNeeded(model, projectDir, url = LITELLM_DEFAULT_URL
7762
7804
  const spawnProxy = () => {
7763
7805
  const portMatch = activeUrl.match(/:(\d+)/);
7764
7806
  const port = portMatch ? portMatch[1] : "4000";
7765
- const configPath = path26.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
7807
+ const configPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.yaml`);
7766
7808
  fs28.writeFileSync(configPath, generateLitellmConfigYaml(model));
7767
7809
  const args = ["--config", configPath, "--port", port];
7768
- const nextLogPath = path26.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
7810
+ const nextLogPath = path27.join(os4.tmpdir(), `kody-local-litellm-${Date.now()}.log`);
7769
7811
  const outFd = fs28.openSync(nextLogPath, "w");
7770
7812
  child = spawn4(cmd, args, { stdio: ["ignore", outFd, outFd], detached: true, env: childEnv });
7771
7813
  fs28.closeSync(outFd);
@@ -7855,17 +7897,17 @@ async function nextAvailableLitellmUrl(url) {
7855
7897
  throw new Error(`no free LiteLLM port found after ${startPort}`);
7856
7898
  }
7857
7899
  function canListen(port, host) {
7858
- return new Promise((resolve23) => {
7900
+ return new Promise((resolve24) => {
7859
7901
  const server = net.createServer();
7860
- server.once("error", () => resolve23(false));
7902
+ server.once("error", () => resolve24(false));
7861
7903
  server.once("listening", () => {
7862
- server.close(() => resolve23(true));
7904
+ server.close(() => resolve24(true));
7863
7905
  });
7864
7906
  server.listen(port, host);
7865
7907
  });
7866
7908
  }
7867
7909
  function readDotenvApiKeys(projectDir) {
7868
- const dotenvPath = path26.join(projectDir, ".env");
7910
+ const dotenvPath = path27.join(projectDir, ".env");
7869
7911
  if (!fs28.existsSync(dotenvPath)) return {};
7870
7912
  const result = {};
7871
7913
  for (const rawLine of fs28.readFileSync(dotenvPath, "utf-8").split("\n")) {
@@ -8528,7 +8570,7 @@ var init_pushWithRetry = __esm({
8528
8570
  // src/commit.ts
8529
8571
  import { execFileSync as execFileSync6 } from "child_process";
8530
8572
  import * as fs29 from "fs";
8531
- import * as path27 from "path";
8573
+ import * as path28 from "path";
8532
8574
  function isGitHubYamlPath(filePath) {
8533
8575
  const normalized = filePath.replace(/^\.\/+/, "");
8534
8576
  return normalized.startsWith(".github/") && /\.ya?ml$/i.test(normalized);
@@ -8570,18 +8612,18 @@ function ensureGitIdentity(cwd) {
8570
8612
  }
8571
8613
  function abortUnfinishedGitOps(cwd) {
8572
8614
  const aborted = [];
8573
- const gitDir = path27.join(cwd ?? process.cwd(), ".git");
8615
+ const gitDir = path28.join(cwd ?? process.cwd(), ".git");
8574
8616
  if (!fs29.existsSync(gitDir)) return aborted;
8575
- if (fs29.existsSync(path27.join(gitDir, "MERGE_HEAD"))) {
8617
+ if (fs29.existsSync(path28.join(gitDir, "MERGE_HEAD"))) {
8576
8618
  if (tryGit(["merge", "--abort"], cwd)) aborted.push("merge");
8577
8619
  }
8578
- if (fs29.existsSync(path27.join(gitDir, "CHERRY_PICK_HEAD"))) {
8620
+ if (fs29.existsSync(path28.join(gitDir, "CHERRY_PICK_HEAD"))) {
8579
8621
  if (tryGit(["cherry-pick", "--abort"], cwd)) aborted.push("cherry-pick");
8580
8622
  }
8581
- if (fs29.existsSync(path27.join(gitDir, "REVERT_HEAD"))) {
8623
+ if (fs29.existsSync(path28.join(gitDir, "REVERT_HEAD"))) {
8582
8624
  if (tryGit(["revert", "--abort"], cwd)) aborted.push("revert");
8583
8625
  }
8584
- if (fs29.existsSync(path27.join(gitDir, "rebase-merge")) || fs29.existsSync(path27.join(gitDir, "rebase-apply"))) {
8626
+ if (fs29.existsSync(path28.join(gitDir, "rebase-merge")) || fs29.existsSync(path28.join(gitDir, "rebase-apply"))) {
8585
8627
  if (tryGit(["rebase", "--abort"], cwd)) aborted.push("rebase");
8586
8628
  }
8587
8629
  try {
@@ -8638,7 +8680,7 @@ function normalizeCommitMessage(raw) {
8638
8680
  function commitAndPush(branch, agentMessage, cwd) {
8639
8681
  const allChanged = listChangedFiles(cwd);
8640
8682
  const allowedFiles = allChanged.filter((f) => !isForbiddenPath(f));
8641
- const mergeHeadExists = fs29.existsSync(path27.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
8683
+ const mergeHeadExists = fs29.existsSync(path28.join(cwd ?? process.cwd(), ".git", "MERGE_HEAD"));
8642
8684
  if (allowedFiles.length === 0 && !mergeHeadExists) {
8643
8685
  return { committed: false, pushed: false, sha: "", message: "" };
8644
8686
  }
@@ -9282,9 +9324,9 @@ import * as fs30 from "fs";
9282
9324
  function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
9283
9325
  const logs = goalRunLogs(data);
9284
9326
  const existing = logs[goalId];
9285
- const path58 = existing?.path ?? goalRunLogPath(goalId, data);
9327
+ const path59 = existing?.path ?? goalRunLogPath(goalId, data);
9286
9328
  logs[goalId] = {
9287
- path: path58,
9329
+ path: path59,
9288
9330
  events: [...existing?.events ?? [], buildGoalRunLogEvent(data, goalId, event, at)]
9289
9331
  };
9290
9332
  }
@@ -9732,7 +9774,7 @@ var init_stateStore = __esm({
9732
9774
 
9733
9775
  // src/goal/targetLoopResolution.ts
9734
9776
  import * as fs31 from "fs";
9735
- import * as path28 from "path";
9777
+ import * as path29 from "path";
9736
9778
  async function resolveActiveGoalLoopTarget(config, cwd, loopGoalId, loopGoal) {
9737
9779
  const targetId = loopGoal.loopTarget?.id.trim() ?? "";
9738
9780
  assertSafeGoalId(targetId, "loop target");
@@ -9810,7 +9852,7 @@ function goalInstanceTime(state) {
9810
9852
  return Number.isNaN(parsed) ? 0 : parsed;
9811
9853
  }
9812
9854
  function loadGoalTemplate(cwd, targetId) {
9813
- return readJsonObject2(path28.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
9855
+ return readJsonObject2(path29.join(cwd, ".kody-engine", "definitions", "goals", targetId, "state.json"));
9814
9856
  }
9815
9857
  function readJsonObject2(filePath) {
9816
9858
  if (!fs31.existsSync(filePath)) return null;
@@ -10161,15 +10203,15 @@ var init_backendStateBackend = __esm({
10161
10203
  this.jobsDir = opts.jobsDir.replace(/\/+$/, "");
10162
10204
  }
10163
10205
  async load(slug) {
10164
- const path58 = stateFilePath(this.jobsDir, slug);
10206
+ const path59 = stateFilePath(this.jobsDir, slug);
10165
10207
  const loaded = await createStateBackendFromEnv().get(this.tenantId, `capabilities/${slug}`, "job-state");
10166
10208
  if (!loaded) {
10167
- return { path: path58, handle: null, state: initialStateEnvelope("seed"), created: true };
10209
+ return { path: path59, handle: null, state: initialStateEnvelope("seed"), created: true };
10168
10210
  }
10169
10211
  if (!isStateEnvelope(loaded.doc)) {
10170
10212
  throw new Error(`BackendStateBackend: capabilities/${slug} is not a StateEnvelope`);
10171
10213
  }
10172
- return { path: path58, handle: loaded.updatedAt, state: loaded.doc, created: false };
10214
+ return { path: path59, handle: loaded.updatedAt, state: loaded.doc, created: false };
10173
10215
  }
10174
10216
  async save(loaded, next) {
10175
10217
  if (!loaded.created && isStateUnchanged(loaded.state, next)) return false;
@@ -10190,7 +10232,7 @@ var init_backendStateBackend = __esm({
10190
10232
 
10191
10233
  // src/scripts/jobState/localFileBackend.ts
10192
10234
  import * as fs32 from "fs";
10193
- import * as path29 from "path";
10235
+ import * as path30 from "path";
10194
10236
  function sanitizeKey(s) {
10195
10237
  return s.replace(/[^A-Za-z0-9._-]/g, "-");
10196
10238
  }
@@ -10246,7 +10288,7 @@ var init_localFileBackend = __esm({
10246
10288
  if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
10247
10289
  this.cwd = opts.cwd;
10248
10290
  this.jobsDir = opts.jobsDir;
10249
- this.absDir = path29.resolve(opts.cwd, opts.jobsDir);
10291
+ this.absDir = path30.resolve(opts.cwd, opts.jobsDir);
10250
10292
  this.owner = opts.owner;
10251
10293
  this.repo = opts.repo;
10252
10294
  this.cache = opts.cache ?? defaultCacheAdapter();
@@ -10306,7 +10348,7 @@ var init_localFileBackend = __esm({
10306
10348
  }
10307
10349
  load(slug) {
10308
10350
  const relPath = stateFilePath(this.jobsDir, slug);
10309
- const absPath = path29.resolve(this.cwd, relPath);
10351
+ const absPath = path30.resolve(this.cwd, relPath);
10310
10352
  if (!fs32.existsSync(absPath)) {
10311
10353
  return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
10312
10354
  }
@@ -10327,8 +10369,8 @@ var init_localFileBackend = __esm({
10327
10369
  if (!loaded.created && isStateUnchanged(loaded.state, next)) {
10328
10370
  return false;
10329
10371
  }
10330
- const absPath = path29.resolve(this.cwd, loaded.path);
10331
- fs32.mkdirSync(path29.dirname(absPath), { recursive: true });
10372
+ const absPath = path30.resolve(this.cwd, loaded.path);
10373
+ fs32.mkdirSync(path30.dirname(absPath), { recursive: true });
10332
10374
  const body = `${JSON.stringify(next, null, 2)}
10333
10375
  `;
10334
10376
  const tmpPath = `${absPath}.${process.pid}.tmp`;
@@ -10365,7 +10407,7 @@ var init_jobState = __esm({
10365
10407
  });
10366
10408
 
10367
10409
  // src/scripts/goalCapabilityScheduling.ts
10368
- import * as path30 from "path";
10410
+ import * as path31 from "path";
10369
10411
  function isCapabilityCadenceGoal(goal, extra) {
10370
10412
  return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
10371
10413
  }
@@ -10421,7 +10463,7 @@ function planTargetLoopSchedule(opts) {
10421
10463
  }
10422
10464
  async function planGoalCapabilitySchedule(opts) {
10423
10465
  const jobsDir = opts.jobsDir ?? capabilitiesRoot(opts.cwd);
10424
- const jobsRoot = path30.resolve(opts.cwd, jobsDir);
10466
+ const jobsRoot = path31.resolve(opts.cwd, jobsDir);
10425
10467
  const now = opts.now ?? /* @__PURE__ */ new Date();
10426
10468
  const at = now.toISOString();
10427
10469
  const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
@@ -12238,7 +12280,7 @@ var init_classifyByLabel = __esm({
12238
12280
  // src/scripts/commitAndPush.ts
12239
12281
  import { createHash as createHash5 } from "crypto";
12240
12282
  import * as fs33 from "fs";
12241
- import * as path31 from "path";
12283
+ import * as path32 from "path";
12242
12284
  function sentinelPathForStage(cwd, profileName, workflowExecutionKey) {
12243
12285
  const runId = resolveRunId();
12244
12286
  const executionSuffix = typeof workflowExecutionKey === "string" && workflowExecutionKey.length > 0 ? `-${createHash5("sha256").update(workflowExecutionKey).digest("hex").slice(0, 16)}` : "";
@@ -12322,7 +12364,7 @@ var init_commitAndPush = __esm({
12322
12364
  const result = ctx.data.commitResult;
12323
12365
  if (sentinel && result?.committed) {
12324
12366
  try {
12325
- fs33.mkdirSync(path31.dirname(sentinel), { recursive: true });
12367
+ fs33.mkdirSync(path32.dirname(sentinel), { recursive: true });
12326
12368
  fs33.writeFileSync(
12327
12369
  sentinel,
12328
12370
  JSON.stringify(
@@ -12418,7 +12460,7 @@ var init_commitGoalState = __esm({
12418
12460
 
12419
12461
  // src/scripts/composePrompt.ts
12420
12462
  import * as fs34 from "fs";
12421
- import * as path32 from "path";
12463
+ import * as path33 from "path";
12422
12464
  function fenceUntrusted(value) {
12423
12465
  if (value.trim().length === 0) return value;
12424
12466
  const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
@@ -12542,10 +12584,10 @@ var init_composePrompt = __esm({
12542
12584
  const explicit = ctx.data.promptTemplate;
12543
12585
  const mode = ctx.args.mode;
12544
12586
  const candidates = [
12545
- explicit ? path32.join(profile.dir, explicit) : null,
12546
- mode ? path32.join(profile.dir, "prompts", `${mode}.md`) : null,
12547
- path32.join(profile.dir, "prompt.md"),
12548
- path32.join(profile.dir, "capability.md")
12587
+ explicit ? path33.join(profile.dir, explicit) : null,
12588
+ mode ? path33.join(profile.dir, "prompts", `${mode}.md`) : null,
12589
+ path33.join(profile.dir, "prompt.md"),
12590
+ path33.join(profile.dir, "capability.md")
12549
12591
  ].filter(Boolean);
12550
12592
  let templatePath = "";
12551
12593
  let template = "";
@@ -13305,14 +13347,14 @@ var init_deriveQaScopeFromIssue = __esm({
13305
13347
  import { execFileSync as execFileSync9 } from "child_process";
13306
13348
  import * as fs35 from "fs";
13307
13349
  import * as os5 from "os";
13308
- import * as path33 from "path";
13350
+ import * as path34 from "path";
13309
13351
  var diagMcp;
13310
13352
  var init_diagMcp = __esm({
13311
13353
  "src/scripts/diagMcp.ts"() {
13312
13354
  "use strict";
13313
13355
  diagMcp = async (_ctx) => {
13314
13356
  const home = os5.homedir();
13315
- const cacheDir = path33.join(home, ".cache", "ms-playwright");
13357
+ const cacheDir = path34.join(home, ".cache", "ms-playwright");
13316
13358
  let entries = [];
13317
13359
  try {
13318
13360
  entries = fs35.readdirSync(cacheDir);
@@ -13344,12 +13386,12 @@ var init_diagMcp = __esm({
13344
13386
 
13345
13387
  // src/scripts/frameworkDetectors.ts
13346
13388
  import * as fs36 from "fs";
13347
- import * as path34 from "path";
13389
+ import * as path35 from "path";
13348
13390
  function detectFrameworks(cwd) {
13349
13391
  const out = [];
13350
13392
  let deps = {};
13351
13393
  try {
13352
- const pkg = JSON.parse(fs36.readFileSync(path34.join(cwd, "package.json"), "utf-8"));
13394
+ const pkg = JSON.parse(fs36.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
13353
13395
  deps = { ...pkg.dependencies, ...pkg.devDependencies };
13354
13396
  } catch {
13355
13397
  return out;
@@ -13386,14 +13428,14 @@ function detectFrameworks(cwd) {
13386
13428
  }
13387
13429
  function findFile(cwd, candidates) {
13388
13430
  for (const c of candidates) {
13389
- if (fs36.existsSync(path34.join(cwd, c))) return c;
13431
+ if (fs36.existsSync(path35.join(cwd, c))) return c;
13390
13432
  }
13391
13433
  return null;
13392
13434
  }
13393
13435
  function discoverPayloadCollections(cwd) {
13394
13436
  const out = [];
13395
13437
  for (const dir of COLLECTION_DIRS) {
13396
- const full = path34.join(cwd, dir);
13438
+ const full = path35.join(cwd, dir);
13397
13439
  if (!fs36.existsSync(full)) continue;
13398
13440
  let files;
13399
13441
  try {
@@ -13403,7 +13445,7 @@ function discoverPayloadCollections(cwd) {
13403
13445
  }
13404
13446
  for (const file of files) {
13405
13447
  try {
13406
- const filePath = path34.join(full, file);
13448
+ const filePath = path35.join(full, file);
13407
13449
  const content = fs36.readFileSync(filePath, "utf-8").slice(0, 1e4);
13408
13450
  const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
13409
13451
  if (!slugMatch) continue;
@@ -13418,7 +13460,7 @@ function discoverPayloadCollections(cwd) {
13418
13460
  out.push({
13419
13461
  name,
13420
13462
  slug,
13421
- filePath: path34.relative(cwd, filePath),
13463
+ filePath: path35.relative(cwd, filePath),
13422
13464
  fields: fields.slice(0, 20),
13423
13465
  hasAdmin
13424
13466
  });
@@ -13431,7 +13473,7 @@ function discoverPayloadCollections(cwd) {
13431
13473
  function discoverAdminComponents(cwd, collections) {
13432
13474
  const out = [];
13433
13475
  for (const dir of ADMIN_COMPONENT_DIRS) {
13434
- const full = path34.join(cwd, dir);
13476
+ const full = path35.join(cwd, dir);
13435
13477
  if (!fs36.existsSync(full)) continue;
13436
13478
  let entries;
13437
13479
  try {
@@ -13440,19 +13482,19 @@ function discoverAdminComponents(cwd, collections) {
13440
13482
  continue;
13441
13483
  }
13442
13484
  for (const entry of entries) {
13443
- const entryPath = path34.join(full, entry.name);
13485
+ const entryPath = path35.join(full, entry.name);
13444
13486
  let name;
13445
13487
  let filePath;
13446
13488
  if (entry.isDirectory()) {
13447
13489
  const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
13448
- (f) => fs36.existsSync(path34.join(entryPath, f))
13490
+ (f) => fs36.existsSync(path35.join(entryPath, f))
13449
13491
  );
13450
13492
  if (!indexFile) continue;
13451
13493
  name = entry.name;
13452
- filePath = path34.relative(cwd, path34.join(entryPath, indexFile));
13494
+ filePath = path35.relative(cwd, path35.join(entryPath, indexFile));
13453
13495
  } else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
13454
13496
  name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
13455
- filePath = path34.relative(cwd, entryPath);
13497
+ filePath = path35.relative(cwd, entryPath);
13456
13498
  } else {
13457
13499
  continue;
13458
13500
  }
@@ -13460,7 +13502,7 @@ function discoverAdminComponents(cwd, collections) {
13460
13502
  if (collections) {
13461
13503
  for (const col of collections) {
13462
13504
  try {
13463
- const colContent = fs36.readFileSync(path34.join(cwd, col.filePath), "utf-8");
13505
+ const colContent = fs36.readFileSync(path35.join(cwd, col.filePath), "utf-8");
13464
13506
  if (colContent.includes(name)) {
13465
13507
  usedInCollection = col.slug;
13466
13508
  break;
@@ -13478,7 +13520,7 @@ function scanApiRoutes(cwd) {
13478
13520
  const out = [];
13479
13521
  const appDirs = ["src/app", "app"];
13480
13522
  for (const appDir of appDirs) {
13481
- const apiDir = path34.join(cwd, appDir, "api");
13523
+ const apiDir = path35.join(cwd, appDir, "api");
13482
13524
  if (!fs36.existsSync(apiDir)) continue;
13483
13525
  walkApiRoutes(apiDir, "/api", cwd, out);
13484
13526
  break;
@@ -13495,7 +13537,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13495
13537
  const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
13496
13538
  if (routeFile) {
13497
13539
  try {
13498
- const content = fs36.readFileSync(path34.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
13540
+ const content = fs36.readFileSync(path35.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
13499
13541
  const methods = HTTP_METHODS.filter(
13500
13542
  (m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
13501
13543
  );
@@ -13503,7 +13545,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13503
13545
  out.push({
13504
13546
  path: prefix,
13505
13547
  methods,
13506
- filePath: path34.relative(cwd, path34.join(dir, routeFile.name))
13548
+ filePath: path35.relative(cwd, path35.join(dir, routeFile.name))
13507
13549
  });
13508
13550
  }
13509
13551
  } catch {
@@ -13514,7 +13556,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13514
13556
  if (entry.name === "node_modules" || entry.name === ".next") continue;
13515
13557
  let segment = entry.name;
13516
13558
  if (segment.startsWith("(") && segment.endsWith(")")) {
13517
- walkApiRoutes(path34.join(dir, entry.name), prefix, cwd, out);
13559
+ walkApiRoutes(path35.join(dir, entry.name), prefix, cwd, out);
13518
13560
  continue;
13519
13561
  }
13520
13562
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
@@ -13522,13 +13564,13 @@ function walkApiRoutes(dir, prefix, cwd, out) {
13522
13564
  } else if (segment.startsWith("[") && segment.endsWith("]")) {
13523
13565
  segment = `:${segment.slice(1, -1)}`;
13524
13566
  }
13525
- walkApiRoutes(path34.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
13567
+ walkApiRoutes(path35.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
13526
13568
  }
13527
13569
  }
13528
13570
  function scanEnvVars(cwd) {
13529
13571
  const candidates = [".env.example", ".env.local.example", ".env.template"];
13530
13572
  for (const envFile of candidates) {
13531
- const envPath = path34.join(cwd, envFile);
13573
+ const envPath = path35.join(cwd, envFile);
13532
13574
  if (!fs36.existsSync(envPath)) continue;
13533
13575
  try {
13534
13576
  const content = fs36.readFileSync(envPath, "utf-8");
@@ -13577,7 +13619,7 @@ var init_frameworkDetectors = __esm({
13577
13619
 
13578
13620
  // src/scripts/discoverQaContext.ts
13579
13621
  import * as fs37 from "fs";
13580
- import * as path35 from "path";
13622
+ import * as path36 from "path";
13581
13623
  function runQaDiscovery(cwd) {
13582
13624
  const out = {
13583
13625
  routes: [],
@@ -13608,9 +13650,9 @@ function runQaDiscovery(cwd) {
13608
13650
  }
13609
13651
  function detectDevServer(cwd, out) {
13610
13652
  try {
13611
- const pkg = JSON.parse(fs37.readFileSync(path35.join(cwd, "package.json"), "utf-8"));
13653
+ const pkg = JSON.parse(fs37.readFileSync(path36.join(cwd, "package.json"), "utf-8"));
13612
13654
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
13613
- 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";
13655
+ 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";
13614
13656
  if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
13615
13657
  if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
13616
13658
  else if (allDeps.vite) out.devPort = 5173;
@@ -13620,7 +13662,7 @@ function detectDevServer(cwd, out) {
13620
13662
  function scanFrontendRoutes(cwd, out) {
13621
13663
  const appDirs = ["src/app", "app"];
13622
13664
  for (const appDir of appDirs) {
13623
- const full = path35.join(cwd, appDir);
13665
+ const full = path36.join(cwd, appDir);
13624
13666
  if (!fs37.existsSync(full)) continue;
13625
13667
  walkFrontendRoutes(full, "", out);
13626
13668
  break;
@@ -13646,7 +13688,7 @@ function walkFrontendRoutes(dir, prefix, out) {
13646
13688
  if (entry.name === "node_modules" || entry.name === ".next") continue;
13647
13689
  let segment = entry.name;
13648
13690
  if (segment.startsWith("(") && segment.endsWith(")")) {
13649
- walkFrontendRoutes(path35.join(dir, entry.name), prefix, out);
13691
+ walkFrontendRoutes(path36.join(dir, entry.name), prefix, out);
13650
13692
  continue;
13651
13693
  }
13652
13694
  if (segment.startsWith("[[") && segment.endsWith("]]")) {
@@ -13654,7 +13696,7 @@ function walkFrontendRoutes(dir, prefix, out) {
13654
13696
  } else if (segment.startsWith("[") && segment.endsWith("]")) {
13655
13697
  segment = `:${segment.slice(1, -1)}`;
13656
13698
  }
13657
- walkFrontendRoutes(path35.join(dir, entry.name), `${prefix}/${segment}`, out);
13699
+ walkFrontendRoutes(path36.join(dir, entry.name), `${prefix}/${segment}`, out);
13658
13700
  }
13659
13701
  }
13660
13702
  function detectAuthFiles(cwd, out) {
@@ -13671,13 +13713,13 @@ function detectAuthFiles(cwd, out) {
13671
13713
  "src/app/api/oauth"
13672
13714
  ];
13673
13715
  for (const c of candidates) {
13674
- if (fs37.existsSync(path35.join(cwd, c))) out.authFiles.push(c);
13716
+ if (fs37.existsSync(path36.join(cwd, c))) out.authFiles.push(c);
13675
13717
  }
13676
13718
  }
13677
13719
  function detectRoles(cwd, out) {
13678
13720
  const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
13679
13721
  for (const rp of rolePaths) {
13680
- const dir = path35.join(cwd, rp);
13722
+ const dir = path36.join(cwd, rp);
13681
13723
  if (!fs37.existsSync(dir)) continue;
13682
13724
  let files;
13683
13725
  try {
@@ -13687,7 +13729,7 @@ function detectRoles(cwd, out) {
13687
13729
  }
13688
13730
  for (const f of files) {
13689
13731
  try {
13690
- const content = fs37.readFileSync(path35.join(dir, f), "utf-8").slice(0, 5e3);
13732
+ const content = fs37.readFileSync(path36.join(dir, f), "utf-8").slice(0, 5e3);
13691
13733
  const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
13692
13734
  if (roleMatches) {
13693
13735
  for (const m of roleMatches) {
@@ -13949,7 +13991,7 @@ var init_dispatchClassified = __esm({
13949
13991
 
13950
13992
  // src/loopDefinitions.ts
13951
13993
  import * as fs38 from "fs";
13952
- import * as path36 from "path";
13994
+ import * as path37 from "path";
13953
13995
  function normalizeLoopDefinition(value) {
13954
13996
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
13955
13997
  const raw = value;
@@ -13976,7 +14018,7 @@ function readLoopDefinition(cwd, id) {
13976
14018
  if (!ID.test(id)) return null;
13977
14019
  const roots = loopRoots(cwd);
13978
14020
  for (const root of roots) {
13979
- const filePath = path36.join(root, "loops", id, "loop.json");
14021
+ const filePath = path37.join(root, "loops", id, "loop.json");
13980
14022
  if (!fs38.existsSync(filePath)) continue;
13981
14023
  try {
13982
14024
  const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
@@ -13989,7 +14031,7 @@ function readLoopDefinition(cwd, id) {
13989
14031
  }
13990
14032
  }
13991
14033
  process.stderr.write(
13992
- `[kody] Loop not found: ${id} (${roots.map((root) => path36.join(root, "loops", id, "loop.json")).join(", ")})
14034
+ `[kody] Loop not found: ${id} (${roots.map((root) => path37.join(root, "loops", id, "loop.json")).join(", ")})
13993
14035
  `
13994
14036
  );
13995
14037
  return null;
@@ -13998,11 +14040,11 @@ function listLoopDefinitions(cwd) {
13998
14040
  const roots = loopRoots(cwd);
13999
14041
  const byId = /* @__PURE__ */ new Map();
14000
14042
  for (const root of roots.reverse()) {
14001
- const loopsDir = path36.join(root, "loops");
14043
+ const loopsDir = path37.join(root, "loops");
14002
14044
  if (!fs38.existsSync(loopsDir)) continue;
14003
14045
  for (const id of fs38.readdirSync(loopsDir).sort()) {
14004
14046
  if (!ID.test(id)) continue;
14005
- const filePath = path36.join(loopsDir, id, "loop.json");
14047
+ const filePath = path37.join(loopsDir, id, "loop.json");
14006
14048
  if (!fs38.existsSync(filePath)) continue;
14007
14049
  try {
14008
14050
  const loop = normalizeLoopDefinition(JSON.parse(fs38.readFileSync(filePath, "utf8")));
@@ -14017,8 +14059,8 @@ function listLoopDefinitions(cwd) {
14017
14059
  }
14018
14060
  function loopRoots(cwd) {
14019
14061
  return [
14020
- path36.join(cwd, ".kody-engine", "runtime"),
14021
- path36.join(cwd, ".kody-engine", "definitions"),
14062
+ path37.join(cwd, ".kody-engine", "runtime"),
14063
+ path37.join(cwd, ".kody-engine", "definitions"),
14022
14064
  definitionsRoot(cwd)
14023
14065
  ].filter((root, index, roots) => roots.indexOf(root) === index);
14024
14066
  }
@@ -15297,11 +15339,11 @@ var init_fixFlow = __esm({
15297
15339
 
15298
15340
  // src/workflow-template.ts
15299
15341
  import * as fs39 from "fs";
15300
- import * as path37 from "path";
15342
+ import * as path38 from "path";
15301
15343
  import { fileURLToPath } from "url";
15302
15344
  function loadKodyWorkflowTemplate() {
15303
- const here = path37.dirname(fileURLToPath(import.meta.url));
15304
- const candidates = [path37.resolve(here, "../templates/kody.yml"), path37.resolve(here, "../../templates/kody.yml")];
15345
+ const here = path38.dirname(fileURLToPath(import.meta.url));
15346
+ const candidates = [path38.resolve(here, "../templates/kody.yml"), path38.resolve(here, "../../templates/kody.yml")];
15305
15347
  const source = candidates.find((candidate) => fs39.existsSync(candidate));
15306
15348
  if (!source) throw new Error(`Kody workflow template is missing: ${KODY_WORKFLOW_TEMPLATE_PATH}`);
15307
15349
  return fs39.readFileSync(source, "utf8");
@@ -15317,11 +15359,11 @@ var init_workflow_template = __esm({
15317
15359
  // src/scripts/initFlow.ts
15318
15360
  import { execFileSync as execFileSync14 } from "child_process";
15319
15361
  import * as fs40 from "fs";
15320
- import * as path38 from "path";
15362
+ import * as path39 from "path";
15321
15363
  function detectPackageManager(cwd) {
15322
- if (fs40.existsSync(path38.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
15323
- if (fs40.existsSync(path38.join(cwd, "yarn.lock"))) return "yarn";
15324
- if (fs40.existsSync(path38.join(cwd, "bun.lockb"))) return "bun";
15364
+ if (fs40.existsSync(path39.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
15365
+ if (fs40.existsSync(path39.join(cwd, "yarn.lock"))) return "yarn";
15366
+ if (fs40.existsSync(path39.join(cwd, "bun.lockb"))) return "bun";
15325
15367
  return "npm";
15326
15368
  }
15327
15369
  function qualityCommandsFor(pm) {
@@ -15393,7 +15435,7 @@ function performInit(cwd, force) {
15393
15435
  const pm = detectPackageManager(cwd);
15394
15436
  const ownerRepo = detectOwnerRepo(cwd);
15395
15437
  const defaultBranch = defaultBranchFromGit(cwd);
15396
- const configPath = path38.join(cwd, "kody.config.json");
15438
+ const configPath = path39.join(cwd, "kody.config.json");
15397
15439
  if (fs40.existsSync(configPath) && !force) {
15398
15440
  skipped.push("kody.config.json");
15399
15441
  } else {
@@ -15402,8 +15444,8 @@ function performInit(cwd, force) {
15402
15444
  `);
15403
15445
  wrote.push("kody.config.json");
15404
15446
  }
15405
- const workflowDir = path38.join(cwd, ".github", "workflows");
15406
- const workflowPath = path38.join(workflowDir, "kody.yml");
15447
+ const workflowDir = path39.join(cwd, ".github", "workflows");
15448
+ const workflowPath = path39.join(workflowDir, "kody.yml");
15407
15449
  if (fs40.existsSync(workflowPath) && !force) {
15408
15450
  skipped.push(".github/workflows/kody.yml");
15409
15451
  } else {
@@ -15598,13 +15640,13 @@ var init_loadCapabilityState = __esm({
15598
15640
  function isCompanyIntentId(value) {
15599
15641
  return SLUG_RE2.test(value);
15600
15642
  }
15601
- function normalizeCompanyIntent(path58, raw) {
15643
+ function normalizeCompanyIntent(path59, raw) {
15602
15644
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
15603
- throw new Error(`${path58}: intent must be JSON object`);
15645
+ throw new Error(`${path59}: intent must be JSON object`);
15604
15646
  }
15605
15647
  const input = raw;
15606
15648
  const id = stringField4(input.id);
15607
- if (!id || !isCompanyIntentId(id)) throw new Error(`${path58}: invalid intent id`);
15649
+ if (!id || !isCompanyIntentId(id)) throw new Error(`${path59}: invalid intent id`);
15608
15650
  const createdAt = stringField4(input.createdAt) || nowIso();
15609
15651
  const updatedAt = stringField4(input.updatedAt) || createdAt;
15610
15652
  const description = stringField4(input.description);
@@ -15766,7 +15808,7 @@ function retryDelaysMs() {
15766
15808
  }
15767
15809
  function sleep(ms) {
15768
15810
  if (ms <= 0) return Promise.resolve();
15769
- return new Promise((resolve23) => setTimeout(resolve23, ms));
15811
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
15770
15812
  }
15771
15813
  async function fetchGoalStateWithRetry(config, goalId, cwd) {
15772
15814
  let state = await fetchGoalStateAsync(config, goalId, cwd);
@@ -15896,7 +15938,7 @@ var init_loadIssueStateComment = __esm({
15896
15938
 
15897
15939
  // src/scripts/loadJobFromFile.ts
15898
15940
  import * as fs42 from "fs";
15899
- import * as path39 from "path";
15941
+ import * as path40 from "path";
15900
15942
  function parseJobFile(raw, slug) {
15901
15943
  let stripped = raw;
15902
15944
  if (stripped.startsWith("---\n")) {
@@ -15935,10 +15977,10 @@ var init_loadJobFromFile = __esm({
15935
15977
  if (!slug) {
15936
15978
  throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
15937
15979
  }
15938
- const capability = resolveCapabilityFolder(slug, path39.resolve(ctx.cwd, jobsDir));
15980
+ const capability = resolveCapabilityFolder(slug, path40.resolve(ctx.cwd, jobsDir));
15939
15981
  if (!capability) {
15940
15982
  throw new Error(
15941
- `loadJobFromFile: capability folder not found or incomplete: ${path39.resolve(ctx.cwd, jobsDir, slug)}`
15983
+ `loadJobFromFile: capability folder not found or incomplete: ${path40.resolve(ctx.cwd, jobsDir, slug)}`
15942
15984
  );
15943
15985
  }
15944
15986
  const { title, body, config } = capability;
@@ -16034,9 +16076,9 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
16034
16076
 
16035
16077
  // src/scripts/kodyVariables.ts
16036
16078
  import * as fs43 from "fs";
16037
- import * as path40 from "path";
16079
+ import * as path41 from "path";
16038
16080
  function readKodyVariables(cwd) {
16039
- const full = path40.join(cwd, KODY_VARIABLES_REL_PATH);
16081
+ const full = path41.join(cwd, KODY_VARIABLES_REL_PATH);
16040
16082
  let raw;
16041
16083
  try {
16042
16084
  raw = fs43.readFileSync(full, "utf-8");
@@ -16065,7 +16107,7 @@ var init_kodyVariables = __esm({
16065
16107
 
16066
16108
  // src/scripts/loadQaContext.ts
16067
16109
  import * as fs44 from "fs";
16068
- import * as path41 from "path";
16110
+ import * as path42 from "path";
16069
16111
  function parseSlugList(value) {
16070
16112
  const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
16071
16113
  return inner.split(",").map(
@@ -16094,7 +16136,7 @@ function readProfileAgents(raw) {
16094
16136
  return { agent: agent ?? legacy ?? ["kody"], body };
16095
16137
  }
16096
16138
  function readProfile(cwd) {
16097
- const dir = path41.join(cwd, CONTEXT_DIR_REL_PATH);
16139
+ const dir = path42.join(cwd, CONTEXT_DIR_REL_PATH);
16098
16140
  if (!fs44.existsSync(dir)) return "";
16099
16141
  let entries;
16100
16142
  try {
@@ -16105,7 +16147,7 @@ function readProfile(cwd) {
16105
16147
  const blocks = [];
16106
16148
  for (const file of entries) {
16107
16149
  try {
16108
- const raw = fs44.readFileSync(path41.join(dir, file), "utf-8");
16150
+ const raw = fs44.readFileSync(path42.join(dir, file), "utf-8");
16109
16151
  const { agent, body } = readProfileAgents(raw);
16110
16152
  if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
16111
16153
  blocks.push(`## ${file}
@@ -16157,7 +16199,7 @@ var init_loadQaContext = __esm({
16157
16199
  import { randomUUID as randomUUID2 } from "crypto";
16158
16200
  import * as fs45 from "fs";
16159
16201
  import * as os6 from "os";
16160
- import * as path42 from "path";
16202
+ import * as path43 from "path";
16161
16203
  function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
16162
16204
  const subagentFiles = toolFiles.flatMap((file) => {
16163
16205
  const match = /^agents\/([a-z][a-z0-9-]{0,63})\.md$/.exec(file);
@@ -16170,7 +16212,7 @@ function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
16170
16212
  profile.subagentTemplates = {
16171
16213
  ...profile.subagentTemplates ?? {},
16172
16214
  ...Object.fromEntries(
16173
- subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(path42.join(toolRoot, file), "utf-8")])
16215
+ subagentFiles.map(({ name, file }) => [name, fs45.readFileSync(path43.join(toolRoot, file), "utf-8")])
16174
16216
  )
16175
16217
  };
16176
16218
  if (!profile.claudeCode.tools.includes("Agent")) {
@@ -16215,10 +16257,10 @@ function listFiles(root) {
16215
16257
  const files = [];
16216
16258
  const visit = (dir) => {
16217
16259
  for (const entry of fs45.readdirSync(dir, { withFileTypes: true })) {
16218
- const absolute = path42.join(dir, entry.name);
16260
+ const absolute = path43.join(dir, entry.name);
16219
16261
  if (entry.isSymbolicLink()) continue;
16220
16262
  if (entry.isDirectory()) visit(absolute);
16221
- else if (entry.isFile()) files.push(path42.relative(root, absolute));
16263
+ else if (entry.isFile()) files.push(path43.relative(root, absolute));
16222
16264
  }
16223
16265
  };
16224
16266
  visit(root);
@@ -16241,8 +16283,8 @@ var init_loadSimpleCapability = __esm({
16241
16283
  if (!capability) {
16242
16284
  throw new Error(`Capability "${slug}" is not a valid simple capability folder`);
16243
16285
  }
16244
- const toolRoot = path42.join(capability.dir, "tools");
16245
- const skillRoot = path42.join(capability.dir, "skills");
16286
+ const toolRoot = path43.join(capability.dir, "tools");
16287
+ const skillRoot = path43.join(capability.dir, "skills");
16246
16288
  const toolFiles = listFiles(toolRoot);
16247
16289
  const skillFiles = listFiles(skillRoot);
16248
16290
  const parsedInput = parseInput(ctx.args.input);
@@ -16267,14 +16309,14 @@ var init_loadSimpleCapability = __esm({
16267
16309
  }
16268
16310
  if (requiredSubagents.length > 0) ctx.data.requiredSubagents = requiredSubagents;
16269
16311
  if (capability.contract?.execution === "script") {
16270
- ctx.data.capabilityScriptPath = path42.join(capability.dir, "tools", "run.sh");
16312
+ ctx.data.capabilityScriptPath = path43.join(capability.dir, "tools", "run.sh");
16271
16313
  ctx.data.capabilitySecretNames = capability.contract.secrets ?? [];
16272
16314
  ctx.data.capabilityScriptTimeoutMs = capability.contract.timeoutMs;
16273
16315
  }
16274
16316
  if (capability.config.outputSchema) {
16275
16317
  ctx.data.capabilityOutputSchema = capability.config.outputSchema;
16276
16318
  }
16277
- const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ? path42.join(os6.tmpdir(), `kody-capability-output-${randomUUID2()}.json`) : void 0;
16319
+ const outputPath = ctx.data.capabilityExecution === "agent" && capability.config.outputSchema ? path43.join(os6.tmpdir(), `kody-capability-output-${randomUUID2()}.json`) : void 0;
16278
16320
  if (outputPath) ctx.data.capabilityOutputPath = outputPath;
16279
16321
  ctx.data.capabilityEnvironment = {
16280
16322
  ...capabilityInputEnvironment(input),
@@ -16297,7 +16339,7 @@ var init_loadSimpleCapability = __esm({
16297
16339
  ...skillFiles.flatMap((file) => [
16298
16340
  `### ${file}`,
16299
16341
  "",
16300
- fs45.readFileSync(path42.join(skillRoot, file), "utf-8"),
16342
+ fs45.readFileSync(path43.join(skillRoot, file), "utf-8"),
16301
16343
  ""
16302
16344
  ])
16303
16345
  ] : [],
@@ -16306,7 +16348,7 @@ var init_loadSimpleCapability = __esm({
16306
16348
  "## Tools",
16307
16349
  "",
16308
16350
  "Inspect or run these capability-owned files when needed:",
16309
- ...toolFiles.map((file) => `- ${path42.join(toolRoot, file)}`)
16351
+ ...toolFiles.map((file) => `- ${path43.join(toolRoot, file)}`)
16310
16352
  ] : [],
16311
16353
  "",
16312
16354
  ...capability.config.outputSchema ? [
@@ -16338,7 +16380,7 @@ var init_loadSimpleCapability = __esm({
16338
16380
 
16339
16381
  // src/taskContext.ts
16340
16382
  import * as fs46 from "fs";
16341
- import * as path43 from "path";
16383
+ import * as path44 from "path";
16342
16384
  function buildTaskContext(args) {
16343
16385
  return {
16344
16386
  schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
@@ -16355,7 +16397,7 @@ function persistTaskContext(cwd, ctx) {
16355
16397
  try {
16356
16398
  const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
16357
16399
  fs46.mkdirSync(dir, { recursive: true });
16358
- const file = path43.join(dir, "task-context.json");
16400
+ const file = path44.join(dir, "task-context.json");
16359
16401
  fs46.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
16360
16402
  `);
16361
16403
  return file;
@@ -16783,19 +16825,19 @@ function parseAgencyModelProposal(raw) {
16783
16825
  function normalizeBundleFiles(bundle) {
16784
16826
  const seen = /* @__PURE__ */ new Set();
16785
16827
  return bundle.files.map((file, index) => {
16786
- const path58 = file.path.replace(/^\/+/, "");
16787
- const parts = path58.split("/");
16788
- if (!path58 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
16828
+ const path59 = file.path.replace(/^\/+/, "");
16829
+ const parts = path59.split("/");
16830
+ if (!path59 || file.path.startsWith("/") || file.path.includes("\\") || parts.some((part) => !part || part === "." || part === "..")) {
16789
16831
  throw new Error(`openAgencyModelReviewPr: files[${index}].path is unsafe`);
16790
16832
  }
16791
16833
  if (!/^(agents\/[^/]+\.md|capabilities\/[^/]+\/.+|goals\/(?:templates\/)?[^/]+\/.+|workflows\/[^/]+\.json)$/.test(
16792
- path58
16834
+ path59
16793
16835
  )) {
16794
16836
  throw new Error(`openAgencyModelReviewPr: files[${index}].path is not a supported definition path`);
16795
16837
  }
16796
- if (seen.has(path58)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path58}`);
16797
- seen.add(path58);
16798
- return { path: path58, content: file.content.replace(/\r\n?/g, "\n") };
16838
+ if (seen.has(path59)) throw new Error(`openAgencyModelReviewPr: duplicate generated file path: ${path59}`);
16839
+ seen.add(path59);
16840
+ return { path: path59, content: file.content.replace(/\r\n?/g, "\n") };
16799
16841
  });
16800
16842
  }
16801
16843
  function buildProposalId(issueNumber, bundle, sourceLabel) {
@@ -17907,7 +17949,7 @@ var init_postResearchComment = __esm({
17907
17949
  // src/scripts/prepareBrowserAuth.ts
17908
17950
  import * as fs48 from "fs";
17909
17951
  import * as os7 from "os";
17910
- import * as path44 from "path";
17952
+ import * as path45 from "path";
17911
17953
  function appendAuthMessage(ctx, message) {
17912
17954
  const current = typeof ctx.data.qaAuthBlock === "string" ? ctx.data.qaAuthBlock.trim() : "";
17913
17955
  ctx.data.qaAuthBlock = current ? `${current}
@@ -17946,9 +17988,9 @@ async function githubJson(url, token) {
17946
17988
  return await response.json();
17947
17989
  }
17948
17990
  function writeKodyStorageState(input) {
17949
- const directory = fs48.mkdtempSync(path44.join(os7.tmpdir(), "kody-browser-auth-"));
17991
+ const directory = fs48.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
17950
17992
  fs48.chmodSync(directory, 448);
17951
- const file = path44.join(directory, "storage-state.json");
17993
+ const file = path45.join(directory, "storage-state.json");
17952
17994
  const now = Date.now();
17953
17995
  const repoEntry = {
17954
17996
  repoUrl: input.repoUrl,
@@ -18207,7 +18249,7 @@ var init_prepareCapabilityDelivery = __esm({
18207
18249
 
18208
18250
  // src/scripts/prepareSimpleCapabilityRuntime.ts
18209
18251
  import { isIP } from "net";
18210
- import * as path45 from "path";
18252
+ import * as path46 from "path";
18211
18253
  function requirementsFrom(ctx) {
18212
18254
  const raw = ctx.data.capabilityRequirements;
18213
18255
  return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -18251,7 +18293,7 @@ function browserRuntime(ctx, requirements) {
18251
18293
  "--allowed-origins",
18252
18294
  origin,
18253
18295
  "--output-dir",
18254
- path45.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
18296
+ path46.resolve(ctx.cwd, "test-results", "quality-runs", qualityRunId)
18255
18297
  ]
18256
18298
  };
18257
18299
  }
@@ -18616,9 +18658,9 @@ function latestResult(raw, agentResult) {
18616
18658
  function recordField4(value) {
18617
18659
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
18618
18660
  }
18619
- function resolveDotted(root, path58) {
18620
- if (!path58) return void 0;
18621
- return path58.split(".").reduce((value, key) => recordField4(value)?.[key], root);
18661
+ function resolveDotted(root, path59) {
18662
+ if (!path59) return void 0;
18663
+ return path59.split(".").reduce((value, key) => recordField4(value)?.[key], root);
18622
18664
  }
18623
18665
  function stringValue5(value) {
18624
18666
  return typeof value === "string" && value.trim() ? value.trim() : null;
@@ -19460,7 +19502,7 @@ var init_previewBuildHelpers = __esm({
19460
19502
  // src/scripts/previewBuildRun.ts
19461
19503
  import { spawn as spawn5 } from "child_process";
19462
19504
  async function runCmd(cmd, args, opts = {}) {
19463
- await new Promise((resolve23, reject) => {
19505
+ await new Promise((resolve24, reject) => {
19464
19506
  const child = spawn5(cmd, args, {
19465
19507
  cwd: opts.cwd,
19466
19508
  env: { ...process.env, ...opts.env ?? {} },
@@ -19472,7 +19514,7 @@ async function runCmd(cmd, args, opts = {}) {
19472
19514
  }
19473
19515
  child.on("error", reject);
19474
19516
  child.on("close", (code) => {
19475
- if (code === 0) resolve23();
19517
+ if (code === 0) resolve24();
19476
19518
  else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
19477
19519
  });
19478
19520
  });
@@ -19544,12 +19586,12 @@ fi
19544
19586
 
19545
19587
  // src/scripts/runPreviewBuild.ts
19546
19588
  import { copyFile, writeFile } from "fs/promises";
19547
- import * as path46 from "path";
19589
+ import * as path47 from "path";
19548
19590
  import { fileURLToPath as fileURLToPath2 } from "url";
19549
19591
  function bundledDockerfilePath(mode) {
19550
- const here = path46.dirname(fileURLToPath2(import.meta.url));
19592
+ const here = path47.dirname(fileURLToPath2(import.meta.url));
19551
19593
  const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
19552
- return path46.join(here, "preview-build-templates", file);
19594
+ return path47.join(here, "preview-build-templates", file);
19553
19595
  }
19554
19596
  function required(name) {
19555
19597
  const v = (process.env[name] ?? "").trim();
@@ -19784,10 +19826,10 @@ var init_runPreviewBuild = __esm({
19784
19826
  console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
19785
19827
  if (Object.keys(buildEnv).length > 0) {
19786
19828
  const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
19787
- await writeFile(path46.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
19829
+ await writeFile(path47.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
19788
19830
  `, "utf8");
19789
19831
  }
19790
- const consumerDockerfile = path46.join(ctx.cwd, "Dockerfile.preview");
19832
+ const consumerDockerfile = path47.join(ctx.cwd, "Dockerfile.preview");
19791
19833
  const { stat } = await import("fs/promises");
19792
19834
  let hasConsumerDockerfile = false;
19793
19835
  try {
@@ -19972,7 +20014,7 @@ var init_tickShellRunner = __esm({
19972
20014
 
19973
20015
  // src/scripts/runScheduledImplementationTick.ts
19974
20016
  import * as fs49 from "fs";
19975
- import * as path47 from "path";
20017
+ import * as path48 from "path";
19976
20018
  var runScheduledImplementationTick;
19977
20019
  var init_runScheduledImplementationTick = __esm({
19978
20020
  "src/scripts/runScheduledImplementationTick.ts"() {
@@ -19993,13 +20035,13 @@ var init_runScheduledImplementationTick = __esm({
19993
20035
  ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
19994
20036
  return;
19995
20037
  }
19996
- const capability = resolveCapabilityFolder(slug, path47.resolve(ctx.cwd, jobsDir));
20038
+ const capability = resolveCapabilityFolder(slug, path48.resolve(ctx.cwd, jobsDir));
19997
20039
  if (!capability) {
19998
20040
  ctx.output.exitCode = 99;
19999
20041
  ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug} (searched ${jobsDir} and company store)`;
20000
20042
  return;
20001
20043
  }
20002
- const shellPath = path47.join(profile.dir, shell);
20044
+ const shellPath = path48.join(profile.dir, shell);
20003
20045
  if (!fs49.existsSync(shellPath)) {
20004
20046
  ctx.output.exitCode = 99;
20005
20047
  ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
@@ -20118,7 +20160,7 @@ var init_runSimpleCapabilityScript = __esm({
20118
20160
 
20119
20161
  // src/scripts/runTickScript.ts
20120
20162
  import * as fs51 from "fs";
20121
- import * as path48 from "path";
20163
+ import * as path49 from "path";
20122
20164
  var runTickScript;
20123
20165
  var init_runTickScript = __esm({
20124
20166
  "src/scripts/runTickScript.ts"() {
@@ -20138,10 +20180,10 @@ var init_runTickScript = __esm({
20138
20180
  ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
20139
20181
  return;
20140
20182
  }
20141
- const capability = readCapabilityFolder(path48.resolve(ctx.cwd, jobsDir), slug);
20183
+ const capability = readCapabilityFolder(path49.resolve(ctx.cwd, jobsDir), slug);
20142
20184
  if (!capability) {
20143
20185
  ctx.output.exitCode = 99;
20144
- ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path48.resolve(ctx.cwd, jobsDir, slug)}`;
20186
+ ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path49.resolve(ctx.cwd, jobsDir, slug)}`;
20145
20187
  return;
20146
20188
  }
20147
20189
  const tickScript = capability.config.tickScript;
@@ -20150,7 +20192,7 @@ var init_runTickScript = __esm({
20150
20192
  ctx.output.reason = `runTickScript: capability ${slug} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
20151
20193
  return;
20152
20194
  }
20153
- const scriptPath = path48.isAbsolute(tickScript) ? tickScript : path48.join(ctx.cwd, tickScript);
20195
+ const scriptPath = path49.isAbsolute(tickScript) ? tickScript : path49.join(ctx.cwd, tickScript);
20154
20196
  if (!fs51.existsSync(scriptPath)) {
20155
20197
  ctx.output.exitCode = 99;
20156
20198
  ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
@@ -20433,7 +20475,7 @@ var init_syncFlow = __esm({
20433
20475
  });
20434
20476
 
20435
20477
  // src/scripts/validateAgencyModelProposal.ts
20436
- import * as path49 from "path";
20478
+ import * as path50 from "path";
20437
20479
  function validateModelBundle(bundle, expectedKind, options = {}) {
20438
20480
  const failures = [];
20439
20481
  validateOneModel(bundle.model, bundle.files, "model", true, failures, expectedKind, options);
@@ -20751,7 +20793,7 @@ var init_validateAgencyModelProposal = __esm({
20751
20793
  const bundle = parseAgencyModelProposal(raw);
20752
20794
  const expectedKind = readExpectedModelKind(args);
20753
20795
  const failures = validateModelBundle(bundle, expectedKind, {
20754
- capabilityRoot: path49.join(ctx.cwd, ".kody", "capabilities")
20796
+ capabilityRoot: path50.join(ctx.cwd, ".kody", "capabilities")
20755
20797
  });
20756
20798
  if (failures.length > 0) {
20757
20799
  throw new Error(`validateAgencyModelProposal: ${failures.join("; ")}`);
@@ -20814,7 +20856,7 @@ function stripAnsi2(s) {
20814
20856
  return s.replace(ANSI_RE2, "");
20815
20857
  }
20816
20858
  function runCommand2(command, cwd) {
20817
- return new Promise((resolve23) => {
20859
+ return new Promise((resolve24) => {
20818
20860
  const child = spawn6(command, {
20819
20861
  cwd,
20820
20862
  shell: true,
@@ -20841,11 +20883,11 @@ function runCommand2(command, cwd) {
20841
20883
  }, TEST_TIMEOUT_MS);
20842
20884
  child.on("exit", (code) => {
20843
20885
  clearTimeout(timer);
20844
- resolve23({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
20886
+ resolve24({ exitCode: code ?? -1, output: Buffer.concat(buffers).toString("utf-8") });
20845
20887
  });
20846
20888
  child.on("error", (err) => {
20847
20889
  clearTimeout(timer);
20848
- resolve23({ exitCode: -1, output: err.message });
20890
+ resolve24({ exitCode: -1, output: err.message });
20849
20891
  });
20850
20892
  });
20851
20893
  }
@@ -21259,21 +21301,21 @@ function lineStream(stream) {
21259
21301
  tryDeliver();
21260
21302
  });
21261
21303
  return {
21262
- next: (timeoutMs) => new Promise((resolve23) => {
21304
+ next: (timeoutMs) => new Promise((resolve24) => {
21263
21305
  if (queue.length > 0) {
21264
- resolve23(queue.shift());
21306
+ resolve24(queue.shift());
21265
21307
  return;
21266
21308
  }
21267
21309
  if (ended) {
21268
- resolve23(null);
21310
+ resolve24(null);
21269
21311
  return;
21270
21312
  }
21271
- waiter = resolve23;
21313
+ waiter = resolve24;
21272
21314
  const t = setTimeout(
21273
21315
  () => {
21274
- if (waiter === resolve23) {
21316
+ if (waiter === resolve24) {
21275
21317
  waiter = null;
21276
- resolve23(null);
21318
+ resolve24(null);
21277
21319
  }
21278
21320
  },
21279
21321
  Math.max(0, timeoutMs)
@@ -21675,15 +21717,15 @@ var init_scripts = __esm({
21675
21717
 
21676
21718
  // src/stateWorkspace.ts
21677
21719
  import * as fs53 from "fs";
21678
- import * as path50 from "path";
21720
+ import * as path51 from "path";
21679
21721
  function tenantId(config) {
21680
21722
  const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
21681
21723
  const repo = config.github?.repo?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
21682
21724
  return owner && repo ? `${owner}/${repo}` : null;
21683
21725
  }
21684
21726
  function writeRuntimeFile(cwd, relativePath, content) {
21685
- const target = path50.join(cwd, RUNTIME_ROOT, relativePath);
21686
- fs53.mkdirSync(path50.dirname(target), { recursive: true });
21727
+ const target = path51.join(cwd, RUNTIME_ROOT, relativePath);
21728
+ fs53.mkdirSync(path51.dirname(target), { recursive: true });
21687
21729
  fs53.writeFileSync(target, content, "utf8");
21688
21730
  }
21689
21731
  function record(value) {
@@ -21749,10 +21791,10 @@ async function hydrateStateWorkspace(config, cwd, backendOverride) {
21749
21791
  throw new Error("Kody backend access is required for runtime workspace documents");
21750
21792
  return;
21751
21793
  }
21752
- const key = `${path50.resolve(cwd)}|${tenant}`;
21794
+ const key = `${path51.resolve(cwd)}|${tenant}`;
21753
21795
  if (hydratedWorkspaces.has(key)) return;
21754
21796
  const backend = backendOverride ?? createStateBackendFromEnv();
21755
- const root = path50.join(cwd, RUNTIME_ROOT);
21797
+ const root = path51.join(cwd, RUNTIME_ROOT);
21756
21798
  fs53.rmSync(root, { recursive: true, force: true });
21757
21799
  await Promise.all([
21758
21800
  hydratePrefix(backend, tenant, cwd, "context:"),
@@ -21769,7 +21811,7 @@ var init_stateWorkspace = __esm({
21769
21811
  "src/stateWorkspace.ts"() {
21770
21812
  "use strict";
21771
21813
  init_state_backend();
21772
- RUNTIME_ROOT = path50.join(".kody-engine", "runtime");
21814
+ RUNTIME_ROOT = path51.join(".kody-engine", "runtime");
21773
21815
  hydratedWorkspaces = /* @__PURE__ */ new Set();
21774
21816
  }
21775
21817
  });
@@ -21842,7 +21884,7 @@ var init_tools = __esm({
21842
21884
  import { spawn as spawn8 } from "child_process";
21843
21885
  import * as fs54 from "fs";
21844
21886
  import * as os8 from "os";
21845
- import * as path51 from "path";
21887
+ import * as path52 from "path";
21846
21888
  function isMutatingPostflight(scriptName) {
21847
21889
  return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
21848
21890
  }
@@ -22099,7 +22141,7 @@ async function runImplementation(profileName, input) {
22099
22141
  const reason = input.abortController.signal.reason;
22100
22142
  throw reason instanceof Error ? reason : new Error("agent invocation aborted");
22101
22143
  }
22102
- const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path51.isAbsolute(p) ? p : path51.resolve(profile.dir, p)).filter((p) => p.length > 0);
22144
+ const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path52.isAbsolute(p) ? p : path52.resolve(profile.dir, p)).filter((p) => p.length > 0);
22103
22145
  const syntheticPath = ctx.data.syntheticPluginPath;
22104
22146
  const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
22105
22147
  const agents = loadSubagents(profile);
@@ -22138,6 +22180,7 @@ async function runImplementation(profileName, input) {
22138
22180
  verbose: input.verbose,
22139
22181
  quiet: input.quiet,
22140
22182
  abortController: input.abortController,
22183
+ deadlineAtMs: input.deadlineAtMs,
22141
22184
  ndjsonDir,
22142
22185
  additionalDirectories: agentTaskArtifacts ? [agentTaskArtifacts.absDir] : void 0,
22143
22186
  allowedToolsOverride: profile.claudeCode.tools,
@@ -22580,13 +22623,13 @@ function clearStampedLifecycleLabels(profile, ctx) {
22580
22623
  function resolveProfilePath(profileName, cwd = process.cwd()) {
22581
22624
  const found = resolveImplementation(profileName, getRuntimeProfileRootsForCwd(cwd));
22582
22625
  if (found) return found;
22583
- const here = path51.dirname(new URL(import.meta.url).pathname);
22626
+ const here = path52.dirname(new URL(import.meta.url).pathname);
22584
22627
  const candidates = [
22585
- path51.join(here, "implementations", profileName, "profile.json"),
22628
+ path52.join(here, "implementations", profileName, "profile.json"),
22586
22629
  // same-dir sibling (dev)
22587
- path51.join(here, "..", "implementations", profileName, "profile.json"),
22630
+ path52.join(here, "..", "implementations", profileName, "profile.json"),
22588
22631
  // up one (prod: dist/bin → dist/implementations)
22589
- path51.join(here, "..", "src", "implementations", profileName, "profile.json")
22632
+ path52.join(here, "..", "src", "implementations", profileName, "profile.json")
22590
22633
  // fallback
22591
22634
  ];
22592
22635
  for (const c of candidates) {
@@ -22705,7 +22748,7 @@ function resolveShellTimeoutMs(entry) {
22705
22748
  }
22706
22749
  async function runShellEntry(entry, ctx, profile) {
22707
22750
  const shellName = entry.shell;
22708
- const shellPath = path51.join(profile.dir, shellName);
22751
+ const shellPath = path52.join(profile.dir, shellName);
22709
22752
  if (!fs54.existsSync(shellPath)) {
22710
22753
  ctx.skipAgent = true;
22711
22754
  ctx.output.exitCode = 99;
@@ -22713,7 +22756,7 @@ async function runShellEntry(entry, ctx, profile) {
22713
22756
  return;
22714
22757
  }
22715
22758
  const positional = entry.with ? Object.values(entry.with).map((v) => String(v)) : [];
22716
- const outputFile = path51.join(
22759
+ const outputFile = path52.join(
22717
22760
  os8.tmpdir(),
22718
22761
  `kody-shell-output-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
22719
22762
  );
@@ -22743,14 +22786,14 @@ async function runShellEntry(entry, ctx, profile) {
22743
22786
  let killTimer;
22744
22787
  let escalateTimer;
22745
22788
  const result = await new Promise(
22746
- (resolve23) => {
22789
+ (resolve24) => {
22747
22790
  let settled = false;
22748
22791
  const settle = (code, signal, spawnErr) => {
22749
22792
  if (settled) return;
22750
22793
  settled = true;
22751
22794
  if (killTimer) clearTimeout(killTimer);
22752
22795
  if (escalateTimer) clearTimeout(escalateTimer);
22753
- resolve23({ code, signal, spawnErr });
22796
+ resolve24({ code, signal, spawnErr });
22754
22797
  };
22755
22798
  child.on("error", (err) => settle(null, null, err));
22756
22799
  child.on("close", (code, signal) => settle(code, signal));
@@ -23324,6 +23367,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
23324
23367
  verbose: base.verbose,
23325
23368
  quiet: base.quiet,
23326
23369
  abortController: base.abortController,
23370
+ deadlineAtMs: base.deadlineAtMs,
23327
23371
  preloadedData: Object.keys(preloadedData).length > 0 ? preloadedData : void 0
23328
23372
  };
23329
23373
  const shouldApplyResolvedCapabilityArgs = valid.implementation === void 0 && resolvedCapability && profileName === resolvedCapability.implementation;
@@ -23637,6 +23681,7 @@ async function runGraphCapabilityWorkflow(parent, workflow, capability, base, ch
23637
23681
  result = await runJob(child, {
23638
23682
  ...base,
23639
23683
  abortController: stepAbort.controller,
23684
+ deadlineAtMs: stepAbort.deadlineAtMs,
23640
23685
  preloadedData: {
23641
23686
  ...chainData,
23642
23687
  runSubjectType: "capability",
@@ -23793,11 +23838,11 @@ function exhaustedWorkflowTransitions(step, data, counts) {
23793
23838
  }
23794
23839
  function workflowResultConditionPaths(transitions) {
23795
23840
  return transitions.flatMap(
23796
- (transition) => Object.keys(transition.when ?? {}).filter((path58) => path58.startsWith("result."))
23841
+ (transition) => Object.keys(transition.when ?? {}).filter((path59) => path59.startsWith("result."))
23797
23842
  );
23798
23843
  }
23799
23844
  function conditionMatches(condition, context) {
23800
- return Object.entries(condition).every(([path58, expected]) => valueMatches(resolveDottedPath2(context, path58), expected));
23845
+ return Object.entries(condition).every(([path59, expected]) => valueMatches(resolveDottedPath2(context, path59), expected));
23801
23846
  }
23802
23847
  function withWorkflowBoundaryEval(capability, result) {
23803
23848
  const capabilityKind = capability.config.capabilityKind;
@@ -23966,8 +24011,9 @@ function canContinueWorkflow(step, outcome) {
23966
24011
  return step.continueOn.includes(outcome.type);
23967
24012
  }
23968
24013
  function workflowStepAbortController(parent, timeoutSeconds) {
23969
- if (!timeoutSeconds) return { controller: parent, cleanup: () => void 0 };
24014
+ if (!timeoutSeconds) return { controller: parent, deadlineAtMs: void 0, cleanup: () => void 0 };
23970
24015
  const controller = new AbortController();
24016
+ const deadlineAtMs = Date.now() + timeoutSeconds * 1e3;
23971
24017
  const forwardParentAbort = () => controller.abort(parent?.signal.reason);
23972
24018
  if (parent?.signal.aborted) forwardParentAbort();
23973
24019
  else parent?.signal.addEventListener("abort", forwardParentAbort, { once: true });
@@ -23977,6 +24023,7 @@ function workflowStepAbortController(parent, timeoutSeconds) {
23977
24023
  timer.unref?.();
23978
24024
  return {
23979
24025
  controller,
24026
+ deadlineAtMs,
23980
24027
  cleanup: () => {
23981
24028
  clearTimeout(timer);
23982
24029
  parent?.signal.removeEventListener("abort", forwardParentAbort);
@@ -24270,7 +24317,7 @@ function translateOpenAISseToBrain(opts) {
24270
24317
 
24271
24318
  // src/servers/brain-serve.ts
24272
24319
  import { createServer as createServer2 } from "http";
24273
- import * as path54 from "path";
24320
+ import * as path55 from "path";
24274
24321
 
24275
24322
  // src/chat/loop.ts
24276
24323
  init_agent();
@@ -24279,12 +24326,12 @@ init_config();
24279
24326
  init_registry();
24280
24327
  init_task_artifacts();
24281
24328
  import * as fs18 from "fs";
24282
- import * as path19 from "path";
24329
+ import * as path20 from "path";
24283
24330
 
24284
24331
  // src/chat/attachments.ts
24285
24332
  init_runtimePaths();
24286
24333
  import * as fs15 from "fs";
24287
- import * as path16 from "path";
24334
+ import * as path17 from "path";
24288
24335
  var INLINE_ATTACHMENT_RE = /(?:\[(?:Image|File): ([^\]]*)\]\n)?data:([\w.+-]+\/[\w.+-]+);base64,([A-Za-z0-9+/=]+)/g;
24289
24336
  var EXT_BY_MIME = {
24290
24337
  "image/png": "png",
@@ -24320,7 +24367,7 @@ function prepareAttachments(turns, cwd, sessionId) {
24320
24367
  fs15.mkdirSync(dir, { recursive: true });
24321
24368
  dirEnsured = true;
24322
24369
  }
24323
- const filePath = path16.join(dir, `${imageCounter}.${extFor(mime)}`);
24370
+ const filePath = path17.join(dir, `${imageCounter}.${extFor(mime)}`);
24324
24371
  fs15.writeFileSync(filePath, Buffer.from(data, "base64"));
24325
24372
  imageCounter += 1;
24326
24373
  imagePaths.push(filePath);
@@ -24339,7 +24386,7 @@ function prepareAttachments(turns, cwd, sessionId) {
24339
24386
  // src/chat/codex-app-server.ts
24340
24387
  import { spawn as spawn3 } from "child_process";
24341
24388
  import * as fs16 from "fs";
24342
- import * as path17 from "path";
24389
+ import * as path18 from "path";
24343
24390
  import { createInterface } from "readline";
24344
24391
  function codexThreadStartParams(args) {
24345
24392
  return {
@@ -24424,9 +24471,9 @@ var CodexAppServerClient = class {
24424
24471
  await this.request("thread/resume", { threadId });
24425
24472
  }
24426
24473
  async runTurn(args) {
24427
- await new Promise((resolve23, reject) => {
24474
+ await new Promise((resolve24, reject) => {
24428
24475
  this.process.turnWaiters.set(args.threadId, {
24429
- resolve: resolve23,
24476
+ resolve: resolve24,
24430
24477
  reject,
24431
24478
  onNotification: args.onNotification,
24432
24479
  queue: Promise.resolve()
@@ -24443,8 +24490,8 @@ var CodexAppServerClient = class {
24443
24490
  }
24444
24491
  request(method, params) {
24445
24492
  const id = this.process.nextId++;
24446
- return new Promise((resolve23, reject) => {
24447
- this.process.pending.set(id, { resolve: resolve23, reject });
24493
+ return new Promise((resolve24, reject) => {
24494
+ this.process.pending.set(id, { resolve: resolve24, reject });
24448
24495
  this.process.child.stdin.write(`${JSON.stringify({ method, id, params })}
24449
24496
  `);
24450
24497
  });
@@ -24510,7 +24557,7 @@ var CodexAppServerClient = class {
24510
24557
  };
24511
24558
  var clients = /* @__PURE__ */ new Map();
24512
24559
  function threadMapPath(cwd) {
24513
- return path17.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
24560
+ return path18.join(cwd, ".kody-engine", "runtime", "codex-threads.json");
24514
24561
  }
24515
24562
  function readThreadMap(cwd) {
24516
24563
  try {
@@ -24527,7 +24574,7 @@ function readThreadMap(cwd) {
24527
24574
  }
24528
24575
  function writeThreadMap(cwd, map) {
24529
24576
  const file = threadMapPath(cwd);
24530
- fs16.mkdirSync(path17.dirname(file), { recursive: true });
24577
+ fs16.mkdirSync(path18.dirname(file), { recursive: true });
24531
24578
  fs16.writeFileSync(file, `${JSON.stringify(map, null, 2)}
24532
24579
  `);
24533
24580
  }
@@ -24619,7 +24666,7 @@ async function runCodexChatTurn(args) {
24619
24666
 
24620
24667
  // src/chat/events.ts
24621
24668
  import * as fs17 from "fs";
24622
- import * as path18 from "path";
24669
+ import * as path19 from "path";
24623
24670
  import posixPath2 from "path/posix";
24624
24671
  var BackendEventSink = class {
24625
24672
  constructor(append, tenantId2, sessionId) {
@@ -24635,7 +24682,7 @@ var BackendEventSink = class {
24635
24682
  }
24636
24683
  };
24637
24684
  function eventsFilePath(cwd, sessionId) {
24638
- return path18.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
24685
+ return path19.join(cwd, ".kody-engine", "runtime", "events", `${sessionId}.jsonl`);
24639
24686
  }
24640
24687
  var FileSink = class {
24641
24688
  constructor(file) {
@@ -24643,7 +24690,7 @@ var FileSink = class {
24643
24690
  }
24644
24691
  file;
24645
24692
  async emit(event) {
24646
- fs17.mkdirSync(path18.dirname(this.file), { recursive: true });
24693
+ fs17.mkdirSync(path19.dirname(this.file), { recursive: true });
24647
24694
  fs17.appendFileSync(this.file, `${JSON.stringify(event)}
24648
24695
  `);
24649
24696
  }
@@ -25031,7 +25078,7 @@ async function runChatTurn(opts) {
25031
25078
  quiet: opts.quiet,
25032
25079
  additionalDirectories: [
25033
25080
  taskArtifactsPaths.absDir,
25034
- ...Array.from(new Set(imagePaths.map((p2) => path19.dirname(p2))))
25081
+ ...Array.from(new Set(imagePaths.map((p2) => path20.dirname(p2))))
25035
25082
  ],
25036
25083
  systemPromptAppend: systemPrompt,
25037
25084
  ...opts.reasoningEffort ? { reasoningEffort: opts.reasoningEffort } : {},
@@ -25219,7 +25266,7 @@ async function emit(sink, type, sessionId, suffix, payload) {
25219
25266
  var MEMORY_INDEX_REL = ".kody-engine/runtime/memory/INDEX.md";
25220
25267
  var MAX_INDEX_BYTES = 8e3;
25221
25268
  function readMemoryIndexBlock(cwd) {
25222
- const indexPath = path19.join(cwd, MEMORY_INDEX_REL);
25269
+ const indexPath = path20.join(cwd, MEMORY_INDEX_REL);
25223
25270
  let raw;
25224
25271
  try {
25225
25272
  raw = fs18.readFileSync(indexPath, "utf-8");
@@ -25242,7 +25289,7 @@ _\u2026 (memory index truncated; use recall_search to read more)_` : trimmed;
25242
25289
  var CONTEXT_DIR_REL = ".kody-engine/runtime/context";
25243
25290
  var MAX_CONTEXT_BYTES = 12e3;
25244
25291
  function readContextBlock(cwd) {
25245
- const dir = path19.join(cwd, CONTEXT_DIR_REL);
25292
+ const dir = path20.join(cwd, CONTEXT_DIR_REL);
25246
25293
  let files;
25247
25294
  try {
25248
25295
  files = fs18.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
@@ -25252,7 +25299,7 @@ function readContextBlock(cwd) {
25252
25299
  const sections = [];
25253
25300
  for (const file of files) {
25254
25301
  try {
25255
- const content = fs18.readFileSync(path19.join(dir, file), "utf-8").trim();
25302
+ const content = fs18.readFileSync(path20.join(dir, file), "utf-8").trim();
25256
25303
  if (content) sections.push(`### ${file.replace(/\.md$/, "")}
25257
25304
 
25258
25305
  ${content}`);
@@ -25278,7 +25325,7 @@ var SYSTEM_PROMPT_OVERRIDE_REL = ".kody-engine/runtime/system-prompt.md";
25278
25325
  function readSystemPromptOverride(cwd) {
25279
25326
  let raw;
25280
25327
  try {
25281
- raw = fs18.readFileSync(path19.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
25328
+ raw = fs18.readFileSync(path20.join(cwd, SYSTEM_PROMPT_OVERRIDE_REL), "utf-8");
25282
25329
  } catch {
25283
25330
  return null;
25284
25331
  }
@@ -25286,7 +25333,7 @@ function readSystemPromptOverride(cwd) {
25286
25333
  return trimmed.length > 0 ? trimmed : null;
25287
25334
  }
25288
25335
  function readInstructionsBlock(cwd) {
25289
- const instructionsPath = path19.join(cwd, INSTRUCTIONS_REL);
25336
+ const instructionsPath = path20.join(cwd, INSTRUCTIONS_REL);
25290
25337
  let raw;
25291
25338
  try {
25292
25339
  raw = fs18.readFileSync(instructionsPath, "utf-8");
@@ -25324,10 +25371,10 @@ function resolveBrainDriver(runtime) {
25324
25371
 
25325
25372
  // src/chat/session.ts
25326
25373
  import * as fs19 from "fs";
25327
- import * as path20 from "path";
25374
+ import * as path21 from "path";
25328
25375
  import posixPath3 from "path/posix";
25329
25376
  function sessionFilePath(cwd, sessionId) {
25330
- return path20.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
25377
+ return path21.join(cwd, ".kody-engine", "runtime", "sessions", `${sessionId}.jsonl`);
25331
25378
  }
25332
25379
  function readSession(file) {
25333
25380
  if (!fs19.existsSync(file)) return [];
@@ -25355,7 +25402,7 @@ init_state_backend();
25355
25402
  init_workflowDefinitions();
25356
25403
  import { createHash as createHash2 } from "crypto";
25357
25404
  import * as fs21 from "fs";
25358
- import * as path22 from "path";
25405
+ import * as path23 from "path";
25359
25406
  var SLUG_RE = /^[a-z0-9][a-z0-9_-]{0,127}$/;
25360
25407
  var REPOSITORY_OWNED_NAMESPACES = ["loops"];
25361
25408
  function assertSafeDefinitionPath(filePath) {
@@ -25387,8 +25434,8 @@ function verifyDefinition(definition) {
25387
25434
  }
25388
25435
  function writeBundle(root, bundle) {
25389
25436
  for (const [filePath, contents] of Object.entries(bundle.files)) {
25390
- const target = path22.join(root, filePath);
25391
- fs21.mkdirSync(path22.dirname(target), { recursive: true });
25437
+ const target = path23.join(root, filePath);
25438
+ fs21.mkdirSync(path23.dirname(target), { recursive: true });
25392
25439
  fs21.writeFileSync(target, contents, "utf8");
25393
25440
  }
25394
25441
  }
@@ -25397,22 +25444,22 @@ function writeDefinition(root, kind, definition) {
25397
25444
  if (kind === "agent") {
25398
25445
  const raw = bundle.files["agent.md"];
25399
25446
  if (typeof raw !== "string") throw new Error(`agent definition ${definition.slug} is missing agent.md`);
25400
- fs21.writeFileSync(path22.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25447
+ fs21.writeFileSync(path23.join(root, "agents", `${definition.slug}.md`), raw, "utf8");
25401
25448
  return;
25402
25449
  }
25403
25450
  if (kind === "goal") {
25404
- writeBundle(path22.join(root, "goals", definition.slug), bundle);
25451
+ writeBundle(path23.join(root, "goals", definition.slug), bundle);
25405
25452
  return;
25406
25453
  }
25407
25454
  if (kind === "implementation") {
25408
- writeBundle(path22.join(root, "implementations", definition.slug), bundle);
25455
+ writeBundle(path23.join(root, "implementations", definition.slug), bundle);
25409
25456
  return;
25410
25457
  }
25411
25458
  if (kind === "asset") {
25412
- writeBundle(path22.join(root, "shared"), bundle);
25459
+ writeBundle(path23.join(root, "shared"), bundle);
25413
25460
  return;
25414
25461
  }
25415
- writeBundle(path22.join(root, "capabilities", definition.slug), bundle);
25462
+ writeBundle(path23.join(root, "capabilities", definition.slug), bundle);
25416
25463
  }
25417
25464
  function writeWorkflow(root, document) {
25418
25465
  const workflow = normalizeWorkflowDefinition(document.definition);
@@ -25420,28 +25467,28 @@ function writeWorkflow(root, document) {
25420
25467
  const contents = `${JSON.stringify(workflow, null, 2)}
25421
25468
  `;
25422
25469
  const bundle = { schemaVersion: 1, files: { "workflow.json": contents } };
25423
- const target = path22.join(root, workflowDefinitionPath(document.workflowId));
25424
- fs21.mkdirSync(path22.dirname(target), { recursive: true });
25470
+ const target = path23.join(root, workflowDefinitionPath(document.workflowId));
25471
+ fs21.mkdirSync(path23.dirname(target), { recursive: true });
25425
25472
  fs21.writeFileSync(target, contents, "utf8");
25426
25473
  return definitionVersion(bundle);
25427
25474
  }
25428
25475
  function preserveRepositoryDefinitions(root, staging) {
25429
25476
  for (const namespace of REPOSITORY_OWNED_NAMESPACES) {
25430
- const source = path22.join(root, namespace);
25477
+ const source = path23.join(root, namespace);
25431
25478
  if (!fs21.existsSync(source)) continue;
25432
- fs21.cpSync(source, path22.join(staging, namespace), { recursive: true });
25479
+ fs21.cpSync(source, path23.join(staging, namespace), { recursive: true });
25433
25480
  }
25434
25481
  }
25435
25482
  async function hydrateDefinitions(options) {
25436
- const root = path22.join(options.cwd, ".kody-engine", "definitions");
25483
+ const root = path23.join(options.cwd, ".kody-engine", "definitions");
25437
25484
  const staging = `${root}.tmp-${process.pid}-${Date.now()}`;
25438
25485
  fs21.rmSync(staging, { recursive: true, force: true });
25439
- fs21.mkdirSync(path22.join(staging, "agents"), { recursive: true });
25440
- fs21.mkdirSync(path22.join(staging, "capabilities"), { recursive: true });
25441
- fs21.mkdirSync(path22.join(staging, "goals"), { recursive: true });
25442
- fs21.mkdirSync(path22.join(staging, "implementations"), { recursive: true });
25443
- fs21.mkdirSync(path22.join(staging, "shared"), { recursive: true });
25444
- fs21.mkdirSync(path22.join(staging, "workflows"), { recursive: true });
25486
+ fs21.mkdirSync(path23.join(staging, "agents"), { recursive: true });
25487
+ fs21.mkdirSync(path23.join(staging, "capabilities"), { recursive: true });
25488
+ fs21.mkdirSync(path23.join(staging, "goals"), { recursive: true });
25489
+ fs21.mkdirSync(path23.join(staging, "implementations"), { recursive: true });
25490
+ fs21.mkdirSync(path23.join(staging, "shared"), { recursive: true });
25491
+ fs21.mkdirSync(path23.join(staging, "workflows"), { recursive: true });
25445
25492
  try {
25446
25493
  const [capabilities, agents, goals, implementations, assets, workflows] = await Promise.all([
25447
25494
  options.backend.listDefinitions(options.tenantId, "capability"),
@@ -25482,7 +25529,7 @@ async function hydrateDefinitions(options) {
25482
25529
  hydratedAt: (/* @__PURE__ */ new Date()).toISOString(),
25483
25530
  versions: Object.fromEntries(Object.entries(versions).sort(([left], [right]) => left.localeCompare(right)))
25484
25531
  };
25485
- fs21.writeFileSync(path22.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25532
+ fs21.writeFileSync(path23.join(staging, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
25486
25533
  `, "utf8");
25487
25534
  fs21.rmSync(root, { recursive: true, force: true });
25488
25535
  fs21.renameSync(staging, root);
@@ -25511,7 +25558,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
25511
25558
  // src/kody-cli.ts
25512
25559
  import { execFileSync as execFileSync24 } from "child_process";
25513
25560
  import * as fs55 from "fs";
25514
- import * as path52 from "path";
25561
+ import * as path53 from "path";
25515
25562
 
25516
25563
  // src/app-auth.ts
25517
25564
  import { createSign } from "crypto";
@@ -26313,9 +26360,9 @@ async function resolveAuthToken(env = process.env) {
26313
26360
  return void 0;
26314
26361
  }
26315
26362
  function detectPackageManager2(cwd) {
26316
- if (fs55.existsSync(path52.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
26317
- if (fs55.existsSync(path52.join(cwd, "yarn.lock"))) return "yarn";
26318
- if (fs55.existsSync(path52.join(cwd, "bun.lockb"))) return "bun";
26363
+ if (fs55.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
26364
+ if (fs55.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
26365
+ if (fs55.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
26319
26366
  return "npm";
26320
26367
  }
26321
26368
  function shouldChainScheduledWatch(match) {
@@ -26448,7 +26495,7 @@ async function runCi(argv) {
26448
26495
  return 0;
26449
26496
  }
26450
26497
  const args = parseCiArgs(argv);
26451
- const cwd = args.cwd ? path52.resolve(args.cwd) : process.cwd();
26498
+ const cwd = args.cwd ? path53.resolve(args.cwd) : process.cwd();
26452
26499
  try {
26453
26500
  const n = unpackAllSecrets();
26454
26501
  if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
@@ -26932,7 +26979,7 @@ init_repoWorkspace();
26932
26979
  // src/scripts/brainTurnLog.ts
26933
26980
  init_runtimePaths();
26934
26981
  import * as fs56 from "fs";
26935
- import * as path53 from "path";
26982
+ import * as path54 from "path";
26936
26983
  import posixPath4 from "path/posix";
26937
26984
  var live = /* @__PURE__ */ new Map();
26938
26985
  function brainEventsFilePath(dir, chatId) {
@@ -26979,7 +27026,7 @@ function beginTurn(dir, chatId) {
26979
27026
  };
26980
27027
  live.set(chatId, state);
26981
27028
  const p = brainEventsFilePath(dir, chatId);
26982
- fs56.mkdirSync(path53.dirname(p), { recursive: true });
27029
+ fs56.mkdirSync(path54.dirname(p), { recursive: true });
26983
27030
  return (event) => {
26984
27031
  state.seq += 1;
26985
27032
  const rec = { seq: state.seq, turn, ts: Date.now(), event };
@@ -27117,17 +27164,17 @@ function authOk(req, expected) {
27117
27164
  return false;
27118
27165
  }
27119
27166
  function readJsonBody(req) {
27120
- return new Promise((resolve23, reject) => {
27167
+ return new Promise((resolve24, reject) => {
27121
27168
  const chunks = [];
27122
27169
  req.on("data", (c) => chunks.push(c));
27123
27170
  req.on("end", () => {
27124
27171
  const raw = Buffer.concat(chunks).toString("utf-8");
27125
27172
  if (!raw.trim()) {
27126
- resolve23({});
27173
+ resolve24({});
27127
27174
  return;
27128
27175
  }
27129
27176
  try {
27130
- resolve23(JSON.parse(raw));
27177
+ resolve24(JSON.parse(raw));
27131
27178
  } catch (err) {
27132
27179
  reject(err instanceof Error ? err : new Error(String(err)));
27133
27180
  }
@@ -27419,7 +27466,7 @@ function buildServer(opts) {
27419
27466
  const runTurn = opts.runTurn ?? runChatTurn;
27420
27467
  const createStore = opts.createStore ?? createSessionStore;
27421
27468
  const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
27422
- const reposRoot = opts.reposRoot ?? path54.join(path54.dirname(path54.resolve(opts.cwd)), "repos");
27469
+ const reposRoot = opts.reposRoot ?? path55.join(path55.dirname(path55.resolve(opts.cwd)), "repos");
27423
27470
  return createServer2(async (req, res) => {
27424
27471
  if (!req.method || !req.url) {
27425
27472
  sendJson(res, 400, { error: "bad request" });
@@ -27500,11 +27547,11 @@ async function brainServe(opts) {
27500
27547
  litellmUrl,
27501
27548
  driver
27502
27549
  });
27503
- await new Promise((resolve23) => {
27550
+ await new Promise((resolve24) => {
27504
27551
  server.listen(port, "0.0.0.0", () => {
27505
27552
  process.stdout.write(`[brain-serve] listening on 0.0.0.0:${port} (cwd=${opts.cwd})
27506
27553
  `);
27507
- resolve23();
27554
+ resolve24();
27508
27555
  });
27509
27556
  });
27510
27557
  const shutdown = (signal) => {
@@ -27759,14 +27806,14 @@ async function startBrainProxy(opts) {
27759
27806
  const { httpServer, handler } = buildBrainProxy(opts);
27760
27807
  const port = opts.port ?? 0;
27761
27808
  const host = opts.host ?? "127.0.0.1";
27762
- await new Promise((resolve23) => httpServer.listen(port, host, () => resolve23()));
27809
+ await new Promise((resolve24) => httpServer.listen(port, host, () => resolve24()));
27763
27810
  const addr = httpServer.address();
27764
27811
  return {
27765
27812
  httpServer,
27766
27813
  port: addr.port,
27767
27814
  url: `http://${host}:${addr.port}`,
27768
- stop: () => new Promise((resolve23) => {
27769
- httpServer.close(() => resolve23());
27815
+ stop: () => new Promise((resolve24) => {
27816
+ httpServer.close(() => resolve24());
27770
27817
  }),
27771
27818
  handler
27772
27819
  };
@@ -27916,23 +27963,23 @@ function buildMcpHttpServer(opts) {
27916
27963
  httpServer,
27917
27964
  routes,
27918
27965
  port,
27919
- stop: () => new Promise((resolve23) => {
27966
+ stop: () => new Promise((resolve24) => {
27920
27967
  let pending = transports.size;
27921
27968
  if (pending === 0) {
27922
- httpServer.close(() => resolve23());
27969
+ httpServer.close(() => resolve24());
27923
27970
  return;
27924
27971
  }
27925
27972
  for (const transport of transports.values()) {
27926
27973
  void transport.close().finally(() => {
27927
27974
  pending--;
27928
- if (pending === 0) httpServer.close(() => resolve23());
27975
+ if (pending === 0) httpServer.close(() => resolve24());
27929
27976
  });
27930
27977
  }
27931
27978
  })
27932
27979
  };
27933
27980
  }
27934
27981
  function listenMcpHttpServer(server, host = "127.0.0.1") {
27935
- return new Promise((resolve23, reject) => {
27982
+ return new Promise((resolve24, reject) => {
27936
27983
  server.httpServer.once("error", reject);
27937
27984
  server.httpServer.listen(server.port, host, () => {
27938
27985
  server.httpServer.off("error", reject);
@@ -27940,7 +27987,7 @@ function listenMcpHttpServer(server, host = "127.0.0.1") {
27940
27987
  if (addr && typeof addr === "object") {
27941
27988
  server.port = addr.port;
27942
27989
  }
27943
- resolve23();
27990
+ resolve24();
27944
27991
  });
27945
27992
  });
27946
27993
  }
@@ -28023,7 +28070,7 @@ async function loadConfigSafe() {
28023
28070
  }
28024
28071
 
28025
28072
  // src/chat-cli.ts
28026
- import * as path55 from "path";
28073
+ import * as path56 from "path";
28027
28074
 
28028
28075
  // src/chat/inbox.ts
28029
28076
  import { execFileSync as execFileSync25 } from "child_process";
@@ -28090,7 +28137,7 @@ async function waitForNextUserMessage(opts) {
28090
28137
  }
28091
28138
  }
28092
28139
  function sleep3(ms) {
28093
- return new Promise((resolve23) => setTimeout(resolve23, ms));
28140
+ return new Promise((resolve24) => setTimeout(resolve24, ms));
28094
28141
  }
28095
28142
  function currentBranch(cwd) {
28096
28143
  try {
@@ -28314,7 +28361,7 @@ async function runChat(argv) {
28314
28361
  ${CHAT_HELP}`);
28315
28362
  return 64;
28316
28363
  }
28317
- const cwd = args.cwd ? path55.resolve(args.cwd) : process.cwd();
28364
+ const cwd = args.cwd ? path56.resolve(args.cwd) : process.cwd();
28318
28365
  const sessionId = args.sessionId;
28319
28366
  const runRequest = readRunRequestFromEnv();
28320
28367
  if (runRequest && "request" in runRequest) {
@@ -28441,7 +28488,7 @@ init_registry();
28441
28488
 
28442
28489
  // src/servers/brain-terminal-agent.ts
28443
28490
  init_repoWorkspace();
28444
- import * as path57 from "path";
28491
+ import * as path58 from "path";
28445
28492
  import { createInterface as createInterface2 } from "readline";
28446
28493
 
28447
28494
  // src/terminal/brain-terminal-session.ts
@@ -28755,10 +28802,10 @@ var BrainTerminalSessionAgent = class {
28755
28802
  // src/terminal/brain-terminal-adapters.ts
28756
28803
  import { createHash as createHash10, randomBytes as randomBytes2 } from "crypto";
28757
28804
  import { mkdir, readFile, rename, writeFile as writeFile2 } from "fs/promises";
28758
- import * as path56 from "path";
28805
+ import * as path57 from "path";
28759
28806
  import { spawn as spawn9 } from "child_process";
28760
28807
  function runTerminalCommand(command, args, input) {
28761
- return new Promise((resolve23, reject) => {
28808
+ return new Promise((resolve24, reject) => {
28762
28809
  const child = spawn9(command, args, { stdio: ["pipe", "pipe", "pipe"] });
28763
28810
  const stdout = [];
28764
28811
  const stderr = [];
@@ -28766,7 +28813,7 @@ function runTerminalCommand(command, args, input) {
28766
28813
  child.stderr.on("data", (chunk) => stderr.push(chunk));
28767
28814
  child.on("error", reject);
28768
28815
  child.on("close", (code) => {
28769
- resolve23({
28816
+ resolve24({
28770
28817
  code: code ?? 1,
28771
28818
  stdout: Buffer.concat(stdout).toString("utf8"),
28772
28819
  stderr: Buffer.concat(stderr).toString("utf8")
@@ -28790,7 +28837,7 @@ var FileBrainTerminalMetadataStore = class {
28790
28837
  }
28791
28838
  root;
28792
28839
  file(id) {
28793
- return path56.join(this.root, `${storeKey(id)}.json`);
28840
+ return path57.join(this.root, `${storeKey(id)}.json`);
28794
28841
  }
28795
28842
  async read(id) {
28796
28843
  try {
@@ -28911,8 +28958,8 @@ async function brainTerminalAgent(options) {
28911
28958
  const input = options.input ?? process.stdin;
28912
28959
  const output = options.output ?? process.stdout;
28913
28960
  const error = options.error ?? process.stderr;
28914
- const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() || path57.join(path57.dirname(path57.resolve(options.cwd)), "repos");
28915
- const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() || path57.join(path57.dirname(reposRoot), ".kody", "terminal-sessions");
28961
+ const reposRoot = process.env.BRAIN_REPOS_ROOT?.trim() || path58.join(path58.dirname(path58.resolve(options.cwd)), "repos");
28962
+ const stateRoot = process.env.BRAIN_TERMINAL_STATE_ROOT?.trim() || path58.join(path58.dirname(reposRoot), ".kody", "terminal-sessions");
28916
28963
  const agent = new BrainTerminalSessionAgent({
28917
28964
  store: new FileBrainTerminalMetadataStore(stateRoot),
28918
28965
  runtime: new TmuxBrainTerminalRuntime()
@@ -29079,8 +29126,8 @@ var FlyClient = class {
29079
29126
  get fetch() {
29080
29127
  return this.opts.fetchImpl ?? fetch;
29081
29128
  }
29082
- async call(path58, init = {}) {
29083
- const res = await this.fetch(`${FLY_API_BASE}${path58}`, {
29129
+ async call(path59, init = {}) {
29130
+ const res = await this.fetch(`${FLY_API_BASE}${path59}`, {
29084
29131
  method: init.method ?? "GET",
29085
29132
  headers: {
29086
29133
  Authorization: `Bearer ${this.opts.token}`,
@@ -29091,7 +29138,7 @@ var FlyClient = class {
29091
29138
  if (res.status === 404 && init.allow404) return null;
29092
29139
  if (!res.ok) {
29093
29140
  const text2 = await res.text().catch(() => "");
29094
- throw new Error(`Fly API ${res.status} on ${path58}: ${text2.slice(0, 200) || res.statusText}`);
29141
+ throw new Error(`Fly API ${res.status} on ${path59}: ${text2.slice(0, 200) || res.statusText}`);
29095
29142
  }
29096
29143
  if (res.status === 204) return null;
29097
29144
  const raw = await res.text();
@@ -29604,14 +29651,14 @@ function sendJson2(res, status, body) {
29604
29651
  res.end(JSON.stringify(body));
29605
29652
  }
29606
29653
  function readJsonBody2(req) {
29607
- return new Promise((resolve23, reject) => {
29654
+ return new Promise((resolve24, reject) => {
29608
29655
  const chunks = [];
29609
29656
  req.on("data", (c) => chunks.push(c));
29610
29657
  req.on("end", () => {
29611
29658
  const raw = Buffer.concat(chunks).toString("utf-8");
29612
- if (!raw.trim()) return resolve23({});
29659
+ if (!raw.trim()) return resolve24({});
29613
29660
  try {
29614
- resolve23(JSON.parse(raw));
29661
+ resolve24(JSON.parse(raw));
29615
29662
  } catch (err) {
29616
29663
  reject(err instanceof Error ? err : new Error(String(err)));
29617
29664
  }
@@ -29765,10 +29812,10 @@ async function poolServe() {
29765
29812
  }
29766
29813
  });
29767
29814
  const apiHost = process.env.POOL_API_HOST ?? "::";
29768
- await new Promise((resolve23) => {
29815
+ await new Promise((resolve24) => {
29769
29816
  server.listen(apiPort, apiHost, () => {
29770
29817
  log(`listening on ${apiHost}:${apiPort} (min=${min}, app=${app}, region=${region})`);
29771
- resolve23();
29818
+ resolve24();
29772
29819
  });
29773
29820
  });
29774
29821
  if (loopTickEnabled) void runLoopTick();
@@ -29808,17 +29855,17 @@ function authOk2(req, expected) {
29808
29855
  return false;
29809
29856
  }
29810
29857
  function readJsonBody3(req) {
29811
- return new Promise((resolve23, reject) => {
29858
+ return new Promise((resolve24, reject) => {
29812
29859
  const chunks = [];
29813
29860
  req.on("data", (c) => chunks.push(c));
29814
29861
  req.on("end", () => {
29815
29862
  const raw = Buffer.concat(chunks).toString("utf-8");
29816
29863
  if (!raw.trim()) {
29817
- resolve23({});
29864
+ resolve24({});
29818
29865
  return;
29819
29866
  }
29820
29867
  try {
29821
- resolve23(JSON.parse(raw));
29868
+ resolve24(JSON.parse(raw));
29822
29869
  } catch (err) {
29823
29870
  reject(err instanceof Error ? err : new Error(String(err)));
29824
29871
  }
@@ -29893,13 +29940,13 @@ async function defaultRunJob(job) {
29893
29940
  ...interactive && job.idleExitMs ? { KODY_IDLE_EXIT_MS: String(job.idleExitMs) } : {},
29894
29941
  ...interactive && job.hardCapMs ? { KODY_HARD_CAP_MS: String(job.hardCapMs) } : {}
29895
29942
  };
29896
- const run = (cmd, args, cwd) => new Promise((resolve23) => {
29943
+ const run = (cmd, args, cwd) => new Promise((resolve24) => {
29897
29944
  const child = spawn10(cmd, args, { stdio: "inherit", env: childEnv, cwd });
29898
- child.on("exit", (code) => resolve23(code ?? 0));
29945
+ child.on("exit", (code) => resolve24(code ?? 0));
29899
29946
  child.on("error", (err) => {
29900
29947
  process.stderr.write(`[runner-serve] ${cmd} failed: ${err.message}
29901
29948
  `);
29902
- resolve23(1);
29949
+ resolve24(1);
29903
29950
  });
29904
29951
  });
29905
29952
  process.stdout.write(`[runner-serve] job ${job.jobId}: cloning ${job.repo}@${branch}
@@ -29975,11 +30022,11 @@ async function runnerServe() {
29975
30022
  const port = Number(process.env.PORT ?? DEFAULT_PORT2);
29976
30023
  const server = buildServer2({ apiKey });
29977
30024
  const host = process.env.RUNNER_HOST ?? "::";
29978
- await new Promise((resolve23) => {
30025
+ await new Promise((resolve24) => {
29979
30026
  server.listen(port, host, () => {
29980
30027
  process.stdout.write(`[runner-serve] listening on ${host}:${port} (idle, awaiting job)
29981
30028
  `);
29982
- resolve23();
30029
+ resolve24();
29983
30030
  });
29984
30031
  });
29985
30032
  const shutdown = (signal) => {
@@ -30048,14 +30095,14 @@ async function serve(opts) {
30048
30095
  `);
30049
30096
  const args = ["--dangerously-skip-permissions", "--model", model.model];
30050
30097
  const child = spawn11("claude", args, { stdio: "inherit", env: editorEnv, cwd: opts.cwd });
30051
- const exitCode = await new Promise((resolve23) => {
30052
- child.on("exit", (code) => resolve23(code ?? 0));
30098
+ const exitCode = await new Promise((resolve24) => {
30099
+ child.on("exit", (code) => resolve24(code ?? 0));
30053
30100
  child.on("error", (err) => {
30054
30101
  process.stderr.write(`[kody serve] failed to launch Claude Code: ${err.message}
30055
30102
  `);
30056
30103
  process.stderr.write(` Install: https://docs.anthropic.com/claude/docs/claude-code
30057
30104
  `);
30058
- resolve23(1);
30105
+ resolve24(1);
30059
30106
  });
30060
30107
  });
30061
30108
  killProxy();