claudecode-omc 4.7.4 → 4.8.1

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 (133) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +50 -0
  3. package/agents/test-engineer.md +74 -0
  4. package/bridge/cli.cjs +1960 -108
  5. package/dist/cli/index.js +181 -0
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/hud/usage-api.d.ts.map +1 -1
  8. package/dist/hud/usage-api.js +14 -0
  9. package/dist/hud/usage-api.js.map +1 -1
  10. package/dist/testing/analyzers/complexity.d.ts +18 -0
  11. package/dist/testing/analyzers/complexity.d.ts.map +1 -0
  12. package/dist/testing/analyzers/complexity.js +121 -0
  13. package/dist/testing/analyzers/complexity.js.map +1 -0
  14. package/dist/testing/analyzers/coverage.d.ts +13 -0
  15. package/dist/testing/analyzers/coverage.d.ts.map +1 -0
  16. package/dist/testing/analyzers/coverage.js +99 -0
  17. package/dist/testing/analyzers/coverage.js.map +1 -0
  18. package/dist/testing/analyzers/quality-scorer.d.ts +8 -0
  19. package/dist/testing/analyzers/quality-scorer.d.ts.map +1 -0
  20. package/dist/testing/analyzers/quality-scorer.js +128 -0
  21. package/dist/testing/analyzers/quality-scorer.js.map +1 -0
  22. package/dist/testing/analyzers/types.d.ts +56 -0
  23. package/dist/testing/analyzers/types.d.ts.map +1 -0
  24. package/dist/testing/analyzers/types.js +2 -0
  25. package/dist/testing/analyzers/types.js.map +1 -0
  26. package/dist/testing/cli/agent-integration.d.ts +20 -0
  27. package/dist/testing/cli/agent-integration.d.ts.map +1 -0
  28. package/dist/testing/cli/agent-integration.js +60 -0
  29. package/dist/testing/cli/agent-integration.js.map +1 -0
  30. package/dist/testing/cli/commands.d.ts +89 -0
  31. package/dist/testing/cli/commands.d.ts.map +1 -0
  32. package/dist/testing/cli/commands.js +228 -0
  33. package/dist/testing/cli/commands.js.map +1 -0
  34. package/dist/testing/cli/ultraqa-integration.d.ts +13 -0
  35. package/dist/testing/cli/ultraqa-integration.d.ts.map +1 -0
  36. package/dist/testing/cli/ultraqa-integration.js +68 -0
  37. package/dist/testing/cli/ultraqa-integration.js.map +1 -0
  38. package/dist/testing/detectors/go.d.ts +3 -0
  39. package/dist/testing/detectors/go.d.ts.map +1 -0
  40. package/dist/testing/detectors/go.js +38 -0
  41. package/dist/testing/detectors/go.js.map +1 -0
  42. package/dist/testing/detectors/index.d.ts +8 -0
  43. package/dist/testing/detectors/index.d.ts.map +1 -0
  44. package/dist/testing/detectors/index.js +46 -0
  45. package/dist/testing/detectors/index.js.map +1 -0
  46. package/dist/testing/detectors/package-json.d.ts +3 -0
  47. package/dist/testing/detectors/package-json.d.ts.map +1 -0
  48. package/dist/testing/detectors/package-json.js +52 -0
  49. package/dist/testing/detectors/package-json.js.map +1 -0
  50. package/dist/testing/detectors/python.d.ts +3 -0
  51. package/dist/testing/detectors/python.d.ts.map +1 -0
  52. package/dist/testing/detectors/python.js +37 -0
  53. package/dist/testing/detectors/python.js.map +1 -0
  54. package/dist/testing/detectors/rust.d.ts +3 -0
  55. package/dist/testing/detectors/rust.d.ts.map +1 -0
  56. package/dist/testing/detectors/rust.js +39 -0
  57. package/dist/testing/detectors/rust.js.map +1 -0
  58. package/dist/testing/generators/contract.d.ts +14 -0
  59. package/dist/testing/generators/contract.d.ts.map +1 -0
  60. package/dist/testing/generators/contract.js +163 -0
  61. package/dist/testing/generators/contract.js.map +1 -0
  62. package/dist/testing/generators/e2e.d.ts +34 -0
  63. package/dist/testing/generators/e2e.d.ts.map +1 -0
  64. package/dist/testing/generators/e2e.js +74 -0
  65. package/dist/testing/generators/e2e.js.map +1 -0
  66. package/dist/testing/generators/go.d.ts +12 -0
  67. package/dist/testing/generators/go.d.ts.map +1 -0
  68. package/dist/testing/generators/go.js +144 -0
  69. package/dist/testing/generators/go.js.map +1 -0
  70. package/dist/testing/generators/nodejs.d.ts +12 -0
  71. package/dist/testing/generators/nodejs.d.ts.map +1 -0
  72. package/dist/testing/generators/nodejs.js +37 -0
  73. package/dist/testing/generators/nodejs.js.map +1 -0
  74. package/dist/testing/generators/python.d.ts +12 -0
  75. package/dist/testing/generators/python.d.ts.map +1 -0
  76. package/dist/testing/generators/python.js +163 -0
  77. package/dist/testing/generators/python.js.map +1 -0
  78. package/dist/testing/generators/react.d.ts +12 -0
  79. package/dist/testing/generators/react.d.ts.map +1 -0
  80. package/dist/testing/generators/react.js +31 -0
  81. package/dist/testing/generators/react.js.map +1 -0
  82. package/dist/testing/generators/rust.d.ts +11 -0
  83. package/dist/testing/generators/rust.d.ts.map +1 -0
  84. package/dist/testing/generators/rust.js +138 -0
  85. package/dist/testing/generators/rust.js.map +1 -0
  86. package/dist/testing/index.d.ts +6 -0
  87. package/dist/testing/index.d.ts.map +1 -0
  88. package/dist/testing/index.js +11 -0
  89. package/dist/testing/index.js.map +1 -0
  90. package/dist/testing/integrations/autopilot.d.ts +42 -0
  91. package/dist/testing/integrations/autopilot.d.ts.map +1 -0
  92. package/dist/testing/integrations/autopilot.js +55 -0
  93. package/dist/testing/integrations/autopilot.js.map +1 -0
  94. package/dist/testing/integrations/cicd.d.ts +26 -0
  95. package/dist/testing/integrations/cicd.d.ts.map +1 -0
  96. package/dist/testing/integrations/cicd.js +162 -0
  97. package/dist/testing/integrations/cicd.js.map +1 -0
  98. package/dist/testing/integrations/giskard/behavioral-tests.d.ts +4 -0
  99. package/dist/testing/integrations/giskard/behavioral-tests.d.ts.map +1 -0
  100. package/dist/testing/integrations/giskard/behavioral-tests.js +66 -0
  101. package/dist/testing/integrations/giskard/behavioral-tests.js.map +1 -0
  102. package/dist/testing/integrations/giskard/types.d.ts +35 -0
  103. package/dist/testing/integrations/giskard/types.d.ts.map +1 -0
  104. package/dist/testing/integrations/giskard/types.js +2 -0
  105. package/dist/testing/integrations/giskard/types.js.map +1 -0
  106. package/dist/testing/integrations/ralph.d.ts +65 -0
  107. package/dist/testing/integrations/ralph.d.ts.map +1 -0
  108. package/dist/testing/integrations/ralph.js +69 -0
  109. package/dist/testing/integrations/ralph.js.map +1 -0
  110. package/dist/testing/performance/cache-manager.d.ts +16 -0
  111. package/dist/testing/performance/cache-manager.d.ts.map +1 -0
  112. package/dist/testing/performance/cache-manager.js +39 -0
  113. package/dist/testing/performance/cache-manager.js.map +1 -0
  114. package/dist/testing/performance/parallel-generator.d.ts +23 -0
  115. package/dist/testing/performance/parallel-generator.d.ts.map +1 -0
  116. package/dist/testing/performance/parallel-generator.js +31 -0
  117. package/dist/testing/performance/parallel-generator.js.map +1 -0
  118. package/dist/testing/types.d.ts +23 -0
  119. package/dist/testing/types.d.ts.map +1 -0
  120. package/dist/testing/types.js +2 -0
  121. package/dist/testing/types.js.map +1 -0
  122. package/docs/2026-03-06-llm-testing-system-phase1.md +0 -0
  123. package/docs/plans/2026-03-06-llm-testing-system-design.md +311 -0
  124. package/docs/plans/2026-03-06-llm-testing-system-phase1.md +1268 -0
  125. package/docs/plans/2026-03-06-llm-testing-system-phase2.md +3053 -0
  126. package/docs/plans/2026-03-06-llm-testing-system-phase3.md +1830 -0
  127. package/docs/testing/IMPLEMENTATION.md +804 -0
  128. package/docs/testing/PHASE2.md +266 -0
  129. package/docs/testing/PHASE3.md +601 -0
  130. package/docs/testing/README.md +634 -0
  131. package/package.json +1 -1
  132. package/skills/test-gen/skill.md +531 -0
  133. package/skills/ultraqa.md +58 -0
package/bridge/cli.cjs CHANGED
@@ -967,8 +967,8 @@ var require_command = __commonJS({
967
967
  "node_modules/commander/lib/command.js"(exports2) {
968
968
  var EventEmitter = require("node:events").EventEmitter;
969
969
  var childProcess = require("node:child_process");
970
- var path20 = require("node:path");
971
- var fs19 = require("node:fs");
970
+ var path26 = require("node:path");
971
+ var fs25 = require("node:fs");
972
972
  var process3 = require("node:process");
973
973
  var { Argument: Argument2, humanReadableArgName } = require_argument();
974
974
  var { CommanderError: CommanderError2 } = require_error();
@@ -1900,11 +1900,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1900
1900
  let launchWithNode = false;
1901
1901
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1902
1902
  function findFile(baseDir, baseName) {
1903
- const localBin = path20.resolve(baseDir, baseName);
1904
- if (fs19.existsSync(localBin)) return localBin;
1905
- if (sourceExt.includes(path20.extname(baseName))) return void 0;
1903
+ const localBin = path26.resolve(baseDir, baseName);
1904
+ if (fs25.existsSync(localBin)) return localBin;
1905
+ if (sourceExt.includes(path26.extname(baseName))) return void 0;
1906
1906
  const foundExt = sourceExt.find(
1907
- (ext) => fs19.existsSync(`${localBin}${ext}`)
1907
+ (ext) => fs25.existsSync(`${localBin}${ext}`)
1908
1908
  );
1909
1909
  if (foundExt) return `${localBin}${foundExt}`;
1910
1910
  return void 0;
@@ -1916,21 +1916,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1916
1916
  if (this._scriptPath) {
1917
1917
  let resolvedScriptPath;
1918
1918
  try {
1919
- resolvedScriptPath = fs19.realpathSync(this._scriptPath);
1919
+ resolvedScriptPath = fs25.realpathSync(this._scriptPath);
1920
1920
  } catch (err) {
1921
1921
  resolvedScriptPath = this._scriptPath;
1922
1922
  }
1923
- executableDir = path20.resolve(
1924
- path20.dirname(resolvedScriptPath),
1923
+ executableDir = path26.resolve(
1924
+ path26.dirname(resolvedScriptPath),
1925
1925
  executableDir
1926
1926
  );
1927
1927
  }
1928
1928
  if (executableDir) {
1929
1929
  let localFile = findFile(executableDir, executableFile);
1930
1930
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1931
- const legacyName = path20.basename(
1931
+ const legacyName = path26.basename(
1932
1932
  this._scriptPath,
1933
- path20.extname(this._scriptPath)
1933
+ path26.extname(this._scriptPath)
1934
1934
  );
1935
1935
  if (legacyName !== this._name) {
1936
1936
  localFile = findFile(
@@ -1941,7 +1941,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1941
1941
  }
1942
1942
  executableFile = localFile || executableFile;
1943
1943
  }
1944
- launchWithNode = sourceExt.includes(path20.extname(executableFile));
1944
+ launchWithNode = sourceExt.includes(path26.extname(executableFile));
1945
1945
  let proc;
1946
1946
  if (process3.platform !== "win32") {
1947
1947
  if (launchWithNode) {
@@ -2781,7 +2781,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2781
2781
  * @return {Command}
2782
2782
  */
2783
2783
  nameFromFilename(filename) {
2784
- this._name = path20.basename(filename, path20.extname(filename));
2784
+ this._name = path26.basename(filename, path26.extname(filename));
2785
2785
  return this;
2786
2786
  }
2787
2787
  /**
@@ -2795,9 +2795,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2795
2795
  * @param {string} [path]
2796
2796
  * @return {(string|null|Command)}
2797
2797
  */
2798
- executableDir(path21) {
2799
- if (path21 === void 0) return this._executableDir;
2800
- this._executableDir = path21;
2798
+ executableDir(path27) {
2799
+ if (path27 === void 0) return this._executableDir;
2800
+ this._executableDir = path27;
2801
2801
  return this;
2802
2802
  }
2803
2803
  /**
@@ -3041,8 +3041,8 @@ var init_config_dir = __esm({
3041
3041
  });
3042
3042
 
3043
3043
  // src/utils/paths.ts
3044
- function toForwardSlash(path20) {
3045
- return path20.replace(/\\/g, "/");
3044
+ function toForwardSlash(path26) {
3045
+ return path26.replace(/\\/g, "/");
3046
3046
  }
3047
3047
  function getClaudeConfigDir() {
3048
3048
  return getConfigDir();
@@ -3382,16 +3382,16 @@ function getConfigPaths() {
3382
3382
  project: (0, import_path2.join)(process.cwd(), ".claude", "omc.jsonc")
3383
3383
  };
3384
3384
  }
3385
- function loadJsoncFile(path20) {
3386
- if (!(0, import_fs2.existsSync)(path20)) {
3385
+ function loadJsoncFile(path26) {
3386
+ if (!(0, import_fs2.existsSync)(path26)) {
3387
3387
  return null;
3388
3388
  }
3389
3389
  try {
3390
- const content = (0, import_fs2.readFileSync)(path20, "utf-8");
3390
+ const content = (0, import_fs2.readFileSync)(path26, "utf-8");
3391
3391
  const result = parseJsonc(content);
3392
3392
  return result;
3393
3393
  } catch (error2) {
3394
- console.error(`Error loading config from ${path20}:`, error2);
3394
+ console.error(`Error loading config from ${path26}:`, error2);
3395
3395
  return null;
3396
3396
  }
3397
3397
  }
@@ -17617,12 +17617,12 @@ async function pollTelegram(config2, state, rateLimiter) {
17617
17617
  }
17618
17618
  try {
17619
17619
  const offset = state.telegramLastUpdateId ? state.telegramLastUpdateId + 1 : 0;
17620
- const path20 = `/bot${config2.telegramBotToken}/getUpdates?offset=${offset}&timeout=0`;
17620
+ const path26 = `/bot${config2.telegramBotToken}/getUpdates?offset=${offset}&timeout=0`;
17621
17621
  const updates = await new Promise((resolve12, reject) => {
17622
17622
  const req = (0, import_https2.request)(
17623
17623
  {
17624
17624
  hostname: "api.telegram.org",
17625
- path: path20,
17625
+ path: path26,
17626
17626
  method: "GET",
17627
17627
  family: 4,
17628
17628
  // Force IPv4
@@ -19132,8 +19132,8 @@ async function exportWisdomToNotepad(directory) {
19132
19132
  let hasWisdom = false;
19133
19133
  try {
19134
19134
  const planDirs = (0, import_fs53.readdirSync)(notepadsDir).filter((name) => {
19135
- const path20 = (0, import_path62.join)(notepadsDir, name);
19136
- return (0, import_fs53.statSync)(path20).isDirectory();
19135
+ const path26 = (0, import_path62.join)(notepadsDir, name);
19136
+ return (0, import_fs53.statSync)(path26).isDirectory();
19137
19137
  });
19138
19138
  for (const planDir of planDirs) {
19139
19139
  const planPath = (0, import_path62.join)(notepadsDir, planDir);
@@ -19192,9 +19192,9 @@ async function saveModeSummary(directory) {
19192
19192
  }
19193
19193
  ];
19194
19194
  const reads = stateFiles.map(async (config2) => {
19195
- const path20 = (0, import_path62.join)(stateDir, config2.file);
19195
+ const path26 = (0, import_path62.join)(stateDir, config2.file);
19196
19196
  try {
19197
- const content = await import_fs54.promises.readFile(path20, "utf-8");
19197
+ const content = await import_fs54.promises.readFile(path26, "utf-8");
19198
19198
  const state = JSON.parse(content);
19199
19199
  const extracted = config2.extract(state);
19200
19200
  return extracted ? { key: config2.key, value: extracted } : null;
@@ -21572,6 +21572,17 @@ async function getUsage() {
21572
21572
  const authToken = process.env.ANTHROPIC_AUTH_TOKEN;
21573
21573
  const isZai = baseUrl != null && isZaiHost(baseUrl);
21574
21574
  const currentSource = isZai && authToken ? "zai" : "anthropic";
21575
+ if (!isZai || !authToken) {
21576
+ const creds2 = getCredentials();
21577
+ if (!creds2) {
21578
+ const cache2 = readCache();
21579
+ if (cache2 && isCacheValid(cache2) && cache2.errorReason === "no_credentials") {
21580
+ return { rateLimits: null, error: "no_credentials" };
21581
+ }
21582
+ writeCache(null, true, "anthropic", false, 0, "no_credentials");
21583
+ return { rateLimits: null, error: "no_credentials" };
21584
+ }
21585
+ }
21575
21586
  const cache = readCache();
21576
21587
  if (cache && isCacheValid(cache) && cache.source === currentSource) {
21577
21588
  if (cache.rateLimited) {
@@ -23234,7 +23245,7 @@ async function requeueDeadWorkerTasks(teamName, deadWorkerNames, cwd2) {
23234
23245
  await writeFile5(sidecarPath, JSON.stringify(sidecar, null, 2), "utf-8");
23235
23246
  const taskPath2 = absPath(cwd2, TeamPaths.taskFile(sanitized, task.id));
23236
23247
  try {
23237
- const raw = await import("fs/promises").then((fs19) => fs19.readFile(taskPath2, "utf-8"));
23248
+ const raw = await import("fs/promises").then((fs25) => fs25.readFile(taskPath2, "utf-8"));
23238
23249
  const taskData = JSON.parse(raw);
23239
23250
  taskData.status = "pending";
23240
23251
  taskData.owner = void 0;
@@ -26820,6 +26831,1718 @@ var init_hud = __esm({
26820
26831
  }
26821
26832
  });
26822
26833
 
26834
+ // src/testing/detectors/package-json.ts
26835
+ async function detectFromPackageJson(packageJson) {
26836
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
26837
+ const stack = {};
26838
+ if (deps.react) {
26839
+ stack.frontend = {
26840
+ framework: "react",
26841
+ testFramework: deps.vitest ? "vitest" : deps.jest ? "jest" : "none"
26842
+ };
26843
+ } else if (deps.vue) {
26844
+ stack.frontend = {
26845
+ framework: "vue",
26846
+ testFramework: deps.vitest ? "vitest" : "none"
26847
+ };
26848
+ } else if (deps.svelte) {
26849
+ stack.frontend = {
26850
+ framework: "svelte",
26851
+ testFramework: deps.vitest ? "vitest" : "none"
26852
+ };
26853
+ }
26854
+ if (deps.express || deps.fastify || deps.koa) {
26855
+ stack.backend = {
26856
+ language: "nodejs",
26857
+ testFramework: deps.vitest ? "vitest" : deps.jest ? "jest" : void 0
26858
+ };
26859
+ }
26860
+ const databases = [];
26861
+ if (deps.pg || deps.postgres) databases.push("postgresql");
26862
+ if (deps.mysql || deps.mysql2) databases.push("mysql");
26863
+ if (deps.mongodb || deps.mongoose) databases.push("mongodb");
26864
+ if (databases.length > 0) stack.databases = databases;
26865
+ const apis = [];
26866
+ if (deps.express || deps.fastify) apis.push("rest");
26867
+ if (deps.graphql || deps["@apollo/server"]) apis.push("graphql");
26868
+ if (deps["@grpc/grpc-js"]) apis.push("grpc");
26869
+ if (apis.length > 0) stack.apis = apis;
26870
+ return stack;
26871
+ }
26872
+ var init_package_json = __esm({
26873
+ "src/testing/detectors/package-json.ts"() {
26874
+ "use strict";
26875
+ }
26876
+ });
26877
+
26878
+ // src/testing/detectors/python.ts
26879
+ async function detectPythonStack(projectRoot) {
26880
+ const stack = {};
26881
+ try {
26882
+ const requirementsPath = import_path107.default.join(projectRoot, "requirements.txt");
26883
+ const requirements = await import_promises16.default.readFile(requirementsPath, "utf-8");
26884
+ stack.backend = {
26885
+ language: "python",
26886
+ testFramework: requirements.includes("pytest") ? "pytest" : requirements.includes("unittest") ? "unittest" : void 0
26887
+ };
26888
+ const databases = [];
26889
+ if (requirements.includes("psycopg2") || requirements.includes("psycopg3")) databases.push("postgresql");
26890
+ if (requirements.includes("pymysql") || requirements.includes("mysql-connector")) databases.push("mysql");
26891
+ if (requirements.includes("pymongo")) databases.push("mongodb");
26892
+ if (databases.length > 0) stack.databases = databases;
26893
+ const apis = [];
26894
+ if (requirements.includes("flask") || requirements.includes("fastapi") || requirements.includes("django")) apis.push("rest");
26895
+ if (requirements.includes("graphene") || requirements.includes("strawberry")) apis.push("graphql");
26896
+ if (apis.length > 0) stack.apis = apis;
26897
+ } catch (error2) {
26898
+ }
26899
+ return stack;
26900
+ }
26901
+ var import_promises16, import_path107;
26902
+ var init_python = __esm({
26903
+ "src/testing/detectors/python.ts"() {
26904
+ "use strict";
26905
+ import_promises16 = __toESM(require("fs/promises"), 1);
26906
+ import_path107 = __toESM(require("path"), 1);
26907
+ }
26908
+ });
26909
+
26910
+ // src/testing/detectors/go.ts
26911
+ async function detectGoStack(projectRoot) {
26912
+ const stack = {};
26913
+ try {
26914
+ const goModPath = import_path108.default.join(projectRoot, "go.mod");
26915
+ const goMod = await import_promises17.default.readFile(goModPath, "utf-8");
26916
+ stack.backend = {
26917
+ language: "go",
26918
+ testFramework: "testing"
26919
+ };
26920
+ const databases = [];
26921
+ if (goMod.includes("github.com/lib/pq") || goMod.includes("github.com/jackc/pgx")) databases.push("postgresql");
26922
+ if (goMod.includes("github.com/go-sql-driver/mysql")) databases.push("mysql");
26923
+ if (goMod.includes("go.mongodb.org/mongo-driver")) databases.push("mongodb");
26924
+ if (databases.length > 0) stack.databases = databases;
26925
+ const apis = [];
26926
+ if (goMod.includes("github.com/gin-gonic/gin") || goMod.includes("github.com/gorilla/mux")) apis.push("rest");
26927
+ if (goMod.includes("github.com/graphql-go/graphql")) apis.push("graphql");
26928
+ if (goMod.includes("google.golang.org/grpc")) apis.push("grpc");
26929
+ if (apis.length > 0) stack.apis = apis;
26930
+ } catch (error2) {
26931
+ }
26932
+ return stack;
26933
+ }
26934
+ var import_promises17, import_path108;
26935
+ var init_go = __esm({
26936
+ "src/testing/detectors/go.ts"() {
26937
+ "use strict";
26938
+ import_promises17 = __toESM(require("fs/promises"), 1);
26939
+ import_path108 = __toESM(require("path"), 1);
26940
+ }
26941
+ });
26942
+
26943
+ // src/testing/detectors/rust.ts
26944
+ async function detectRustStack(projectRoot) {
26945
+ const stack = {};
26946
+ try {
26947
+ const cargoTomlPath = import_path109.default.join(projectRoot, "Cargo.toml");
26948
+ const cargoToml = await import_promises18.default.readFile(cargoTomlPath, "utf-8");
26949
+ stack.backend = {
26950
+ language: "rust",
26951
+ testFramework: "cargo test"
26952
+ // Rust's built-in testing
26953
+ };
26954
+ const databases = [];
26955
+ if (cargoToml.includes("tokio-postgres") || cargoToml.includes("sqlx")) databases.push("postgresql");
26956
+ if (cargoToml.includes("mysql_async")) databases.push("mysql");
26957
+ if (cargoToml.includes("mongodb")) databases.push("mongodb");
26958
+ if (databases.length > 0) stack.databases = databases;
26959
+ const apis = [];
26960
+ if (cargoToml.includes("actix-web") || cargoToml.includes("rocket") || cargoToml.includes("axum")) apis.push("rest");
26961
+ if (cargoToml.includes("async-graphql") || cargoToml.includes("juniper")) apis.push("graphql");
26962
+ if (cargoToml.includes("tonic")) apis.push("grpc");
26963
+ if (apis.length > 0) stack.apis = apis;
26964
+ } catch (error2) {
26965
+ }
26966
+ return stack;
26967
+ }
26968
+ var import_promises18, import_path109;
26969
+ var init_rust = __esm({
26970
+ "src/testing/detectors/rust.ts"() {
26971
+ "use strict";
26972
+ import_promises18 = __toESM(require("fs/promises"), 1);
26973
+ import_path109 = __toESM(require("path"), 1);
26974
+ }
26975
+ });
26976
+
26977
+ // src/testing/detectors/index.ts
26978
+ async function detectTechStack(projectRoot) {
26979
+ let stack = {};
26980
+ try {
26981
+ const packageJsonPath = import_path110.default.join(projectRoot, "package.json");
26982
+ const content = await import_promises19.default.readFile(packageJsonPath, "utf-8");
26983
+ const packageJson = JSON.parse(content);
26984
+ stack = await detectFromPackageJson(packageJson);
26985
+ } catch (error2) {
26986
+ }
26987
+ try {
26988
+ const pythonStack = await detectPythonStack(projectRoot);
26989
+ stack = { ...stack, ...pythonStack };
26990
+ } catch (error2) {
26991
+ }
26992
+ try {
26993
+ const goStack = await detectGoStack(projectRoot);
26994
+ stack = { ...stack, ...goStack };
26995
+ } catch (error2) {
26996
+ }
26997
+ try {
26998
+ const rustStack = await detectRustStack(projectRoot);
26999
+ stack = { ...stack, ...rustStack };
27000
+ } catch (error2) {
27001
+ }
27002
+ return stack;
27003
+ }
27004
+ var import_promises19, import_path110;
27005
+ var init_detectors = __esm({
27006
+ "src/testing/detectors/index.ts"() {
27007
+ "use strict";
27008
+ import_promises19 = __toESM(require("fs/promises"), 1);
27009
+ import_path110 = __toESM(require("path"), 1);
27010
+ init_package_json();
27011
+ init_python();
27012
+ init_go();
27013
+ init_rust();
27014
+ }
27015
+ });
27016
+
27017
+ // src/testing/generators/react.ts
27018
+ async function generateReactTest(options) {
27019
+ const { filePath, code, testFramework } = options;
27020
+ const fileName = filePath.split("/").pop()?.replace(/\.(tsx?|jsx?)$/, "") || "Component";
27021
+ const testFilePath = filePath.replace(/\.(tsx?|jsx?)$/, ".test.$1");
27022
+ const hasOnClick = code.includes("onClick");
27023
+ const hasChildren = code.includes("children");
27024
+ const testCode = `import { describe, it, expect${testFramework === "vitest" ? ", vi" : ""} } from '${testFramework}';
27025
+ import { render, screen${hasOnClick ? ", fireEvent" : ""} } from '@testing-library/react';
27026
+ import { ${fileName} } from './${fileName}';
27027
+
27028
+ describe('${fileName}', () => {
27029
+ it('renders children', () => {
27030
+ render(<${fileName}>Click me</${fileName}>);
27031
+ expect(screen.getByText('Click me')).toBeInTheDocument();
27032
+ });
27033
+ ${hasOnClick ? `
27034
+ it('calls onClick when clicked', () => {
27035
+ const handleClick = ${testFramework === "vitest" ? "vi.fn()" : "jest.fn()"};
27036
+ render(<${fileName} onClick={handleClick}>Click me</${fileName}>);
27037
+ fireEvent.click(screen.getByText('Click me'));
27038
+ expect(handleClick).toHaveBeenCalledTimes(1);
27039
+ });
27040
+ ` : ""}});
27041
+ `;
27042
+ return { testFilePath, testCode };
27043
+ }
27044
+ var init_react = __esm({
27045
+ "src/testing/generators/react.ts"() {
27046
+ "use strict";
27047
+ }
27048
+ });
27049
+
27050
+ // src/testing/generators/nodejs.ts
27051
+ async function generateNodeJsTest(options) {
27052
+ const { filePath, code, testFramework } = options;
27053
+ const functionMatches = code.matchAll(/export\s+(?:async\s+)?function\s+(\w+)/g);
27054
+ const functions = Array.from(functionMatches).map((match) => match[1]);
27055
+ const testFilePath = filePath.replace(/\.ts$/, ".test.ts");
27056
+ const fileName = filePath.split("/").pop()?.replace(/\.ts$/, "") || "module";
27057
+ const testCases = functions.map((funcName) => {
27058
+ if (funcName === "add") {
27059
+ return ` it('adds two numbers', () => {
27060
+ expect(add(2, 3)).toBe(5);
27061
+ expect(add(-1, 1)).toBe(0);
27062
+ expect(add(0, 0)).toBe(0);
27063
+ });`;
27064
+ }
27065
+ return ` it('${funcName} works correctly', () => {
27066
+ // TODO: Add specific test cases for ${funcName}
27067
+ expect(${funcName}).toBeDefined();
27068
+ });`;
27069
+ }).join("\n\n");
27070
+ const describeName = functions.length === 1 ? functions[0] : fileName;
27071
+ const testCode = `import { describe, it, expect } from '${testFramework}';
27072
+ import { ${functions.join(", ")} } from './${fileName}';
27073
+
27074
+ describe('${describeName}', () => {
27075
+ ${testCases}
27076
+ });
27077
+ `;
27078
+ return { testFilePath, testCode };
27079
+ }
27080
+ var init_nodejs = __esm({
27081
+ "src/testing/generators/nodejs.ts"() {
27082
+ "use strict";
27083
+ }
27084
+ });
27085
+
27086
+ // src/testing/generators/python.ts
27087
+ async function generatePythonTest(options) {
27088
+ const { filePath, code, testFramework } = options;
27089
+ const fileName = filePath.split("/").pop()?.replace(/\.py$/, "") || "module";
27090
+ const testFilePath = `tests/test_${fileName}.py`;
27091
+ const functions = extractPythonFunctions(code);
27092
+ const classes = extractPythonClasses(code);
27093
+ let testCode = "";
27094
+ if (testFramework === "pytest") {
27095
+ testCode = generatePytestCode(fileName, functions, classes);
27096
+ } else {
27097
+ testCode = generateUnittestCode(fileName, functions, classes);
27098
+ }
27099
+ return { testFilePath, testCode };
27100
+ }
27101
+ function extractPythonFunctions(code) {
27102
+ const functions = [];
27103
+ const functionRegex = /^(async\s+)?def\s+(\w+)\s*\((.*?)\)/gm;
27104
+ let match;
27105
+ while ((match = functionRegex.exec(code)) !== null) {
27106
+ const isAsync3 = !!match[1];
27107
+ const name = match[2];
27108
+ const paramsStr = match[3];
27109
+ const beforeDef = code.substring(0, match.index);
27110
+ const lastClassMatch = beforeDef.lastIndexOf("class ");
27111
+ const lastFunctionMatch = beforeDef.lastIndexOf("\ndef ");
27112
+ if (lastClassMatch > lastFunctionMatch) {
27113
+ continue;
27114
+ }
27115
+ const params = paramsStr.split(",").map((p) => p.trim().split(":")[0].trim()).filter((p) => p && p !== "self");
27116
+ functions.push({ name, params, isAsync: isAsync3 });
27117
+ }
27118
+ return functions;
27119
+ }
27120
+ function extractPythonClasses(code) {
27121
+ const classes = [];
27122
+ const classRegex = /class\s+(\w+).*?:/g;
27123
+ let match;
27124
+ while ((match = classRegex.exec(code)) !== null) {
27125
+ const className = match[1];
27126
+ const classStart = match.index;
27127
+ const methods = [];
27128
+ const methodRegex = /^\s+(async\s+)?def\s+(\w+)\s*\((.*?)\)/gm;
27129
+ methodRegex.lastIndex = classStart;
27130
+ let methodMatch;
27131
+ while ((methodMatch = methodRegex.exec(code)) !== null) {
27132
+ const nextClass = code.indexOf("\nclass ", classStart + 1);
27133
+ if (nextClass !== -1 && methodMatch.index > nextClass) {
27134
+ break;
27135
+ }
27136
+ const isAsync3 = !!methodMatch[1];
27137
+ const methodName = methodMatch[2];
27138
+ const paramsStr = methodMatch[3];
27139
+ const params = paramsStr.split(",").map((p) => p.trim().split(":")[0].trim()).filter((p) => p && p !== "self");
27140
+ methods.push({ name: methodName, params, isAsync: isAsync3 });
27141
+ }
27142
+ classes.push({ name: className, methods });
27143
+ }
27144
+ return classes;
27145
+ }
27146
+ function generatePytestCode(moduleName, functions, classes) {
27147
+ let code = `import pytest
27148
+ from src.${moduleName} import ${[...functions.map((f) => f.name), ...classes.map((c) => c.name)].join(", ")}
27149
+
27150
+ `;
27151
+ for (const func of functions) {
27152
+ code += generatePytestFunction(func);
27153
+ }
27154
+ for (const cls of classes) {
27155
+ code += `class Test${cls.name}:
27156
+ `;
27157
+ for (const method of cls.methods) {
27158
+ code += generatePytestMethod(cls.name, method);
27159
+ }
27160
+ code += "\n";
27161
+ }
27162
+ return code;
27163
+ }
27164
+ function generatePytestFunction(func) {
27165
+ const testName = `test_${func.name}`;
27166
+ const asyncPrefix = func.isAsync ? "@pytest.mark.asyncio\nasync " : "";
27167
+ let testBody = "";
27168
+ if (func.name === "add") {
27169
+ testBody = ` assert add(2, 3) == 5
27170
+ assert add(-1, 1) == 0
27171
+ assert add(0, 0) == 0`;
27172
+ } else {
27173
+ testBody = ` # TODO: Add test cases for ${func.name}
27174
+ assert ${func.name} is not None`;
27175
+ }
27176
+ return `${asyncPrefix}def ${testName}():
27177
+ ${testBody}
27178
+
27179
+ `;
27180
+ }
27181
+ function generatePytestMethod(className, method) {
27182
+ const testName = `test_${method.name}`;
27183
+ const asyncPrefix = method.isAsync ? " @pytest.mark.asyncio\n async " : " ";
27184
+ let testBody = "";
27185
+ if (method.name === "add") {
27186
+ testBody = ` instance = ${className}()
27187
+ assert instance.add(2, 3) == 5
27188
+ assert instance.add(-1, 1) == 0`;
27189
+ } else if (method.name === "subtract") {
27190
+ testBody = ` instance = ${className}()
27191
+ assert instance.subtract(5, 3) == 2
27192
+ assert instance.subtract(0, 0) == 0`;
27193
+ } else {
27194
+ testBody = ` instance = ${className}()
27195
+ # TODO: Add test cases for ${method.name}
27196
+ assert instance.${method.name} is not None`;
27197
+ }
27198
+ return `${asyncPrefix}def ${testName}(self):
27199
+ ${testBody}
27200
+
27201
+ `;
27202
+ }
27203
+ function generateUnittestCode(moduleName, functions, classes) {
27204
+ let code = `import unittest
27205
+ from src.${moduleName} import ${[...functions.map((f) => f.name), ...classes.map((c) => c.name)].join(", ")}
27206
+
27207
+ `;
27208
+ if (functions.length > 0) {
27209
+ code += `class TestFunctions(unittest.TestCase):
27210
+ `;
27211
+ for (const func of functions) {
27212
+ code += generateUnittestFunction(func);
27213
+ }
27214
+ code += "\n";
27215
+ }
27216
+ for (const cls of classes) {
27217
+ code += `class Test${cls.name}(unittest.TestCase):
27218
+ `;
27219
+ for (const method of cls.methods) {
27220
+ code += generateUnittestMethod(cls.name, method);
27221
+ }
27222
+ code += "\n";
27223
+ }
27224
+ code += `
27225
+ if __name__ == '__main__':
27226
+ unittest.main()
27227
+ `;
27228
+ return code;
27229
+ }
27230
+ function generateUnittestFunction(func) {
27231
+ const testName = `test_${func.name}`;
27232
+ let testBody = "";
27233
+ if (func.name === "add") {
27234
+ testBody = ` self.assertEqual(add(2, 3), 5)
27235
+ self.assertEqual(add(-1, 1), 0)
27236
+ self.assertEqual(add(0, 0), 0)`;
27237
+ } else {
27238
+ testBody = ` # TODO: Add test cases for ${func.name}
27239
+ self.assertIsNotNone(${func.name})`;
27240
+ }
27241
+ return ` def ${testName}(self):
27242
+ ${testBody}
27243
+
27244
+ `;
27245
+ }
27246
+ function generateUnittestMethod(className, method) {
27247
+ const testName = `test_${method.name}`;
27248
+ let testBody = "";
27249
+ if (method.name === "add") {
27250
+ testBody = ` instance = ${className}()
27251
+ self.assertEqual(instance.add(2, 3), 5)
27252
+ self.assertEqual(instance.add(-1, 1), 0)`;
27253
+ } else if (method.name === "subtract") {
27254
+ testBody = ` instance = ${className}()
27255
+ self.assertEqual(instance.subtract(5, 3), 2)
27256
+ self.assertEqual(instance.subtract(0, 0), 0)`;
27257
+ } else {
27258
+ testBody = ` instance = ${className}()
27259
+ # TODO: Add test cases for ${method.name}
27260
+ self.assertIsNotNone(instance.${method.name})`;
27261
+ }
27262
+ return ` def ${testName}(self):
27263
+ ${testBody}
27264
+
27265
+ `;
27266
+ }
27267
+ var init_python2 = __esm({
27268
+ "src/testing/generators/python.ts"() {
27269
+ "use strict";
27270
+ }
27271
+ });
27272
+
27273
+ // src/testing/generators/go.ts
27274
+ async function generateGoTest(options) {
27275
+ const { filePath, code, packageName } = options;
27276
+ const testFilePath = filePath.replace(/\.go$/, "_test.go");
27277
+ const functions = extractGoFunctions(code);
27278
+ const testCode = generateTestCode(packageName, functions);
27279
+ return { testFilePath, testCode };
27280
+ }
27281
+ function extractGoFunctions(code) {
27282
+ const functions = [];
27283
+ const funcRegex = /func\s+([A-Z]\w*)\s*\((.*?)\)\s*([\w.*[\]]*)?/g;
27284
+ let match;
27285
+ while ((match = funcRegex.exec(code)) !== null) {
27286
+ const name = match[1];
27287
+ const paramsStr = match[2];
27288
+ const returnType = (match[3] || "").trim();
27289
+ const params = parseGoParams(paramsStr);
27290
+ functions.push({ name, params, returnType });
27291
+ }
27292
+ return functions;
27293
+ }
27294
+ function parseGoParams(paramsStr) {
27295
+ if (!paramsStr.trim()) return [];
27296
+ const params = [];
27297
+ const parts = paramsStr.split(",").map((p) => p.trim());
27298
+ let lastType = "";
27299
+ const parsed = [];
27300
+ for (const part of parts) {
27301
+ const tokens = part.split(/\s+/);
27302
+ if (tokens.length >= 2) {
27303
+ const type = tokens[tokens.length - 1];
27304
+ const names = tokens.slice(0, -1);
27305
+ parsed.push({ names, type });
27306
+ lastType = type;
27307
+ } else {
27308
+ parsed.push({ names: [tokens[0]], type: "" });
27309
+ }
27310
+ }
27311
+ for (let i = parsed.length - 1; i >= 0; i--) {
27312
+ if (parsed[i].type) {
27313
+ lastType = parsed[i].type;
27314
+ } else {
27315
+ parsed[i].type = lastType;
27316
+ }
27317
+ }
27318
+ for (const p of parsed) {
27319
+ for (const name of p.names) {
27320
+ params.push({ name, type: p.type });
27321
+ }
27322
+ }
27323
+ return params;
27324
+ }
27325
+ function generateTestCode(packageName, functions) {
27326
+ let code = `package ${packageName}
27327
+
27328
+ import "testing"
27329
+
27330
+ `;
27331
+ for (const func of functions) {
27332
+ code += generateTableDrivenTest(func);
27333
+ }
27334
+ return code;
27335
+ }
27336
+ function generateTableDrivenTest(func) {
27337
+ const testName = `Test${func.name}`;
27338
+ const structFields = func.params.map((p) => ` ${p.name} ${p.type}`).join("\n");
27339
+ const expectedField = func.returnType ? ` expected ${func.returnType}` : "";
27340
+ const allFields = [structFields, expectedField].filter(Boolean).join("\n");
27341
+ const argsList = func.params.map((p) => `tt.${p.name}`).join(", ");
27342
+ const sampleArgs = func.params.map((p) => getZeroValue(p.type)).join(", ");
27343
+ const sampleExpected = func.returnType ? getZeroValue(func.returnType) : "";
27344
+ let testCase = func.params.map((p) => `${getZeroValue(p.type)}`).join(", ");
27345
+ if (func.returnType) {
27346
+ testCase += `, ${sampleExpected}`;
27347
+ }
27348
+ let code = `func ${testName}(t *testing.T) {
27349
+ `;
27350
+ code += ` tests := []struct {
27351
+ `;
27352
+ code += ` name string
27353
+ `;
27354
+ code += `${allFields}
27355
+ `;
27356
+ code += ` }{
27357
+ `;
27358
+ code += ` {
27359
+ `;
27360
+ code += ` name: "basic case",
27361
+ `;
27362
+ for (const p of func.params) {
27363
+ code += ` ${p.name}: ${getZeroValue(p.type)},
27364
+ `;
27365
+ }
27366
+ if (func.returnType) {
27367
+ code += ` expected: ${getZeroValue(func.returnType)},
27368
+ `;
27369
+ }
27370
+ code += ` },
27371
+ `;
27372
+ code += ` }
27373
+
27374
+ `;
27375
+ code += ` for _, tt := range tests {
27376
+ `;
27377
+ code += ` t.Run(tt.name, func(t *testing.T) {
27378
+ `;
27379
+ if (func.returnType) {
27380
+ code += ` got := ${func.name}(${argsList})
27381
+ `;
27382
+ code += ` if got != tt.expected {
27383
+ `;
27384
+ code += ` t.Errorf("${func.name}() = %v, want %v", got, tt.expected)
27385
+ `;
27386
+ code += ` }
27387
+ `;
27388
+ } else {
27389
+ code += ` ${func.name}(${argsList})
27390
+ `;
27391
+ }
27392
+ code += ` })
27393
+ `;
27394
+ code += ` }
27395
+ `;
27396
+ code += `}
27397
+
27398
+ `;
27399
+ return code;
27400
+ }
27401
+ function getZeroValue(goType) {
27402
+ switch (goType) {
27403
+ case "int":
27404
+ case "int8":
27405
+ case "int16":
27406
+ case "int32":
27407
+ case "int64":
27408
+ case "uint":
27409
+ case "uint8":
27410
+ case "uint16":
27411
+ case "uint32":
27412
+ case "uint64":
27413
+ case "float32":
27414
+ case "float64":
27415
+ return "0";
27416
+ case "string":
27417
+ return '""';
27418
+ case "bool":
27419
+ return "false";
27420
+ default:
27421
+ return "nil";
27422
+ }
27423
+ }
27424
+ var init_go2 = __esm({
27425
+ "src/testing/generators/go.ts"() {
27426
+ "use strict";
27427
+ }
27428
+ });
27429
+
27430
+ // src/testing/generators/rust.ts
27431
+ async function generateRustTest(options) {
27432
+ const { filePath, code } = options;
27433
+ const testFilePath = filePath;
27434
+ const functions = extractRustFunctions(code);
27435
+ const structs = extractRustStructs(code);
27436
+ const testCode = generateRustTestModule(functions, structs);
27437
+ return { testCode, testFilePath };
27438
+ }
27439
+ function extractRustFunctions(code) {
27440
+ const functions = [];
27441
+ const functionRegex = /(pub\s+)?fn\s+(\w+)\s*\((.*?)\)\s*(?:->\s*(.*?))?\s*{/g;
27442
+ let match;
27443
+ while ((match = functionRegex.exec(code)) !== null) {
27444
+ const isPublic = !!match[1];
27445
+ const name = match[2];
27446
+ const paramsStr = match[3];
27447
+ const returnType = match[4]?.trim() || "()";
27448
+ const beforeFn = code.substring(0, match.index);
27449
+ const lastImpl = beforeFn.lastIndexOf("impl ");
27450
+ const lastCloseBrace = beforeFn.lastIndexOf("}");
27451
+ if (lastImpl > lastCloseBrace) {
27452
+ continue;
27453
+ }
27454
+ const params = parseRustParams(paramsStr);
27455
+ functions.push({ name, params, returnType, isPublic });
27456
+ }
27457
+ return functions;
27458
+ }
27459
+ function extractRustStructs(code) {
27460
+ const structs = [];
27461
+ const structRegex = /struct\s+(\w+)/g;
27462
+ let match;
27463
+ while ((match = structRegex.exec(code)) !== null) {
27464
+ const structName = match[1];
27465
+ const implRegex = new RegExp(`impl\\s+${structName}\\s*{([^}]+)}`, "s");
27466
+ const implMatch = implRegex.exec(code);
27467
+ if (implMatch) {
27468
+ const implBody = implMatch[1];
27469
+ const methods = extractRustMethods(implBody);
27470
+ structs.push({ name: structName, methods });
27471
+ }
27472
+ }
27473
+ return structs;
27474
+ }
27475
+ function extractRustMethods(implBody) {
27476
+ const methods = [];
27477
+ const methodRegex = /(pub\s+)?fn\s+(\w+)\s*\((.*?)\)\s*(?:->\s*(.*?))?\s*{/g;
27478
+ let match;
27479
+ while ((match = methodRegex.exec(implBody)) !== null) {
27480
+ const isPublic = !!match[1];
27481
+ const name = match[2];
27482
+ const paramsStr = match[3];
27483
+ const returnType = match[4]?.trim() || "()";
27484
+ const params = parseRustParams(paramsStr);
27485
+ methods.push({ name, params, returnType, isPublic });
27486
+ }
27487
+ return methods;
27488
+ }
27489
+ function parseRustParams(paramsStr) {
27490
+ if (!paramsStr.trim()) return [];
27491
+ const params = [];
27492
+ const parts = paramsStr.split(",").map((p) => p.trim());
27493
+ for (const part of parts) {
27494
+ const colonIndex = part.indexOf(":");
27495
+ if (colonIndex !== -1) {
27496
+ const name = part.substring(0, colonIndex).trim();
27497
+ const type = part.substring(colonIndex + 1).trim();
27498
+ params.push({ name, type });
27499
+ }
27500
+ }
27501
+ return params;
27502
+ }
27503
+ function generateRustTestModule(functions, structs) {
27504
+ let code = `
27505
+ #[cfg(test)]
27506
+ mod tests {
27507
+ use super::*;
27508
+
27509
+ `;
27510
+ for (const func of functions) {
27511
+ if (func.isPublic) {
27512
+ code += generateRustTestFunction(func);
27513
+ }
27514
+ }
27515
+ for (const struct of structs) {
27516
+ for (const method of struct.methods) {
27517
+ if (method.isPublic) {
27518
+ code += generateRustTestMethod(struct.name, method);
27519
+ }
27520
+ }
27521
+ }
27522
+ code += `}
27523
+ `;
27524
+ return code;
27525
+ }
27526
+ function generateRustTestFunction(func) {
27527
+ const testName = `test_${func.name}`;
27528
+ let testBody = "";
27529
+ if (func.name === "add") {
27530
+ testBody = ` assert_eq!(add(2, 3), 5);
27531
+ assert_eq!(add(-1, 1), 0);
27532
+ assert_eq!(add(0, 0), 0);`;
27533
+ } else {
27534
+ testBody = ` // TODO: Add test implementation for ${func.name}`;
27535
+ }
27536
+ return ` #[test]
27537
+ fn ${testName}() {
27538
+ ${testBody}
27539
+ }
27540
+
27541
+ `;
27542
+ }
27543
+ function generateRustTestMethod(structName, method) {
27544
+ const testName = `test_${method.name}`;
27545
+ let testBody = "";
27546
+ if (method.name === "new") {
27547
+ testBody = ` let instance = ${structName}::new();
27548
+ // TODO: Add assertions`;
27549
+ } else if (method.name === "add") {
27550
+ testBody = ` let mut instance = ${structName}::new();
27551
+ instance.add(5);
27552
+ // TODO: Add assertions`;
27553
+ } else {
27554
+ testBody = ` // TODO: Add test implementation for ${method.name}`;
27555
+ }
27556
+ return ` #[test]
27557
+ fn ${testName}() {
27558
+ ${testBody}
27559
+ }
27560
+
27561
+ `;
27562
+ }
27563
+ var init_rust2 = __esm({
27564
+ "src/testing/generators/rust.ts"() {
27565
+ "use strict";
27566
+ }
27567
+ });
27568
+
27569
+ // src/testing/generators/contract.ts
27570
+ async function generateContractTest(options) {
27571
+ const { spec, apiDefinition, framework, consumer, provider } = options;
27572
+ let testCode = "";
27573
+ let testFilePath = "";
27574
+ if (framework === "pact" && spec) {
27575
+ testCode = generatePactTest(spec, consumer || "consumer", provider || "provider");
27576
+ testFilePath = `tests/contract/${consumer}-${provider}.pact.test.ts`;
27577
+ } else if (framework === "supertest" && apiDefinition) {
27578
+ testCode = generateSupertestContract(apiDefinition);
27579
+ testFilePath = `tests/contract/api.contract.test.ts`;
27580
+ } else if (framework === "msw" && spec) {
27581
+ testCode = generateMSWHandlers(spec);
27582
+ testFilePath = `tests/mocks/handlers.ts`;
27583
+ }
27584
+ return { testCode, testFilePath };
27585
+ }
27586
+ function generatePactTest(spec, consumer, provider) {
27587
+ const paths = spec.paths || {};
27588
+ const interactions = [];
27589
+ for (const [path26, methods] of Object.entries(paths)) {
27590
+ for (const [method, details] of Object.entries(methods)) {
27591
+ const interaction = generatePactInteraction(path26, method.toUpperCase(), details);
27592
+ interactions.push(interaction);
27593
+ }
27594
+ }
27595
+ return `import { Pact } from '@pact-foundation/pact';
27596
+ import { like, eachLike } from '@pact-foundation/pact/dsl/matchers';
27597
+
27598
+ describe('${consumer} <-> ${provider} Contract', () => {
27599
+ const provider = new Pact({
27600
+ consumer: '${consumer}',
27601
+ provider: '${provider}',
27602
+ port: 1234,
27603
+ log: './logs/pact.log',
27604
+ dir: './pacts',
27605
+ });
27606
+
27607
+ beforeAll(() => provider.setup());
27608
+ afterEach(() => provider.verify());
27609
+ afterAll(() => provider.finalize());
27610
+
27611
+ ${interactions.join("\n\n")}
27612
+ });
27613
+ `;
27614
+ }
27615
+ function generatePactInteraction(path26, method, details) {
27616
+ const response = details.responses?.["200"] || details.responses?.["201"];
27617
+ const responseSchema = response?.content?.["application/json"]?.schema;
27618
+ const responseBody = responseSchema ? generateMatcherFromSchema(responseSchema) : "{}";
27619
+ return ` it('${method} ${path26}', async () => {
27620
+ await provider.addInteraction({
27621
+ state: 'resource exists',
27622
+ uponReceiving: '${method} request to ${path26}',
27623
+ withRequest: {
27624
+ method: '${method}',
27625
+ path: '${path26}',
27626
+ },
27627
+ willRespondWith: {
27628
+ status: 200,
27629
+ headers: { 'Content-Type': 'application/json' },
27630
+ body: ${responseBody},
27631
+ },
27632
+ });
27633
+
27634
+ // Make actual request and verify
27635
+ const response = await fetch(\`http://localhost:1234${path26}\`);
27636
+ expect(response.status).toBe(200);
27637
+ });`;
27638
+ }
27639
+ function generateMatcherFromSchema(schema) {
27640
+ if (schema.type === "object") {
27641
+ const properties = schema.properties || {};
27642
+ const matchers = [];
27643
+ for (const [key, prop] of Object.entries(properties)) {
27644
+ if (prop.type === "string") {
27645
+ matchers.push(`${key}: like('example')`);
27646
+ } else if (prop.type === "number") {
27647
+ matchers.push(`${key}: like(123)`);
27648
+ } else if (prop.type === "boolean") {
27649
+ matchers.push(`${key}: like(true)`);
27650
+ } else if (prop.type === "array") {
27651
+ matchers.push(`${key}: eachLike({ id: like('1') })`);
27652
+ }
27653
+ }
27654
+ return `{ ${matchers.join(", ")} }`;
27655
+ }
27656
+ return "{}";
27657
+ }
27658
+ function generateSupertestContract(apiDefinition) {
27659
+ const { endpoint, method, requestBody, responseBody } = apiDefinition;
27660
+ const requestExample = generateExampleFromSchema(requestBody);
27661
+ const responseExample = generateExampleFromSchema(responseBody);
27662
+ return `import request from 'supertest';
27663
+ import app from '../src/app';
27664
+
27665
+ describe('API Contract Tests', () => {
27666
+ it('${method} ${endpoint} should match contract', async () => {
27667
+ const response = await request(app)
27668
+ .${method.toLowerCase()}('${endpoint}')
27669
+ .send(${JSON.stringify(requestExample, null, 2)})
27670
+ .expect(200)
27671
+ .expect('Content-Type', /json/);
27672
+
27673
+ // Verify response structure
27674
+ expect(response.body).toMatchObject(${JSON.stringify(responseExample, null, 2)});
27675
+ });
27676
+ });
27677
+ `;
27678
+ }
27679
+ function generateMSWHandlers(spec) {
27680
+ const paths = spec.paths || {};
27681
+ const handlers = [];
27682
+ for (const [path26, methods] of Object.entries(paths)) {
27683
+ for (const [method, details] of Object.entries(methods)) {
27684
+ const handler = generateMSWHandler(path26, method, details);
27685
+ handlers.push(handler);
27686
+ }
27687
+ }
27688
+ return `import { rest } from 'msw';
27689
+
27690
+ export const handlers = [
27691
+ ${handlers.join(",\n\n")}
27692
+ ];
27693
+ `;
27694
+ }
27695
+ function generateMSWHandler(path26, method, details) {
27696
+ const response = details.responses?.["200"] || details.responses?.["201"];
27697
+ const responseSchema = response?.content?.["application/json"]?.schema;
27698
+ const responseExample = responseSchema ? generateExampleFromSchema(responseSchema.properties || {}) : {};
27699
+ return ` rest.${method.toLowerCase()}('${path26}', (req, res, ctx) => {
27700
+ return res(
27701
+ ctx.status(200),
27702
+ ctx.json(${JSON.stringify(responseExample, null, 2)})
27703
+ );
27704
+ })`;
27705
+ }
27706
+ function generateExampleFromSchema(schema) {
27707
+ if (typeof schema === "string") {
27708
+ return schema === "string" ? "example" : schema === "number" ? 123 : schema === "boolean" ? true : [];
27709
+ }
27710
+ const example = {};
27711
+ for (const [key, type] of Object.entries(schema)) {
27712
+ if (type === "string") {
27713
+ example[key] = "example";
27714
+ } else if (type === "number") {
27715
+ example[key] = 123;
27716
+ } else if (type === "boolean") {
27717
+ example[key] = true;
27718
+ } else if (type === "array") {
27719
+ example[key] = [];
27720
+ }
27721
+ }
27722
+ return example;
27723
+ }
27724
+ var init_contract = __esm({
27725
+ "src/testing/generators/contract.ts"() {
27726
+ "use strict";
27727
+ }
27728
+ });
27729
+
27730
+ // src/testing/analyzers/coverage.ts
27731
+ async function analyzeCoverage(options) {
27732
+ const { projectRoot, coverageData } = options;
27733
+ let coverage = coverageData;
27734
+ if (!coverage) {
27735
+ try {
27736
+ (0, import_child_process33.execSync)("pnpm test --coverage --reporter=json", {
27737
+ cwd: projectRoot,
27738
+ stdio: "pipe"
27739
+ });
27740
+ const coveragePath = import_path111.default.join(projectRoot, "coverage", "coverage-summary.json");
27741
+ const coverageContent = await import_promises20.default.readFile(coveragePath, "utf-8");
27742
+ coverage = JSON.parse(coverageContent);
27743
+ } catch (error2) {
27744
+ throw new Error(`Failed to generate coverage: ${error2}`);
27745
+ }
27746
+ }
27747
+ const total = coverage.total;
27748
+ return {
27749
+ totalCoverage: total.lines.pct,
27750
+ lineCoverage: total.lines.pct,
27751
+ functionCoverage: total.functions.pct,
27752
+ branchCoverage: total.branches.pct,
27753
+ statementCoverage: total.statements.pct
27754
+ };
27755
+ }
27756
+ var import_promises20, import_path111, import_child_process33;
27757
+ var init_coverage = __esm({
27758
+ "src/testing/analyzers/coverage.ts"() {
27759
+ "use strict";
27760
+ import_promises20 = __toESM(require("fs/promises"), 1);
27761
+ import_path111 = __toESM(require("path"), 1);
27762
+ import_child_process33 = require("child_process");
27763
+ }
27764
+ });
27765
+
27766
+ // src/testing/analyzers/complexity.ts
27767
+ async function analyzeComplexity(options) {
27768
+ const { code } = options;
27769
+ const metrics = calculateMetrics(code);
27770
+ const reasons = [];
27771
+ let isComplex = false;
27772
+ if (metrics.lines >= 50) {
27773
+ reasons.push("Function exceeds 50 lines");
27774
+ isComplex = true;
27775
+ }
27776
+ if (metrics.cyclomaticComplexity >= 10) {
27777
+ reasons.push("High cyclomatic complexity");
27778
+ isComplex = true;
27779
+ }
27780
+ if (metrics.nestingLevel >= 3) {
27781
+ reasons.push("Deep nesting level");
27782
+ isComplex = true;
27783
+ }
27784
+ if (metrics.externalDependencies > 0) {
27785
+ reasons.push("External API calls");
27786
+ isComplex = true;
27787
+ }
27788
+ if (code.includes("stripe") || code.includes("paypal") || code.includes("payment")) {
27789
+ reasons.push("Payment processing logic");
27790
+ isComplex = true;
27791
+ }
27792
+ if (code.includes("auth") || code.includes("jwt") || code.includes("session")) {
27793
+ reasons.push("Authentication logic");
27794
+ isComplex = true;
27795
+ }
27796
+ if (code.includes("db.transaction") || code.includes("BEGIN") || code.includes("COMMIT")) {
27797
+ reasons.push("Database transactions");
27798
+ isComplex = true;
27799
+ }
27800
+ if (code.includes("async") && code.includes("await")) {
27801
+ const awaitCount = (code.match(/await/g) || []).length;
27802
+ if (awaitCount > 3) {
27803
+ reasons.push("Multiple async operations");
27804
+ isComplex = true;
27805
+ }
27806
+ }
27807
+ return {
27808
+ complexity: isComplex ? "complex" : "simple",
27809
+ metrics,
27810
+ reasons
27811
+ };
27812
+ }
27813
+ function calculateMetrics(code) {
27814
+ const lines = code.split("\n").filter((line) => line.trim() !== "").length;
27815
+ const cyclomaticComplexity = calculateCyclomaticComplexity(code);
27816
+ const nestingLevel = calculateNestingLevel(code);
27817
+ const externalDependencies = countExternalDependencies(code);
27818
+ return {
27819
+ lines,
27820
+ cyclomaticComplexity,
27821
+ nestingLevel,
27822
+ externalDependencies
27823
+ };
27824
+ }
27825
+ function calculateCyclomaticComplexity(code) {
27826
+ let complexity = 1;
27827
+ const decisionPoints = [
27828
+ /\bif\b/g,
27829
+ /\belse\s+if\b/g,
27830
+ /\bfor\b/g,
27831
+ /\bwhile\b/g,
27832
+ /\bcase\b/g,
27833
+ /\bcatch\b/g,
27834
+ /\b\?\s*.*\s*:/g,
27835
+ // Ternary operator
27836
+ /\b&&\b/g,
27837
+ /\b\|\|\b/g
27838
+ ];
27839
+ for (const pattern of decisionPoints) {
27840
+ const matches = code.match(pattern);
27841
+ if (matches) {
27842
+ complexity += matches.length;
27843
+ }
27844
+ }
27845
+ return complexity;
27846
+ }
27847
+ function calculateNestingLevel(code) {
27848
+ let maxNesting = 0;
27849
+ let currentNesting = 0;
27850
+ for (const char of code) {
27851
+ if (char === "{") {
27852
+ currentNesting++;
27853
+ maxNesting = Math.max(maxNesting, currentNesting);
27854
+ } else if (char === "}") {
27855
+ currentNesting--;
27856
+ }
27857
+ }
27858
+ return maxNesting;
27859
+ }
27860
+ function countExternalDependencies(code) {
27861
+ let count = 0;
27862
+ if (code.includes("fetch(") || code.includes("axios.") || code.includes("http.")) {
27863
+ count++;
27864
+ }
27865
+ const externalServices = ["stripe", "aws", "firebase", "sendgrid", "twilio"];
27866
+ for (const service of externalServices) {
27867
+ if (code.includes(service)) {
27868
+ count++;
27869
+ }
27870
+ }
27871
+ return count;
27872
+ }
27873
+ var init_complexity = __esm({
27874
+ "src/testing/analyzers/complexity.ts"() {
27875
+ "use strict";
27876
+ }
27877
+ });
27878
+
27879
+ // src/testing/generators/e2e.ts
27880
+ var e2e_exports = {};
27881
+ __export(e2e_exports, {
27882
+ generateFromUserFlow: () => generateFromUserFlow,
27883
+ generatePlaywrightTest: () => generatePlaywrightTest
27884
+ });
27885
+ function renderTemplate(template, vars) {
27886
+ return template.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] || "");
27887
+ }
27888
+ async function generatePlaywrightTest(options) {
27889
+ const { steps, testName, testSuite = "E2E Tests" } = options;
27890
+ const testSteps = steps.map((step) => {
27891
+ const template = STEP_TEMPLATES[step.action];
27892
+ return renderTemplate(template, {
27893
+ target: step.target,
27894
+ value: step.value || "",
27895
+ assertion: step.assertion || ""
27896
+ });
27897
+ }).join("\n ");
27898
+ return renderTemplate(PLAYWRIGHT_TEST_TEMPLATE, {
27899
+ testSuite,
27900
+ testName,
27901
+ testSteps
27902
+ });
27903
+ }
27904
+ async function generateFromUserFlow(options) {
27905
+ const { flowDescription, baseUrl, testName } = options;
27906
+ const steps = [];
27907
+ const lowerFlow = flowDescription.toLowerCase();
27908
+ const actions = flowDescription.split(/,\s*/).map((s) => s.trim().toLowerCase());
27909
+ for (const action of actions) {
27910
+ if (action.includes("logs in") || action.includes("login")) {
27911
+ steps.push({ action: "goto", target: `${baseUrl}/login` });
27912
+ } else if (action.includes("navigates to") || action.includes("dashboard")) {
27913
+ steps.push({ action: "goto", target: `${baseUrl}/dashboard` });
27914
+ } else if (action.includes("clicks on") || action.includes("settings")) {
27915
+ steps.push({ action: "click", target: 'a[href="/settings"]' });
27916
+ }
27917
+ }
27918
+ const testCode = await generatePlaywrightTest({ steps, testName });
27919
+ return {
27920
+ testCode,
27921
+ steps
27922
+ };
27923
+ }
27924
+ var PLAYWRIGHT_TEST_TEMPLATE, STEP_TEMPLATES;
27925
+ var init_e2e = __esm({
27926
+ "src/testing/generators/e2e.ts"() {
27927
+ "use strict";
27928
+ PLAYWRIGHT_TEST_TEMPLATE = `import { test, expect } from '@playwright/test';
27929
+
27930
+ test.describe('{{testSuite}}', () => {
27931
+ test('{{testName}}', async ({ page }) => {
27932
+ {{testSteps}}
27933
+ });
27934
+ });
27935
+ `;
27936
+ STEP_TEMPLATES = {
27937
+ goto: "await page.goto('{{target}}');",
27938
+ click: "await page.click('{{target}}');",
27939
+ fill: "await page.fill('{{target}}', '{{value}}');",
27940
+ expect: "await expect(page.locator('{{target}}')).{{assertion}}();",
27941
+ waitFor: "await page.waitForSelector('{{target}}');",
27942
+ screenshot: "await page.screenshot({ path: '{{target}}' });"
27943
+ };
27944
+ }
27945
+ });
27946
+
27947
+ // src/testing/integrations/giskard/behavioral-tests.ts
27948
+ var behavioral_tests_exports = {};
27949
+ __export(behavioral_tests_exports, {
27950
+ generatePerturbationTests: () => generatePerturbationTests,
27951
+ generateRobustnessTests: () => generateRobustnessTests
27952
+ });
27953
+ async function generatePerturbationTests(options) {
27954
+ const { testCases, perturbations } = options;
27955
+ const tests = [];
27956
+ for (const testCase of testCases) {
27957
+ for (const perturbationType of perturbations) {
27958
+ const perturbed = applyPerturbation(testCase.input, perturbationType);
27959
+ tests.push({
27960
+ original: testCase.input,
27961
+ perturbed,
27962
+ perturbationType,
27963
+ expectedBehavior: `should still classify as ${testCase.expectedOutput}`,
27964
+ expectedOutput: testCase.expectedOutput
27965
+ });
27966
+ }
27967
+ }
27968
+ return {
27969
+ tests,
27970
+ totalTests: tests.length
27971
+ };
27972
+ }
27973
+ function applyPerturbation(text, type) {
27974
+ switch (type) {
27975
+ case "typo":
27976
+ const pos = Math.floor(Math.random() * (text.length - 1));
27977
+ return text.slice(0, pos) + text[pos + 1] + text[pos] + text.slice(pos + 2);
27978
+ case "negation":
27979
+ return `not ${text}`;
27980
+ case "synonym":
27981
+ return text.replace(/hello/gi, "hi").replace(/goodbye/gi, "bye");
27982
+ default:
27983
+ return text;
27984
+ }
27985
+ }
27986
+ async function generateRobustnessTests(options) {
27987
+ const { modelEndpoint, testInputs, robustnessChecks } = options;
27988
+ const checks = [];
27989
+ for (const checkType of robustnessChecks) {
27990
+ const testCases = testInputs.map((input) => ({
27991
+ input: applyRobustnessTransform(input, checkType),
27992
+ expected: input
27993
+ // Expected to behave same as original
27994
+ }));
27995
+ checks.push({
27996
+ type: checkType,
27997
+ testCases
27998
+ });
27999
+ }
28000
+ return {
28001
+ checks,
28002
+ totalChecks: checks.length
28003
+ };
28004
+ }
28005
+ function applyRobustnessTransform(text, type) {
28006
+ switch (type) {
28007
+ case "case-sensitivity":
28008
+ return text.toUpperCase();
28009
+ case "whitespace":
28010
+ return ` ${text} `;
28011
+ case "special-chars":
28012
+ return `${text}!!!`;
28013
+ default:
28014
+ return text;
28015
+ }
28016
+ }
28017
+ var init_behavioral_tests = __esm({
28018
+ "src/testing/integrations/giskard/behavioral-tests.ts"() {
28019
+ "use strict";
28020
+ }
28021
+ });
28022
+
28023
+ // src/testing/integrations/cicd.ts
28024
+ var cicd_exports = {};
28025
+ __export(cicd_exports, {
28026
+ generateGitHubActionsWorkflow: () => generateGitHubActionsWorkflow
28027
+ });
28028
+ async function generateGitHubActionsWorkflow(config2) {
28029
+ const {
28030
+ language,
28031
+ languages,
28032
+ testCommand: testCommand2,
28033
+ testCommands,
28034
+ nodeVersion = "20",
28035
+ pythonVersion = "3.11",
28036
+ goVersion = "1.21",
28037
+ rustVersion = "stable",
28038
+ coverage = false,
28039
+ coverageProvider = "codecov",
28040
+ artifacts = false,
28041
+ artifactPath = "test-results/",
28042
+ matrix
28043
+ } = config2;
28044
+ const runsOn = matrix?.os ? "${{ matrix.os }}" : "ubuntu-latest";
28045
+ let workflow = `name: Test
28046
+
28047
+ on:
28048
+ push:
28049
+ branches: [main, dev]
28050
+ pull_request:
28051
+ branches: [main, dev]
28052
+
28053
+ jobs:
28054
+ test:
28055
+ runs-on: ${runsOn}
28056
+ `;
28057
+ if (matrix) {
28058
+ workflow += ` strategy:
28059
+ matrix:
28060
+ `;
28061
+ if (matrix.nodeVersion) {
28062
+ workflow += ` node-version: [${matrix.nodeVersion.join(", ")}]
28063
+ `;
28064
+ }
28065
+ if (matrix.pythonVersion) {
28066
+ workflow += ` python-version: [${matrix.pythonVersion.join(", ")}]
28067
+ `;
28068
+ }
28069
+ if (matrix.goVersion) {
28070
+ workflow += ` go-version: [${matrix.goVersion.join(", ")}]
28071
+ `;
28072
+ }
28073
+ if (matrix.os) {
28074
+ workflow += ` os: [${matrix.os.join(", ")}]
28075
+ `;
28076
+ }
28077
+ if (matrix.language) {
28078
+ workflow += ` language: [${matrix.language.join(", ")}]
28079
+ `;
28080
+ }
28081
+ }
28082
+ workflow += ` steps:
28083
+ - uses: actions/checkout@v4
28084
+
28085
+ `;
28086
+ if (languages && matrix?.language) {
28087
+ const matrixLang = "${{ matrix.language }}";
28088
+ workflow += ` - name: Setup Node.js
28089
+ if: matrix.language == 'nodejs'
28090
+ uses: actions/setup-node@v4
28091
+ with:
28092
+ node-version: ${nodeVersion}
28093
+ cache: 'pnpm'
28094
+
28095
+ - name: Setup Python
28096
+ if: matrix.language == 'python'
28097
+ uses: actions/setup-python@v5
28098
+ with:
28099
+ python-version: ${pythonVersion}
28100
+
28101
+ - name: Setup Go
28102
+ if: matrix.language == 'go'
28103
+ uses: actions/setup-go@v5
28104
+ with:
28105
+ go-version: ${goVersion}
28106
+
28107
+ - name: Install Node.js dependencies
28108
+ if: matrix.language == 'nodejs'
28109
+ run: pnpm install
28110
+
28111
+ - name: Install Python dependencies
28112
+ if: matrix.language == 'python'
28113
+ run: pip install -r requirements.txt
28114
+
28115
+ - name: Run tests
28116
+ run: |
28117
+ if [ "${matrixLang}" == "nodejs" ]; then
28118
+ ${testCommands?.nodejs || "pnpm test"}
28119
+ elif [ "${matrixLang}" == "python" ]; then
28120
+ ${testCommands?.python || "pytest"}
28121
+ elif [ "${matrixLang}" == "go" ]; then
28122
+ ${testCommands?.go || "go test ./..."}
28123
+ fi
28124
+ `;
28125
+ } else {
28126
+ if (language === "nodejs" || !language && testCommand2?.includes("pnpm")) {
28127
+ const nodeVer = matrix?.nodeVersion ? "${{ matrix.node-version }}" : nodeVersion;
28128
+ workflow += ` - name: Setup Node.js
28129
+ uses: actions/setup-node@v4
28130
+ with:
28131
+ node-version: ${nodeVer}
28132
+ cache: 'pnpm'
28133
+
28134
+ - name: Install dependencies
28135
+ run: pnpm install
28136
+
28137
+ - name: Run tests
28138
+ run: ${testCommand2 || "pnpm test"}
28139
+ `;
28140
+ } else if (language === "python") {
28141
+ const pyVer = matrix?.pythonVersion ? "${{ matrix.python-version }}" : pythonVersion;
28142
+ workflow += ` - name: Setup Python
28143
+ uses: actions/setup-python@v5
28144
+ with:
28145
+ python-version: ${pyVer}
28146
+
28147
+ - name: Install dependencies
28148
+ run: pip install -r requirements.txt
28149
+
28150
+ - name: Run tests
28151
+ run: ${testCommand2 || "pytest"}
28152
+ `;
28153
+ } else if (language === "go") {
28154
+ const goVer = matrix?.goVersion ? "${{ matrix.go-version }}" : goVersion;
28155
+ workflow += ` - name: Setup Go
28156
+ uses: actions/setup-go@v5
28157
+ with:
28158
+ go-version: ${goVer}
28159
+
28160
+ - name: Run tests
28161
+ run: ${testCommand2 || "go test ./..."}
28162
+ `;
28163
+ } else if (language === "rust") {
28164
+ workflow += ` - name: Setup Rust
28165
+ uses: actions-rust-lang/setup-rust-toolchain@v1
28166
+ with:
28167
+ toolchain: ${rustVersion}
28168
+
28169
+ - name: Run tests
28170
+ run: ${testCommand2 || "cargo test"}
28171
+ `;
28172
+ }
28173
+ }
28174
+ if (coverage) {
28175
+ const token = "${{ secrets.CODECOV_TOKEN }}";
28176
+ workflow += `
28177
+ - name: Upload coverage
28178
+ uses: ${coverageProvider}/codecov-action@v4
28179
+ with:
28180
+ token: ${token}
28181
+ `;
28182
+ }
28183
+ if (artifacts) {
28184
+ workflow += `
28185
+ - name: Upload test results
28186
+ if: always()
28187
+ uses: actions/upload-artifact@v4
28188
+ with:
28189
+ name: test-results
28190
+ path: ${artifactPath}
28191
+ `;
28192
+ }
28193
+ return workflow;
28194
+ }
28195
+ var init_cicd = __esm({
28196
+ "src/testing/integrations/cicd.ts"() {
28197
+ "use strict";
28198
+ }
28199
+ });
28200
+
28201
+ // src/testing/analyzers/quality-scorer.ts
28202
+ var quality_scorer_exports = {};
28203
+ __export(quality_scorer_exports, {
28204
+ scoreTestQuality: () => scoreTestQuality
28205
+ });
28206
+ async function scoreTestQuality(options) {
28207
+ const { testCode } = options;
28208
+ const assertionCount = (testCode.match(/expect\(/g) || []).length;
28209
+ const hasAssertions = assertionCount > 0;
28210
+ const hasEdgeCases = testCode.includes("null") || testCode.includes("undefined") || testCode.includes("0") || testCode.includes("empty") || testCode.includes("-1") || testCode.includes("''") || testCode.includes('""');
28211
+ const specificAssertionPatterns = [
28212
+ /\.toBe\(/g,
28213
+ /\.toEqual\(/g,
28214
+ /\.toStrictEqual\(/g,
28215
+ /\.toMatch\(/g,
28216
+ /\.toContain\(/g,
28217
+ /\.toHaveLength\(/g
28218
+ ];
28219
+ const specificAssertionCount = specificAssertionPatterns.reduce(
28220
+ (count, pattern) => count + (testCode.match(pattern) || []).length,
28221
+ 0
28222
+ );
28223
+ const hasSpecificAssertions = specificAssertionCount > 0;
28224
+ const hasSharedState = testCode.includes("let ") && !testCode.match(/test\([^)]*\)\s*=>\s*\{[^}]*let /s) || testCode.includes("var ") && !testCode.match(/test\([^)]*\)\s*=>\s*\{[^}]*var /s);
28225
+ const testNames = testCode.match(/test\(['"]([^'"]+)['"]/g) || [];
28226
+ const hasDescriptiveNames = testNames.every((name) => {
28227
+ const testName = name.match(/test\(['"]([^'"]+)['"]/)?.[1] || "";
28228
+ return testName.length > 15 && (testName.includes("should") || testName.includes("when"));
28229
+ });
28230
+ const hasMocks = testCode.includes("mock") || testCode.includes("spy") || testCode.includes("stub");
28231
+ const hasSetup = testCode.includes("beforeEach") || testCode.includes("beforeAll");
28232
+ const hasTeardown = testCode.includes("afterEach") || testCode.includes("afterAll");
28233
+ const metrics = {
28234
+ assertionCount,
28235
+ hasEdgeCases,
28236
+ hasAssertions,
28237
+ hasSpecificAssertions,
28238
+ hasSharedState,
28239
+ hasDescriptiveNames,
28240
+ hasMocks,
28241
+ hasSetup,
28242
+ hasTeardown
28243
+ };
28244
+ let completenessScore = 0;
28245
+ if (hasAssertions) completenessScore += 40;
28246
+ completenessScore += Math.min(assertionCount * 10, 30);
28247
+ if (hasEdgeCases) completenessScore += 15;
28248
+ if (hasMocks) completenessScore += 10;
28249
+ if (hasSetup || hasTeardown) completenessScore += 5;
28250
+ let assertionQuality = 0;
28251
+ if (hasAssertions) {
28252
+ assertionQuality += 50;
28253
+ if (hasSpecificAssertions) {
28254
+ const specificRatio = specificAssertionCount / assertionCount;
28255
+ assertionQuality += specificRatio * 50;
28256
+ }
28257
+ }
28258
+ let independenceScore = 100;
28259
+ if (hasSharedState) independenceScore -= 40;
28260
+ if (!hasSetup && testCode.includes("const ") && testCode.split("const ").length > 3) {
28261
+ independenceScore -= 10;
28262
+ }
28263
+ let namingScore = 0;
28264
+ if (testNames.length > 0) {
28265
+ namingScore = hasDescriptiveNames ? 90 : 50;
28266
+ if (testNames.some((name) => name.includes("should"))) namingScore += 10;
28267
+ }
28268
+ const overallScore = Math.round(
28269
+ completenessScore * 0.35 + assertionQuality * 0.25 + independenceScore * 0.2 + namingScore * 0.2
28270
+ );
28271
+ const recommendations = [];
28272
+ if (!hasAssertions) {
28273
+ recommendations.push("Add assertions to verify behavior");
28274
+ }
28275
+ if (assertionCount < 2) {
28276
+ recommendations.push("Add more test cases to cover edge cases");
28277
+ }
28278
+ if (!hasEdgeCases) {
28279
+ recommendations.push("Test edge cases like null, undefined, empty values, and boundary conditions");
28280
+ }
28281
+ if (!hasSpecificAssertions) {
28282
+ recommendations.push("Use specific assertions (toBe, toEqual) instead of generic truthy checks");
28283
+ }
28284
+ if (hasSharedState) {
28285
+ recommendations.push("Avoid shared state between tests - use beforeEach for setup");
28286
+ }
28287
+ if (!hasDescriptiveNames) {
28288
+ recommendations.push("Use descriptive test names that explain what is being tested");
28289
+ }
28290
+ if (assertionQuality < 60) {
28291
+ recommendations.push("Improve assertion quality with more specific matchers");
28292
+ }
28293
+ return {
28294
+ completenessScore: Math.min(completenessScore, 100),
28295
+ assertionQuality: Math.min(assertionQuality, 100),
28296
+ independenceScore: Math.min(independenceScore, 100),
28297
+ namingScore: Math.min(namingScore, 100),
28298
+ overallScore: Math.min(overallScore, 100),
28299
+ assertionCount,
28300
+ hasEdgeCases,
28301
+ hasAssertions,
28302
+ hasSpecificAssertions,
28303
+ hasSharedState,
28304
+ hasDescriptiveNames,
28305
+ metrics,
28306
+ recommendations
28307
+ };
28308
+ }
28309
+ var init_quality_scorer = __esm({
28310
+ "src/testing/analyzers/quality-scorer.ts"() {
28311
+ "use strict";
28312
+ }
28313
+ });
28314
+
28315
+ // src/testing/cli/commands.ts
28316
+ var commands_exports = {};
28317
+ __export(commands_exports, {
28318
+ testAnalyzeCoverageCommand: () => testAnalyzeCoverageCommand,
28319
+ testCICDCommand: () => testCICDCommand,
28320
+ testComplexityCommand: () => testComplexityCommand,
28321
+ testContractCommand: () => testContractCommand,
28322
+ testDetectStackCommand: () => testDetectStackCommand,
28323
+ testE2ECommand: () => testE2ECommand,
28324
+ testGenCommand: () => testGenCommand,
28325
+ testGiskardCommand: () => testGiskardCommand,
28326
+ testQualityCommand: () => testQualityCommand
28327
+ });
28328
+ function detectLanguage(filePath) {
28329
+ if (filePath.match(/\.(tsx|jsx)$/)) return "react";
28330
+ if (filePath.match(/\.ts$/)) return "typescript";
28331
+ if (filePath.match(/\.py$/)) return "python";
28332
+ if (filePath.match(/\.go$/)) return "go";
28333
+ if (filePath.match(/\.rs$/)) return "rust";
28334
+ return null;
28335
+ }
28336
+ async function testGenCommand(options) {
28337
+ try {
28338
+ const { filePath, output } = options;
28339
+ const language = options.language || detectLanguage(filePath);
28340
+ if (!language) {
28341
+ return {
28342
+ success: false,
28343
+ error: "Unsupported file type"
28344
+ };
28345
+ }
28346
+ const code = await import_promises21.default.readFile(filePath, "utf-8");
28347
+ const projectRoot = process.cwd();
28348
+ const stack = await detectTechStack(projectRoot);
28349
+ let result;
28350
+ switch (language) {
28351
+ case "react": {
28352
+ const detectedFramework = stack.frontend?.testFramework;
28353
+ const testFramework = detectedFramework === "jest" ? "jest" : "vitest";
28354
+ result = await generateReactTest({ filePath, code, testFramework });
28355
+ break;
28356
+ }
28357
+ case "typescript": {
28358
+ const detectedFramework = stack.backend?.testFramework;
28359
+ const testFramework = detectedFramework === "jest" ? "jest" : "vitest";
28360
+ result = await generateNodeJsTest({ filePath, code, testFramework });
28361
+ break;
28362
+ }
28363
+ case "python": {
28364
+ const testFramework = stack.backend?.testFramework === "unittest" ? "unittest" : "pytest";
28365
+ result = await generatePythonTest({ filePath, code, testFramework });
28366
+ break;
28367
+ }
28368
+ case "go": {
28369
+ const packageName = import_path112.default.basename(import_path112.default.dirname(filePath));
28370
+ result = await generateGoTest({ filePath, code, packageName });
28371
+ break;
28372
+ }
28373
+ case "rust": {
28374
+ result = await generateRustTest({ filePath, code });
28375
+ break;
28376
+ }
28377
+ default:
28378
+ return {
28379
+ success: false,
28380
+ error: "Unsupported file type"
28381
+ };
28382
+ }
28383
+ const testFilePath = output || result.testFilePath;
28384
+ await import_promises21.default.writeFile(testFilePath, result.testCode, "utf-8");
28385
+ return {
28386
+ success: true,
28387
+ testFilePath
28388
+ };
28389
+ } catch (error2) {
28390
+ return {
28391
+ success: false,
28392
+ error: error2 instanceof Error ? error2.message : "Unknown error"
28393
+ };
28394
+ }
28395
+ }
28396
+ async function testDetectStackCommand(options) {
28397
+ const stack = await detectTechStack(options.projectRoot);
28398
+ return { stack };
28399
+ }
28400
+ async function testAnalyzeCoverageCommand(options) {
28401
+ return analyzeCoverage({
28402
+ projectRoot: options.projectRoot,
28403
+ coverageData: options.coverageData
28404
+ });
28405
+ }
28406
+ async function testContractCommand(options) {
28407
+ const { spec, specPath, framework, consumer, provider } = options;
28408
+ let specData = spec;
28409
+ if (!specData) {
28410
+ const content = await import_promises21.default.readFile(specPath, "utf-8");
28411
+ specData = JSON.parse(content);
28412
+ }
28413
+ const result = await generateContractTest({
28414
+ spec: specData,
28415
+ framework,
28416
+ consumer,
28417
+ provider
28418
+ });
28419
+ return {
28420
+ success: true,
28421
+ testCode: result.testCode,
28422
+ testFilePath: result.testFilePath
28423
+ };
28424
+ }
28425
+ async function testComplexityCommand(options) {
28426
+ const code = await import_promises21.default.readFile(options.filePath, "utf-8");
28427
+ return analyzeComplexity({ code, filePath: options.filePath });
28428
+ }
28429
+ async function testE2ECommand(options) {
28430
+ try {
28431
+ const { generateFromUserFlow: generateFromUserFlow2 } = await Promise.resolve().then(() => (init_e2e(), e2e_exports));
28432
+ const result = await generateFromUserFlow2({
28433
+ flowDescription: options.flowDescription,
28434
+ baseUrl: options.baseUrl || "http://localhost:3000",
28435
+ testName: options.testName || "User flow test"
28436
+ });
28437
+ const testFilePath = options.output || "./tests/e2e/user-flow.spec.ts";
28438
+ await import_promises21.default.writeFile(testFilePath, result.testCode, "utf-8");
28439
+ return {
28440
+ success: true,
28441
+ testFilePath
28442
+ };
28443
+ } catch (error2) {
28444
+ return {
28445
+ success: false,
28446
+ error: error2 instanceof Error ? error2.message : "Unknown error"
28447
+ };
28448
+ }
28449
+ }
28450
+ async function testGiskardCommand(options) {
28451
+ try {
28452
+ const { generatePerturbationTests: generatePerturbationTests2 } = await Promise.resolve().then(() => (init_behavioral_tests(), behavioral_tests_exports));
28453
+ const code = await import_promises21.default.readFile(options.filePath, "utf-8");
28454
+ const result = await generatePerturbationTests2({
28455
+ testCases: [
28456
+ { input: "sample input", expectedOutput: "expected" }
28457
+ ],
28458
+ perturbations: ["typo", "negation", "synonym"]
28459
+ });
28460
+ const testFilePath = options.output || "./tests/behavioral/perturbation.test.ts";
28461
+ const testCode = `// Generated Giskard behavioral tests
28462
+ import { describe, it, expect } from 'vitest';
28463
+
28464
+ describe('Behavioral Tests', () => {
28465
+ ${result.tests.map((test) => `
28466
+ it('${test.expectedBehavior}', async () => {
28467
+ // Original: ${test.original}
28468
+ // Perturbed (${test.perturbationType}): ${test.perturbed}
28469
+ // TODO: Add test implementation
28470
+ });
28471
+ `).join("")}
28472
+ });
28473
+ `;
28474
+ await import_promises21.default.writeFile(testFilePath, testCode, "utf-8");
28475
+ return {
28476
+ success: true,
28477
+ testFilePath
28478
+ };
28479
+ } catch (error2) {
28480
+ return {
28481
+ success: false,
28482
+ error: error2 instanceof Error ? error2.message : "Unknown error"
28483
+ };
28484
+ }
28485
+ }
28486
+ async function testCICDCommand(options) {
28487
+ try {
28488
+ const { generateGitHubActionsWorkflow: generateGitHubActionsWorkflow2 } = await Promise.resolve().then(() => (init_cicd(), cicd_exports));
28489
+ const workflow = await generateGitHubActionsWorkflow2({
28490
+ language: options.language || "nodejs",
28491
+ coverage: true,
28492
+ artifacts: true
28493
+ });
28494
+ const workflowPath = options.output || "./.github/workflows/test.yml";
28495
+ const dir = import_path112.default.dirname(workflowPath);
28496
+ await import_promises21.default.mkdir(dir, { recursive: true });
28497
+ await import_promises21.default.writeFile(workflowPath, workflow, "utf-8");
28498
+ return {
28499
+ success: true,
28500
+ workflowPath
28501
+ };
28502
+ } catch (error2) {
28503
+ return {
28504
+ success: false,
28505
+ error: error2 instanceof Error ? error2.message : "Unknown error"
28506
+ };
28507
+ }
28508
+ }
28509
+ async function testQualityCommand(options) {
28510
+ try {
28511
+ const { scoreTestQuality: scoreTestQuality2 } = await Promise.resolve().then(() => (init_quality_scorer(), quality_scorer_exports));
28512
+ const testCode = await import_promises21.default.readFile(options.testFilePath, "utf-8");
28513
+ const score = await scoreTestQuality2({
28514
+ testCode,
28515
+ testType: options.testType || "unit"
28516
+ });
28517
+ return {
28518
+ success: true,
28519
+ score
28520
+ };
28521
+ } catch (error2) {
28522
+ return {
28523
+ success: false,
28524
+ error: error2 instanceof Error ? error2.message : "Unknown error"
28525
+ };
28526
+ }
28527
+ }
28528
+ var import_promises21, import_path112;
28529
+ var init_commands = __esm({
28530
+ "src/testing/cli/commands.ts"() {
28531
+ "use strict";
28532
+ import_promises21 = __toESM(require("fs/promises"), 1);
28533
+ import_path112 = __toESM(require("path"), 1);
28534
+ init_detectors();
28535
+ init_react();
28536
+ init_nodejs();
28537
+ init_python2();
28538
+ init_go2();
28539
+ init_rust2();
28540
+ init_contract();
28541
+ init_coverage();
28542
+ init_complexity();
28543
+ }
28544
+ });
28545
+
26823
28546
  // node_modules/commander/esm.mjs
26824
28547
  var import_index = __toESM(require_commander(), 1);
26825
28548
  var {
@@ -27334,7 +29057,7 @@ var source_default = chalk;
27334
29057
 
27335
29058
  // src/cli/index.ts
27336
29059
  var import_fs92 = require("fs");
27337
- var import_path107 = require("path");
29060
+ var import_path113 = require("path");
27338
29061
  var import_url15 = require("url");
27339
29062
  init_loader();
27340
29063
  init_models();
@@ -31354,8 +33077,8 @@ var require_schemes = __commonJS2((exports2, module2) => {
31354
33077
  wsComponents.secure = void 0;
31355
33078
  }
31356
33079
  if (wsComponents.resourceName) {
31357
- const [path20, query] = wsComponents.resourceName.split("?");
31358
- wsComponents.path = path20 && path20 !== "/" ? path20 : void 0;
33080
+ const [path26, query] = wsComponents.resourceName.split("?");
33081
+ wsComponents.path = path26 && path26 !== "/" ? path26 : void 0;
31359
33082
  wsComponents.query = query;
31360
33083
  wsComponents.resourceName = void 0;
31361
33084
  }
@@ -34390,12 +36113,12 @@ var require_dist = __commonJS2((exports2, module2) => {
34390
36113
  throw new Error(`Unknown format "${name}"`);
34391
36114
  return f;
34392
36115
  };
34393
- function addFormats(ajv, list, fs22, exportName) {
36116
+ function addFormats(ajv, list, fs25, exportName) {
34394
36117
  var _a;
34395
36118
  var _b;
34396
36119
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 || (_b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`);
34397
36120
  for (const f of list)
34398
- ajv.addFormat(f, fs22[f]);
36121
+ ajv.addFormat(f, fs25[f]);
34399
36122
  }
34400
36123
  module2.exports = exports2 = formatsPlugin;
34401
36124
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -35057,11 +36780,11 @@ function getDebugWriter() {
35057
36780
  if (!debugWriter) {
35058
36781
  debugWriter = createBufferedWriter({
35059
36782
  writeFn: (content) => {
35060
- const path20 = getDebugLogPath();
35061
- if (!getFsImplementation().existsSync((0, import_path6.dirname)(path20))) {
35062
- getFsImplementation().mkdirSync((0, import_path6.dirname)(path20));
36783
+ const path26 = getDebugLogPath();
36784
+ if (!getFsImplementation().existsSync((0, import_path6.dirname)(path26))) {
36785
+ getFsImplementation().mkdirSync((0, import_path6.dirname)(path26));
35063
36786
  }
35064
- getFsImplementation().appendFileSync(path20, content);
36787
+ getFsImplementation().appendFileSync(path26, content);
35065
36788
  updateLatestDebugLogSymlink();
35066
36789
  },
35067
36790
  flushIntervalMs: 1e3,
@@ -35163,40 +36886,40 @@ var NodeFsOperations = {
35163
36886
  }
35164
36887
  });
35165
36888
  },
35166
- appendFileSync(path20, data, options) {
35167
- return withSlowLogging2(`appendFileSync(${path20}, ${data.length} chars)`, () => {
35168
- if (!fs.existsSync(path20) && options?.mode !== void 0) {
35169
- const fd = fs.openSync(path20, "a", options.mode);
36889
+ appendFileSync(path26, data, options) {
36890
+ return withSlowLogging2(`appendFileSync(${path26}, ${data.length} chars)`, () => {
36891
+ if (!fs.existsSync(path26) && options?.mode !== void 0) {
36892
+ const fd = fs.openSync(path26, "a", options.mode);
35170
36893
  try {
35171
36894
  fs.appendFileSync(fd, data);
35172
36895
  } finally {
35173
36896
  fs.closeSync(fd);
35174
36897
  }
35175
36898
  } else {
35176
- fs.appendFileSync(path20, data);
36899
+ fs.appendFileSync(path26, data);
35177
36900
  }
35178
36901
  });
35179
36902
  },
35180
36903
  copyFileSync(src, dest) {
35181
36904
  return withSlowLogging2(`copyFileSync(${src} \u2192 ${dest})`, () => fs.copyFileSync(src, dest));
35182
36905
  },
35183
- unlinkSync(path20) {
35184
- return withSlowLogging2(`unlinkSync(${path20})`, () => fs.unlinkSync(path20));
36906
+ unlinkSync(path26) {
36907
+ return withSlowLogging2(`unlinkSync(${path26})`, () => fs.unlinkSync(path26));
35185
36908
  },
35186
36909
  renameSync(oldPath, newPath) {
35187
36910
  return withSlowLogging2(`renameSync(${oldPath} \u2192 ${newPath})`, () => fs.renameSync(oldPath, newPath));
35188
36911
  },
35189
- linkSync(target, path20) {
35190
- return withSlowLogging2(`linkSync(${target} \u2192 ${path20})`, () => fs.linkSync(target, path20));
36912
+ linkSync(target, path26) {
36913
+ return withSlowLogging2(`linkSync(${target} \u2192 ${path26})`, () => fs.linkSync(target, path26));
35191
36914
  },
35192
- symlinkSync(target, path20) {
35193
- return withSlowLogging2(`symlinkSync(${target} \u2192 ${path20})`, () => fs.symlinkSync(target, path20));
36915
+ symlinkSync(target, path26) {
36916
+ return withSlowLogging2(`symlinkSync(${target} \u2192 ${path26})`, () => fs.symlinkSync(target, path26));
35194
36917
  },
35195
- readlinkSync(path20) {
35196
- return withSlowLogging2(`readlinkSync(${path20})`, () => fs.readlinkSync(path20));
36918
+ readlinkSync(path26) {
36919
+ return withSlowLogging2(`readlinkSync(${path26})`, () => fs.readlinkSync(path26));
35197
36920
  },
35198
- realpathSync(path20) {
35199
- return withSlowLogging2(`realpathSync(${path20})`, () => fs.realpathSync(path20));
36921
+ realpathSync(path26) {
36922
+ return withSlowLogging2(`realpathSync(${path26})`, () => fs.realpathSync(path26));
35200
36923
  },
35201
36924
  mkdirSync(dirPath, options) {
35202
36925
  return withSlowLogging2(`mkdirSync(${dirPath})`, () => {
@@ -35226,11 +36949,11 @@ var NodeFsOperations = {
35226
36949
  rmdirSync(dirPath) {
35227
36950
  return withSlowLogging2(`rmdirSync(${dirPath})`, () => fs.rmdirSync(dirPath));
35228
36951
  },
35229
- rmSync(path20, options) {
35230
- return withSlowLogging2(`rmSync(${path20})`, () => fs.rmSync(path20, options));
36952
+ rmSync(path26, options) {
36953
+ return withSlowLogging2(`rmSync(${path26})`, () => fs.rmSync(path26, options));
35231
36954
  },
35232
- createWriteStream(path20) {
35233
- return fs.createWriteStream(path20);
36955
+ createWriteStream(path26) {
36956
+ return fs.createWriteStream(path26);
35234
36957
  }
35235
36958
  };
35236
36959
  var activeFs = NodeFsOperations;
@@ -35586,8 +37309,8 @@ function getErrorMap() {
35586
37309
  return overrideErrorMap;
35587
37310
  }
35588
37311
  var makeIssue = (params) => {
35589
- const { data, path: path20, errorMaps, issueData } = params;
35590
- const fullPath = [...path20, ...issueData.path || []];
37312
+ const { data, path: path26, errorMaps, issueData } = params;
37313
+ const fullPath = [...path26, ...issueData.path || []];
35591
37314
  const fullIssue = {
35592
37315
  ...issueData,
35593
37316
  path: fullPath
@@ -35694,11 +37417,11 @@ var errorUtil;
35694
37417
  errorUtil22.toString = (message) => typeof message === "string" ? message : message?.message;
35695
37418
  })(errorUtil || (errorUtil = {}));
35696
37419
  var ParseInputLazyPath = class {
35697
- constructor(parent, value, path20, key) {
37420
+ constructor(parent, value, path26, key) {
35698
37421
  this._cachedPath = [];
35699
37422
  this.parent = parent;
35700
37423
  this.data = value;
35701
- this._path = path20;
37424
+ this._path = path26;
35702
37425
  this._key = key;
35703
37426
  }
35704
37427
  get path() {
@@ -39189,10 +40912,10 @@ function assignProp(target, prop, value) {
39189
40912
  configurable: true
39190
40913
  });
39191
40914
  }
39192
- function getElementAtPath(obj, path20) {
39193
- if (!path20)
40915
+ function getElementAtPath(obj, path26) {
40916
+ if (!path26)
39194
40917
  return obj;
39195
- return path20.reduce((acc, key) => acc?.[key], obj);
40918
+ return path26.reduce((acc, key) => acc?.[key], obj);
39196
40919
  }
39197
40920
  function promiseAllObject(promisesObj) {
39198
40921
  const keys = Object.keys(promisesObj);
@@ -39509,11 +41232,11 @@ function aborted(x, startIndex = 0) {
39509
41232
  }
39510
41233
  return false;
39511
41234
  }
39512
- function prefixIssues(path20, issues) {
41235
+ function prefixIssues(path26, issues) {
39513
41236
  return issues.map((iss) => {
39514
41237
  var _a;
39515
41238
  (_a = iss).path ?? (_a.path = []);
39516
- iss.path.unshift(path20);
41239
+ iss.path.unshift(path26);
39517
41240
  return iss;
39518
41241
  });
39519
41242
  }
@@ -48181,8 +49904,8 @@ function getErrorMap2() {
48181
49904
 
48182
49905
  // node_modules/zod/v3/helpers/parseUtil.js
48183
49906
  var makeIssue2 = (params) => {
48184
- const { data, path: path20, errorMaps, issueData } = params;
48185
- const fullPath = [...path20, ...issueData.path || []];
49907
+ const { data, path: path26, errorMaps, issueData } = params;
49908
+ const fullPath = [...path26, ...issueData.path || []];
48186
49909
  const fullIssue = {
48187
49910
  ...issueData,
48188
49911
  path: fullPath
@@ -48298,11 +50021,11 @@ var errorUtil2;
48298
50021
 
48299
50022
  // node_modules/zod/v3/types.js
48300
50023
  var ParseInputLazyPath2 = class {
48301
- constructor(parent, value, path20, key) {
50024
+ constructor(parent, value, path26, key) {
48302
50025
  this._cachedPath = [];
48303
50026
  this.parent = parent;
48304
50027
  this.data = value;
48305
- this._path = path20;
50028
+ this._path = path26;
48306
50029
  this._key = key;
48307
50030
  }
48308
50031
  get path() {
@@ -52562,11 +54285,11 @@ function formatRange(range) {
52562
54285
  function formatLocation(location) {
52563
54286
  const uri = location.uri || location.targetUri;
52564
54287
  if (!uri) return "Unknown location";
52565
- const path20 = uriToPath(uri);
54288
+ const path26 = uriToPath(uri);
52566
54289
  const locationRange = location.range || location.targetRange || location.targetSelectionRange;
52567
- if (!locationRange) return path20;
54290
+ if (!locationRange) return path26;
52568
54291
  const range = formatRange(locationRange);
52569
- return `${path20}:${range}`;
54292
+ return `${path26}:${range}`;
52570
54293
  }
52571
54294
  function formatHover(hover) {
52572
54295
  if (!hover) return "No hover information available";
@@ -52652,8 +54375,8 @@ function formatWorkspaceEdit(edit) {
52652
54375
  const lines = [];
52653
54376
  if (edit.changes) {
52654
54377
  for (const [uri, changes] of Object.entries(edit.changes)) {
52655
- const path20 = uriToPath(uri);
52656
- lines.push(`File: ${path20}`);
54378
+ const path26 = uriToPath(uri);
54379
+ lines.push(`File: ${path26}`);
52657
54380
  for (const change of changes) {
52658
54381
  const range = formatRange(change.range);
52659
54382
  const preview = change.newText.length > 50 ? change.newText.slice(0, 50) + "..." : change.newText;
@@ -52663,8 +54386,8 @@ function formatWorkspaceEdit(edit) {
52663
54386
  }
52664
54387
  if (edit.documentChanges) {
52665
54388
  for (const docChange of edit.documentChanges) {
52666
- const path20 = uriToPath(docChange.textDocument.uri);
52667
- lines.push(`File: ${path20}`);
54389
+ const path26 = uriToPath(docChange.textDocument.uri);
54390
+ lines.push(`File: ${path26}`);
52668
54391
  for (const change of docChange.edits) {
52669
54392
  const range = formatRange(change.range);
52670
54393
  const preview = change.newText.length > 50 ? change.newText.slice(0, 50) + "..." : change.newText;
@@ -53456,7 +55179,7 @@ Note: Patterns must be valid AST nodes for the language.`,
53456
55179
  const {
53457
55180
  pattern,
53458
55181
  language,
53459
- path: path20 = ".",
55182
+ path: path26 = ".",
53460
55183
  context = 2,
53461
55184
  maxResults = 20
53462
55185
  } = args;
@@ -53473,13 +55196,13 @@ Error: ${sgLoadError}`
53473
55196
  ]
53474
55197
  };
53475
55198
  }
53476
- const files = getFilesForLanguage(path20, language);
55199
+ const files = getFilesForLanguage(path26, language);
53477
55200
  if (files.length === 0) {
53478
55201
  return {
53479
55202
  content: [
53480
55203
  {
53481
55204
  type: "text",
53482
- text: `No ${language} files found in ${path20}`
55205
+ text: `No ${language} files found in ${path26}`
53483
55206
  }
53484
55207
  ]
53485
55208
  };
@@ -53519,7 +55242,7 @@ Error: ${sgLoadError}`
53519
55242
  type: "text",
53520
55243
  text: `No matches found for pattern: ${pattern}
53521
55244
 
53522
- Searched ${files.length} ${language} file(s) in ${path20}
55245
+ Searched ${files.length} ${language} file(s) in ${path26}
53523
55246
 
53524
55247
  Tip: Ensure the pattern is a valid AST node. For example:
53525
55248
  - Use "function $NAME" not just "$NAME"
@@ -53579,7 +55302,7 @@ IMPORTANT: dryRun=true (default) only previews changes. Set dryRun=false to appl
53579
55302
  dryRun: external_exports.boolean().optional().describe("Preview only, don't apply changes (default: true)")
53580
55303
  },
53581
55304
  handler: async (args) => {
53582
- const { pattern, replacement, language, path: path20 = ".", dryRun = true } = args;
55305
+ const { pattern, replacement, language, path: path26 = ".", dryRun = true } = args;
53583
55306
  try {
53584
55307
  const sg = await getSgModule();
53585
55308
  if (!sg) {
@@ -53593,13 +55316,13 @@ Error: ${sgLoadError}`
53593
55316
  ]
53594
55317
  };
53595
55318
  }
53596
- const files = getFilesForLanguage(path20, language);
55319
+ const files = getFilesForLanguage(path26, language);
53597
55320
  if (files.length === 0) {
53598
55321
  return {
53599
55322
  content: [
53600
55323
  {
53601
55324
  type: "text",
53602
- text: `No ${language} files found in ${path20}`
55325
+ text: `No ${language} files found in ${path26}`
53603
55326
  }
53604
55327
  ]
53605
55328
  };
@@ -53667,7 +55390,7 @@ Error: ${sgLoadError}`
53667
55390
  type: "text",
53668
55391
  text: `No matches found for pattern: ${pattern}
53669
55392
 
53670
- Searched ${files.length} ${language} file(s) in ${path20}`
55393
+ Searched ${files.length} ${language} file(s) in ${path26}`
53671
55394
  }
53672
55395
  ]
53673
55396
  };
@@ -59655,14 +61378,14 @@ function getGitDiffStats(directory) {
59655
61378
  for (const line of output.split("\n")) {
59656
61379
  const parts = line.split(" ");
59657
61380
  if (parts.length < 3) continue;
59658
- const [addedStr, removedStr, path20] = parts;
61381
+ const [addedStr, removedStr, path26] = parts;
59659
61382
  const added = addedStr === "-" ? 0 : parseInt(addedStr, 10);
59660
61383
  const removed = removedStr === "-" ? 0 : parseInt(removedStr, 10);
59661
61384
  stats.push({
59662
- path: path20,
61385
+ path: path26,
59663
61386
  added,
59664
61387
  removed,
59665
- status: statusMap.get(path20) ?? "modified"
61388
+ status: statusMap.get(path26) ?? "modified"
59666
61389
  });
59667
61390
  }
59668
61391
  return stats;
@@ -60296,11 +62019,11 @@ Running directly without heavy agent stacking. Prefix with \`quick:\`, \`simple:
60296
62019
  const existingPrd = findPrd(directory);
60297
62020
  if (!noPrd && !existingPrd) {
60298
62021
  const { basename: basename21 } = await import("path");
60299
- const { execSync: execSync18 } = await import("child_process");
62022
+ const { execSync: execSync19 } = await import("child_process");
60300
62023
  const projectName = basename21(directory);
60301
62024
  let branchName = "ralph/task";
60302
62025
  try {
60303
- branchName = execSync18("git rev-parse --abbrev-ref HEAD", { cwd: directory, encoding: "utf-8", timeout: 5e3 }).trim();
62026
+ branchName = execSync19("git rev-parse --abbrev-ref HEAD", { cwd: directory, encoding: "utf-8", timeout: 5e3 }).trim();
60304
62027
  } catch {
60305
62028
  }
60306
62029
  initPrdFn(directory, projectName, branchName, cleanPrompt);
@@ -60832,11 +62555,11 @@ async function processPostToolUse(input) {
60832
62555
  const existingPrd = findPrd(directory);
60833
62556
  if (!noPrd && !existingPrd) {
60834
62557
  const { basename: basename21 } = await import("path");
60835
- const { execSync: execSync18 } = await import("child_process");
62558
+ const { execSync: execSync19 } = await import("child_process");
60836
62559
  const projectName = basename21(directory);
60837
62560
  let branchName = "ralph/task";
60838
62561
  try {
60839
- branchName = execSync18("git rev-parse --abbrev-ref HEAD", { cwd: directory, encoding: "utf-8", timeout: 5e3 }).trim();
62562
+ branchName = execSync19("git rev-parse --abbrev-ref HEAD", { cwd: directory, encoding: "utf-8", timeout: 5e3 }).trim();
60840
62563
  } catch {
60841
62564
  }
60842
62565
  initPrdFn(directory, projectName, branchName, cleanPrompt);
@@ -63067,17 +64790,17 @@ function taskFileCandidates(teamName, taskId, cwd2) {
63067
64790
  const legacy = legacyTaskFilePath(teamName, taskId, cwd2);
63068
64791
  return canonical === legacy ? [canonical] : [canonical, legacy];
63069
64792
  }
63070
- async function writeAtomic(path20, data) {
63071
- const tmp = `${path20}.${process.pid}.tmp`;
63072
- await (0, import_promises7.mkdir)((0, import_node_path5.dirname)(path20), { recursive: true });
64793
+ async function writeAtomic(path26, data) {
64794
+ const tmp = `${path26}.${process.pid}.tmp`;
64795
+ await (0, import_promises7.mkdir)((0, import_node_path5.dirname)(path26), { recursive: true });
63073
64796
  await (0, import_promises7.writeFile)(tmp, data, "utf8");
63074
64797
  const { rename: rename3 } = await import("node:fs/promises");
63075
- await rename3(tmp, path20);
64798
+ await rename3(tmp, path26);
63076
64799
  }
63077
- async function readJsonSafe(path20) {
64800
+ async function readJsonSafe(path26) {
63078
64801
  try {
63079
- if (!(0, import_node_fs2.existsSync)(path20)) return null;
63080
- const raw = await (0, import_promises7.readFile)(path20, "utf8");
64802
+ if (!(0, import_node_fs2.existsSync)(path26)) return null;
64803
+ const raw = await (0, import_promises7.readFile)(path26, "utf8");
63081
64804
  return JSON.parse(raw);
63082
64805
  } catch {
63083
64806
  return null;
@@ -63574,10 +65297,10 @@ function readTeamStateRootFromEnv(env2 = process.env) {
63574
65297
  const candidate = typeof env2.OMC_TEAM_STATE_ROOT === "string" && env2.OMC_TEAM_STATE_ROOT.trim() !== "" ? env2.OMC_TEAM_STATE_ROOT.trim() : typeof env2.OMX_TEAM_STATE_ROOT === "string" && env2.OMX_TEAM_STATE_ROOT.trim() !== "" ? env2.OMX_TEAM_STATE_ROOT.trim() : "";
63575
65298
  return candidate || null;
63576
65299
  }
63577
- function readTeamStateRootFromFile(path20) {
63578
- if (!(0, import_node_fs3.existsSync)(path20)) return null;
65300
+ function readTeamStateRootFromFile(path26) {
65301
+ if (!(0, import_node_fs3.existsSync)(path26)) return null;
63579
65302
  try {
63580
- const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path20, "utf8"));
65303
+ const parsed = JSON.parse((0, import_node_fs3.readFileSync)(path26, "utf8"));
63581
65304
  return typeof parsed.team_state_root === "string" && parsed.team_state_root.trim() !== "" ? parsed.team_state_root.trim() : null;
63582
65305
  } catch {
63583
65306
  return null;
@@ -66196,7 +67919,7 @@ function warnIfWin32() {
66196
67919
  }
66197
67920
 
66198
67921
  // src/cli/index.ts
66199
- var __dirname3 = (0, import_path107.dirname)((0, import_url15.fileURLToPath)(importMetaUrl));
67922
+ var __dirname3 = (0, import_path113.dirname)((0, import_url15.fileURLToPath)(importMetaUrl));
66200
67923
  var version2 = getRuntimePackageVersion();
66201
67924
  var program2 = new Command();
66202
67925
  warnIfWin32();
@@ -66244,7 +67967,7 @@ Examples:
66244
67967
  console.log(source_default.gray("Configuration is now managed automatically. Use /oh-my-claudecode:omc-setup instead.\n"));
66245
67968
  const paths = getConfigPaths();
66246
67969
  const targetPath = options.global ? paths.user : paths.project;
66247
- const targetDir = (0, import_path107.dirname)(targetPath);
67970
+ const targetDir = (0, import_path113.dirname)(targetPath);
66248
67971
  console.log(source_default.blue("Oh-My-ClaudeCode Configuration Setup\n"));
66249
67972
  if ((0, import_fs92.existsSync)(targetPath) && !options.force) {
66250
67973
  console.log(source_default.yellow(`Configuration already exists at ${targetPath}`));
@@ -66350,12 +68073,12 @@ Examples:
66350
68073
  `;
66351
68074
  (0, import_fs92.writeFileSync)(targetPath, configContent);
66352
68075
  console.log(source_default.green(`Created configuration: ${targetPath}`));
66353
- const schemaPath = (0, import_path107.join)(targetDir, "omc-schema.json");
68076
+ const schemaPath = (0, import_path113.join)(targetDir, "omc-schema.json");
66354
68077
  (0, import_fs92.writeFileSync)(schemaPath, JSON.stringify(generateConfigSchema(), null, 2));
66355
68078
  console.log(source_default.green(`Created JSON schema: ${schemaPath}`));
66356
68079
  console.log(source_default.blue("\nSetup complete!"));
66357
68080
  console.log(source_default.gray("Edit the configuration file to customize your setup."));
66358
- const agentsMdPath = (0, import_path107.join)(process.cwd(), "AGENTS.md");
68081
+ const agentsMdPath = (0, import_path113.join)(process.cwd(), "AGENTS.md");
66359
68082
  if (!(0, import_fs92.existsSync)(agentsMdPath) && !options.global) {
66360
68083
  const agentsMdContent = `# Project Agents Configuration
66361
68084
 
@@ -67080,8 +68803,8 @@ Note:
67080
68803
  teleportCmd.command("list").description("List existing worktrees in ~/Workspace/omc-worktrees/").option("--json", "Output as JSON").action(async (options) => {
67081
68804
  await teleportListCommand(options);
67082
68805
  });
67083
- teleportCmd.command("remove <path>").alias("rm").description("Remove a worktree").option("-f, --force", "Force removal even with uncommitted changes").option("--json", "Output as JSON").action(async (path20, options) => {
67084
- const exitCode = await teleportRemoveCommand(path20, options);
68806
+ teleportCmd.command("remove <path>").alias("rm").description("Remove a worktree").option("-f, --force", "Force removal even with uncommitted changes").option("--json", "Output as JSON").action(async (path26, options) => {
68807
+ const exitCode = await teleportRemoveCommand(path26, options);
67085
68808
  if (exitCode !== 0) process.exit(exitCode);
67086
68809
  });
67087
68810
  var doctorCmd = program2.command("doctor").description("Diagnostic tools for troubleshooting OMC installation").addHelpText("after", `
@@ -67175,6 +68898,135 @@ program2.command("hud").description("Run the OMC HUD statusline renderer").optio
67175
68898
  await hudMain();
67176
68899
  }
67177
68900
  });
68901
+ var testCommand = program2.command("test").description("Testing utilities");
68902
+ testCommand.command("gen <file>").description("Generate tests for a file (.ts, .tsx, .jsx, .py, .go, .rs)").option("-o, --output <path>", "Output test file path").option("-l, --language <lang>", "Language override (typescript, react, python, go, rust)").action(async (file, options) => {
68903
+ const { testGenCommand: testGenCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68904
+ const result = await testGenCommand2({
68905
+ filePath: file,
68906
+ output: options.output,
68907
+ language: options.language
68908
+ });
68909
+ if (result.success) {
68910
+ console.log(source_default.green(`\u2705 Test generated: ${result.testFilePath}`));
68911
+ } else {
68912
+ console.error(source_default.red(`\u274C Error: ${result.error}`));
68913
+ process.exit(1);
68914
+ }
68915
+ });
68916
+ testCommand.command("detect-stack").description("Detect project tech stack").action(async () => {
68917
+ const { testDetectStackCommand: testDetectStackCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68918
+ const result = await testDetectStackCommand2({
68919
+ projectRoot: process.cwd()
68920
+ });
68921
+ console.log(source_default.blue("\u{1F4CA} Detected Tech Stack:"));
68922
+ console.log(JSON.stringify(result.stack, null, 2));
68923
+ });
68924
+ testCommand.command("analyze").description("Analyze test coverage for the project").action(async () => {
68925
+ const { testAnalyzeCoverageCommand: testAnalyzeCoverageCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68926
+ const result = await testAnalyzeCoverageCommand2({
68927
+ projectRoot: process.cwd()
68928
+ });
68929
+ console.log(source_default.blue("\u{1F4CA} Coverage Analysis:"));
68930
+ console.log(` Total: ${result.totalCoverage}%`);
68931
+ console.log(` Lines: ${result.lineCoverage}%`);
68932
+ console.log(` Functions: ${result.functionCoverage}%`);
68933
+ console.log(` Branches: ${result.branchCoverage}%`);
68934
+ console.log(` Statements: ${result.statementCoverage}%`);
68935
+ });
68936
+ testCommand.command("contract <openapi-spec>").description("Generate contract tests from an OpenAPI spec").option("-f, --framework <framework>", "Test framework (pact, supertest, msw)", "pact").option("-c, --consumer <name>", "Consumer name").option("-p, --provider <name>", "Provider name").action(async (specPath, options) => {
68937
+ const { testContractCommand: testContractCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68938
+ const result = await testContractCommand2({
68939
+ specPath,
68940
+ framework: options.framework,
68941
+ consumer: options.consumer,
68942
+ provider: options.provider
68943
+ });
68944
+ if (result.success) {
68945
+ console.log(source_default.green(`\u2705 Contract test generated: ${result.testFilePath}`));
68946
+ } else {
68947
+ console.error(source_default.red("\u274C Failed to generate contract test"));
68948
+ process.exit(1);
68949
+ }
68950
+ });
68951
+ testCommand.command("complexity <file>").description("Analyze code complexity for a file").action(async (file) => {
68952
+ const { testComplexityCommand: testComplexityCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68953
+ const result = await testComplexityCommand2({ filePath: file });
68954
+ console.log(source_default.blue(`\u{1F4CA} Complexity Analysis: ${result.complexity}`));
68955
+ console.log(` Lines: ${result.metrics.lines}`);
68956
+ console.log(` Cyclomatic Complexity: ${result.metrics.cyclomaticComplexity}`);
68957
+ console.log(` Nesting Level: ${result.metrics.nestingLevel}`);
68958
+ console.log(` External Deps: ${result.metrics.externalDependencies}`);
68959
+ if (result.reasons.length > 0) {
68960
+ console.log(` Reasons: ${result.reasons.join(", ")}`);
68961
+ }
68962
+ });
68963
+ testCommand.command("e2e <flow-description>").description("Generate Playwright E2E tests from user flow description").option("-b, --base-url <url>", "Base URL for the application", "http://localhost:3000").option("-n, --test-name <name>", "Test name", "User flow test").option("-o, --output <path>", "Output test file path", "./tests/e2e/user-flow.spec.ts").action(async (flowDescription, options) => {
68964
+ const { testE2ECommand: testE2ECommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68965
+ const result = await testE2ECommand2({
68966
+ flowDescription,
68967
+ baseUrl: options.baseUrl,
68968
+ testName: options.testName,
68969
+ output: options.output
68970
+ });
68971
+ if (result.success) {
68972
+ console.log(source_default.green(`\u2705 E2E test generated: ${result.testFilePath}`));
68973
+ } else {
68974
+ console.error(source_default.red(`\u274C Error: ${result.error}`));
68975
+ process.exit(1);
68976
+ }
68977
+ });
68978
+ testCommand.command("giskard <file>").description("Generate Giskard behavioral tests for robustness testing").option("-t, --test-type <type>", "Test type (perturbation, robustness)", "perturbation").option("-o, --output <path>", "Output test file path", "./tests/behavioral/perturbation.test.ts").action(async (file, options) => {
68979
+ const { testGiskardCommand: testGiskardCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68980
+ const result = await testGiskardCommand2({
68981
+ filePath: file,
68982
+ testType: options.testType,
68983
+ output: options.output
68984
+ });
68985
+ if (result.success) {
68986
+ console.log(source_default.green(`\u2705 Giskard behavioral tests generated: ${result.testFilePath}`));
68987
+ } else {
68988
+ console.error(source_default.red(`\u274C Error: ${result.error}`));
68989
+ process.exit(1);
68990
+ }
68991
+ });
68992
+ testCommand.command("cicd").description("Generate GitHub Actions CI/CD workflow for testing").option("-l, --language <lang>", "Primary language (nodejs, python, go, rust)", "nodejs").option("-o, --output <path>", "Output workflow file path", "./.github/workflows/test.yml").action(async (options) => {
68993
+ const { testCICDCommand: testCICDCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
68994
+ const result = await testCICDCommand2({
68995
+ language: options.language,
68996
+ output: options.output
68997
+ });
68998
+ if (result.success) {
68999
+ console.log(source_default.green(`\u2705 CI/CD workflow generated: ${result.workflowPath}`));
69000
+ } else {
69001
+ console.error(source_default.red(`\u274C Error: ${result.error}`));
69002
+ process.exit(1);
69003
+ }
69004
+ });
69005
+ testCommand.command("quality <test-file>").description("Score test quality and get improvement recommendations").option("-t, --test-type <type>", "Test type (unit, integration, e2e)", "unit").action(async (testFile, options) => {
69006
+ const { testQualityCommand: testQualityCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
69007
+ const result = await testQualityCommand2({
69008
+ testFilePath: testFile,
69009
+ testType: options.testType
69010
+ });
69011
+ if (result.success && result.score) {
69012
+ console.log(source_default.blue("\u{1F4CA} Test Quality Score:"));
69013
+ console.log(` Overall: ${result.score.overallScore}/100`);
69014
+ console.log(` Completeness: ${result.score.completenessScore}/100`);
69015
+ console.log(` Assertions: ${result.score.assertionQuality}/100`);
69016
+ console.log(` Independence: ${result.score.independenceScore}/100`);
69017
+ console.log(` Naming: ${result.score.namingScore}/100`);
69018
+ console.log(` Assertion Count: ${result.score.assertionCount}`);
69019
+ if (result.score.recommendations.length > 0) {
69020
+ console.log(source_default.yellow("\n\u{1F4A1} Recommendations:"));
69021
+ result.score.recommendations.forEach((rec) => {
69022
+ console.log(` - ${rec}`);
69023
+ });
69024
+ }
69025
+ } else {
69026
+ console.error(source_default.red(`\u274C Error: ${result.error}`));
69027
+ process.exit(1);
69028
+ }
69029
+ });
67178
69030
  program2.command("team").description("Team CLI API for worker lifecycle operations").helpOption(false).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "team subcommand arguments").action(async (args) => {
67179
69031
  await teamCommand(args);
67180
69032
  });