@gobing-ai/superskill 0.2.3 → 0.2.5

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 (3) hide show
  1. package/README.md +41 -244
  2. package/dist/index.js +1028 -288
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2226,13 +2226,20 @@ import { rmSync } from "fs";
2226
2226
  async function backupFile(filePath) {
2227
2227
  let backupPath = `${filePath}.bak`;
2228
2228
  if (await Bun.file(backupPath).exists()) {
2229
- const ts = new Date().toISOString().replace(/[:.]/g, "").slice(0, 15);
2229
+ const ts = new Date().toISOString().replace(/[:.]/g, "").slice(0, 18);
2230
2230
  backupPath = `${filePath}.bak.${ts}`;
2231
+ let counter = 1;
2232
+ while (await Bun.file(backupPath).exists()) {
2233
+ backupPath = `${filePath}.bak.${ts}.${counter++}`;
2234
+ }
2231
2235
  }
2232
2236
  await Bun.write(backupPath, Bun.file(filePath));
2233
2237
  return backupPath;
2234
2238
  }
2235
2239
  async function restoreFromBackup(backupPath, originalPath) {
2240
+ if (!await Bun.file(backupPath).exists()) {
2241
+ throw new Error(`Backup file not found: ${backupPath} \u2014 cannot restore ${originalPath}`);
2242
+ }
2236
2243
  await Bun.write(originalPath, Bun.file(backupPath));
2237
2244
  rmSync(backupPath, { force: true });
2238
2245
  }
@@ -9230,11 +9237,10 @@ var init_dist2 = __esm(() => {
9230
9237
 
9231
9238
  // ../../packages/core/src/content/frontmatter.ts
9232
9239
  function parseFrontmatter(content) {
9233
- if (!content.startsWith(`---
9234
- `)) {
9240
+ if (!/^---\r?\n/.test(content)) {
9235
9241
  throw new FrontmatterError("Missing frontmatter: content must start with ---");
9236
9242
  }
9237
- const closerMatch = content.slice(4).match(/\n---(?=\n|$)/);
9243
+ const closerMatch = content.slice(4).match(/\r?\n---(?=\r?\n|$)/);
9238
9244
  if (closerMatch?.index === undefined) {
9239
9245
  throw new FrontmatterError("Missing frontmatter closing delimiter (---)");
9240
9246
  }
@@ -9445,7 +9451,7 @@ function walkFrontmatter(content, opts) {
9445
9451
  }
9446
9452
  out.push(line);
9447
9453
  }
9448
- if (!injectedName) {
9454
+ if (!injectedName || inFrontmatter) {
9449
9455
  return `${opts.fallbackBlock}
9450
9456
 
9451
9457
  ${content}`;
@@ -9469,6 +9475,12 @@ var init_rewrite_references = __esm(() => {
9469
9475
  SLASH_COMMAND_LINE_RE = /^\s*\/[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+(\s|$)/;
9470
9476
  });
9471
9477
 
9478
+ // ../../packages/core/src/pipeline/yaml-utils.ts
9479
+ function quoteYaml(value) {
9480
+ const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
9481
+ return `"${escaped}"`;
9482
+ }
9483
+
9472
9484
  // ../../packages/core/src/pipeline/adapt-command.ts
9473
9485
  function adaptCommandToSkill(source, expectedName, pluginPrefix) {
9474
9486
  let result;
@@ -9480,7 +9492,7 @@ function adaptCommandToSkill(source, expectedName, pluginPrefix) {
9480
9492
  const description = firstLine?.trim() || `${expectedName} command`;
9481
9493
  result = `---
9482
9494
  name: ${expectedName}
9483
- description: "${description}"
9495
+ description: ${quoteYaml(description)}
9484
9496
  disable-model-invocation: true
9485
9497
  ---
9486
9498
 
@@ -9502,7 +9514,8 @@ function normalizeCommandFrontmatter(content, expectedName) {
9502
9514
  const value = line.slice(line.indexOf(":") + 1).trim();
9503
9515
  if (value.startsWith("["))
9504
9516
  return line;
9505
- const parts = value.split(/,\s*/).map((p) => p.trim()).filter(Boolean);
9517
+ const unquoted = value.replace(/^["']|["']$/g, "");
9518
+ const parts = unquoted.split(/,\s*/).map((p) => p.trim()).filter(Boolean);
9506
9519
  return `allowed-tools: [${parts.join(", ")}]`;
9507
9520
  }
9508
9521
  }
@@ -9517,10 +9530,6 @@ disable-model-invocation: true
9517
9530
  ---`
9518
9531
  });
9519
9532
  }
9520
- function quoteYaml(value) {
9521
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
9522
- return `"${escaped}"`;
9523
- }
9524
9533
  var init_adapt_command = __esm(() => {
9525
9534
  init_rewrite_references();
9526
9535
  });
@@ -9603,7 +9612,7 @@ function adaptSubagentToSkill(source, expectedName, pluginPrefix) {
9603
9612
  const description = firstLine?.trim() || `${expectedName} subagent`;
9604
9613
  result = `---
9605
9614
  name: ${expectedName}
9606
- description: "${description}"
9615
+ description: ${quoteYaml(description)}
9607
9616
  ---
9608
9617
 
9609
9618
  ${source}`;
@@ -9637,17 +9646,17 @@ ${source}`;
9637
9646
  const piTools = normalizePiToolList(rawToolsStr);
9638
9647
  const description = asString(data.description) || `${expectedName} subagent`;
9639
9648
  let model = asString(data.model);
9640
- if (model === "inherit")
9649
+ if (model.toLowerCase() === "inherit")
9641
9650
  model = "";
9642
9651
  const skillsList = resolvePiSkills(data, body, pluginPrefix, skillExists);
9643
9652
  const skillsCsv = skillsList.join(", ");
9644
9653
  const fields = [`name: ${expectedName}`];
9645
9654
  if (description)
9646
- fields.push(`description: ${description}`);
9655
+ fields.push(`description: ${quoteYaml(description)}`);
9647
9656
  if (piTools)
9648
9657
  fields.push(`tools: ${piTools}`);
9649
9658
  if (model)
9650
- fields.push(`model: ${model}`);
9659
+ fields.push(`model: ${quoteYaml(model)}`);
9651
9660
  if (skillsCsv)
9652
9661
  fields.push(`skill: ${skillsCsv}`);
9653
9662
  const runtimeNotes = buildPiRuntimeNotes(parseToolsList(rawToolsStr), skillsCsv);
@@ -9731,10 +9740,59 @@ var init_adapt_subagent = __esm(() => {
9731
9740
  });
9732
9741
 
9733
9742
  // ../../packages/core/src/mapper.ts
9734
- import { existsSync as existsSync3, mkdirSync, readdirSync, readFileSync as readFileSync2, statSync as statSync2, writeFileSync } from "fs";
9735
- import { join as join3 } from "path";
9743
+ import { existsSync as existsSync3, lstatSync, mkdirSync, readdirSync, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync } from "fs";
9744
+ import { homedir as homedir2 } from "os";
9745
+ import { join as join3, resolve } from "path";
9746
+ function convertClaudeHooksToCanonical(claudeJson) {
9747
+ const claudeHooks = claudeJson.hooks;
9748
+ if (!claudeHooks || typeof claudeHooks !== "object")
9749
+ return claudeJson;
9750
+ const canonical = {};
9751
+ for (const [claudeEvent, matcherEntries] of Object.entries(claudeHooks)) {
9752
+ const canonicalEvent = CLAUDE_TO_CANONICAL_EVENT[claudeEvent] ?? claudeEvent;
9753
+ if (!Array.isArray(matcherEntries))
9754
+ continue;
9755
+ const defs = [];
9756
+ for (const entry of matcherEntries) {
9757
+ if (typeof entry !== "object" || entry === null)
9758
+ continue;
9759
+ const e = entry;
9760
+ const hookList = e.hooks;
9761
+ if (Array.isArray(hookList)) {
9762
+ const matcher = e.matcher;
9763
+ for (const hook of hookList) {
9764
+ if (typeof hook !== "object" || hook === null)
9765
+ continue;
9766
+ const h = hook;
9767
+ const def = { ...h };
9768
+ if (matcher !== undefined && matcher !== "*") {
9769
+ def.matcher = matcher;
9770
+ }
9771
+ defs.push(def);
9772
+ }
9773
+ } else {
9774
+ defs.push({ ...e });
9775
+ }
9776
+ }
9777
+ if (defs.length > 0) {
9778
+ canonical[canonicalEvent] = defs;
9779
+ }
9780
+ }
9781
+ return { hooks: canonical };
9782
+ }
9783
+ function setSkillName(content, newName) {
9784
+ if (/^name:\s*.+$/m.test(content)) {
9785
+ return content.replace(/^name:\s*.+$/m, `name: ${newName}`);
9786
+ }
9787
+ return content.replace(/^---\s*$/m, `---
9788
+ name: ${newName}`);
9789
+ }
9736
9790
  function mapPluginToRulesync(pluginPath, pluginName, outputDir) {
9737
9791
  assertSafePathSegment(pluginName, "plugin name");
9792
+ assertSafeOutputDir(outputDir);
9793
+ if (existsSync3(outputDir)) {
9794
+ rmSync2(outputDir, { recursive: true, force: true });
9795
+ }
9738
9796
  mkdirSync(outputDir, { recursive: true });
9739
9797
  const result = { skills: 0, commands: 0, subagents: 0, hooks: false, mcp: false };
9740
9798
  const skillsDir = join3(pluginPath, "skills");
@@ -9756,9 +9814,11 @@ function mapPluginToRulesync(pluginPath, pluginName, outputDir) {
9756
9814
  }
9757
9815
  if (!skillName || !sourcePath)
9758
9816
  continue;
9759
- const dir = join3(skillsOut, `${pluginName}-${skillName}`);
9817
+ const expectedName = `${pluginName}-${skillName}`;
9818
+ const dir = join3(skillsOut, expectedName);
9760
9819
  mkdirSync(dir, { recursive: true });
9761
- const content = rewriteSkillReferences(readFileSync2(sourcePath, "utf-8"), pluginName);
9820
+ const rawContent = readFileSync2(sourcePath, "utf-8");
9821
+ const content = rewriteSkillReferences(setSkillName(rawContent, expectedName), pluginName);
9762
9822
  writeFileSync(join3(dir, "SKILL.md"), content);
9763
9823
  if (sourceDir) {
9764
9824
  for (const subdir of ["scripts", "references", "templates", "assets"]) {
@@ -9807,7 +9867,10 @@ function mapPluginToRulesync(pluginPath, pluginName, outputDir) {
9807
9867
  const hooksSubdirPath = join3(pluginPath, "hooks", "hooks.json");
9808
9868
  const hooksPath = existsSync3(hooksRootPath) ? hooksRootPath : hooksSubdirPath;
9809
9869
  if (existsSync3(hooksPath)) {
9810
- deepMergeJsonFile(hooksPath, join3(outputDir, "hooks.json"));
9870
+ const claudeHooks = readJsonObject(hooksPath);
9871
+ const canonical = convertClaudeHooksToCanonical(claudeHooks);
9872
+ writeFileSync(join3(outputDir, "hooks.json"), `${JSON.stringify(canonical, null, 4)}
9873
+ `);
9811
9874
  result.hooks = true;
9812
9875
  }
9813
9876
  const mcpRootPath = join3(pluginPath, "mcp.json");
@@ -9827,7 +9890,12 @@ function deepMergeJsonFile(sourcePath, targetPath) {
9827
9890
  `);
9828
9891
  }
9829
9892
  function readJsonObject(path) {
9830
- const value = JSON.parse(readFileSync2(path, "utf-8"));
9893
+ let value;
9894
+ try {
9895
+ value = JSON.parse(readFileSync2(path, "utf-8"));
9896
+ } catch (e) {
9897
+ throw new Error(`Failed to parse JSON in ${path}: ${e instanceof Error ? e.message : String(e)}`);
9898
+ }
9831
9899
  if (!isJsonObject(value)) {
9832
9900
  throw new Error(`Expected JSON object in ${path}`);
9833
9901
  }
@@ -9844,24 +9912,93 @@ function deepMerge2(target, source) {
9844
9912
  function isJsonObject(value) {
9845
9913
  return typeof value === "object" && value !== null && !Array.isArray(value);
9846
9914
  }
9915
+ function assertSafeOutputDir(outputDir) {
9916
+ const resolved = resolve(outputDir);
9917
+ const home = homedir2();
9918
+ const dangerous = [home, process.cwd(), "/", "/home", "/Users"];
9919
+ for (const danger of dangerous) {
9920
+ if (resolved === resolve(danger)) {
9921
+ throw new Error(`Refusing to delete output directory '${resolved}': resolves to a protected path ` + `(home, cwd, or filesystem root). Use a subdirectory.`);
9922
+ }
9923
+ }
9924
+ }
9847
9925
  function copyAndRewriteDirectory(source, destination, pluginName) {
9848
9926
  mkdirSync(destination, { recursive: true });
9849
9927
  for (const entry of readdirSync(source)) {
9850
9928
  const srcPath = join3(source, entry);
9851
9929
  const destPath = join3(destination, entry);
9852
- if (statSync2(srcPath).isDirectory()) {
9930
+ const stat = lstatSync(srcPath);
9931
+ if (stat.isSymbolicLink())
9932
+ continue;
9933
+ if (stat.isDirectory()) {
9853
9934
  copyAndRewriteDirectory(srcPath, destPath, pluginName);
9854
9935
  } else {
9855
- const content = readFileSync2(srcPath, "utf-8");
9856
- writeFileSync(destPath, rewriteSkillReferences(content, pluginName));
9936
+ const bytes = readFileSync2(srcPath);
9937
+ if (isTextFile(entry, bytes)) {
9938
+ const content = bytes.toString("utf-8");
9939
+ writeFileSync(destPath, rewriteSkillReferences(content, pluginName));
9940
+ } else {
9941
+ writeFileSync(destPath, bytes);
9942
+ }
9857
9943
  }
9858
9944
  }
9859
9945
  }
9946
+ function isTextFile(filename, bytes) {
9947
+ const ext = filename.slice(filename.lastIndexOf("."));
9948
+ if (TEXT_EXTENSIONS.has(ext))
9949
+ return true;
9950
+ return !bytes.subarray(0, 8192).includes(0);
9951
+ }
9952
+ var CLAUDE_TO_CANONICAL_EVENT, TEXT_EXTENSIONS;
9860
9953
  var init_mapper = __esm(() => {
9861
9954
  init_identity();
9862
9955
  init_adapt_command();
9863
9956
  init_adapt_subagent();
9864
9957
  init_rewrite_references();
9958
+ CLAUDE_TO_CANONICAL_EVENT = {
9959
+ SessionStart: "sessionStart",
9960
+ SessionEnd: "sessionEnd",
9961
+ PreToolUse: "preToolUse",
9962
+ PostToolUse: "postToolUse",
9963
+ PreModelInvocation: "preModelInvocation",
9964
+ PostModelInvocation: "postModelInvocation",
9965
+ BeforeSubmitPrompt: "beforeSubmitPrompt",
9966
+ Stop: "stop",
9967
+ SubagentStop: "subagentStop",
9968
+ PreCompact: "preCompact",
9969
+ Notification: "notification",
9970
+ WorktreeCreate: "worktreeCreate",
9971
+ WorktreeRemove: "worktreeRemove",
9972
+ MessageDisplay: "messageDisplay"
9973
+ };
9974
+ TEXT_EXTENSIONS = new Set([
9975
+ ".md",
9976
+ ".ts",
9977
+ ".js",
9978
+ ".json",
9979
+ ".yaml",
9980
+ ".yml",
9981
+ ".txt",
9982
+ ".sh",
9983
+ ".bash",
9984
+ ".py",
9985
+ ".rb",
9986
+ ".go",
9987
+ ".rs",
9988
+ ".java",
9989
+ ".c",
9990
+ ".cpp",
9991
+ ".h",
9992
+ ".css",
9993
+ ".html",
9994
+ ".xml",
9995
+ ".toml",
9996
+ ".ini",
9997
+ ".cfg",
9998
+ ".env",
9999
+ ".gitignore",
10000
+ ".dockerfile"
10001
+ ]);
9865
10002
  });
9866
10003
 
9867
10004
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/util.js
@@ -13832,20 +13969,20 @@ var init_zod = __esm(() => {
13832
13969
 
13833
13970
  // ../../packages/core/src/marketplace.ts
13834
13971
  import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
13835
- import { join as join4, resolve } from "path";
13972
+ import { join as join4, resolve as resolve2 } from "path";
13836
13973
  function resolvePlugin(marketplacePath, pluginName) {
13837
13974
  let manifestPath = null;
13838
13975
  if (marketplacePath) {
13839
13976
  if (marketplacePath.endsWith("marketplace.json")) {
13840
- manifestPath = resolve(marketplacePath);
13977
+ manifestPath = resolve2(marketplacePath);
13841
13978
  } else {
13842
- manifestPath = resolve(join4(marketplacePath, "marketplace.json"));
13979
+ manifestPath = resolve2(join4(marketplacePath, "marketplace.json"));
13843
13980
  }
13844
13981
  if (!existsSync4(manifestPath)) {
13845
13982
  throw new Error(`Marketplace manifest not found at: ${manifestPath}`);
13846
13983
  }
13847
13984
  } else {
13848
- const cwdManifest = resolve(".claude-plugin", "marketplace.json");
13985
+ const cwdManifest = resolve2(".claude-plugin", "marketplace.json");
13849
13986
  if (existsSync4(cwdManifest)) {
13850
13987
  manifestPath = cwdManifest;
13851
13988
  }
@@ -13872,12 +14009,15 @@ function resolvePlugin(marketplacePath, pluginName) {
13872
14009
  if (!source.startsWith("./")) {
13873
14010
  throw new Error(`Remote sources not yet supported for plugin '${pluginName}'. Phase 1 only supports relative-path sources (starting with './').`);
13874
14011
  }
13875
- if (/(?:^|\/)\.\.(?:\/|$)/.test(source)) {
14012
+ if (/(?:^|[\\/])\.\.(?:[\\/]|$)/.test(source)) {
13876
14013
  throw new Error(`Plugin source for '${pluginName}' escapes the marketplace root: '${source}'.`);
13877
14014
  }
13878
- const marketplaceRoot = resolve(manifestPath, "..", "..");
13879
14015
  const pluginRootBase = manifest.metadata?.pluginRoot ?? "";
13880
- const pluginRoot = resolve(marketplaceRoot, pluginRootBase, source);
14016
+ if (pluginRootBase && /(?:^|[\\/])\.\.(?:[\\/]|$)/.test(pluginRootBase)) {
14017
+ throw new Error(`Plugin root for '${pluginName}' escapes the marketplace root: '${pluginRootBase}'.`);
14018
+ }
14019
+ const marketplaceRoot = resolve2(manifestPath, "..", "..");
14020
+ const pluginRoot = resolve2(marketplaceRoot, pluginRootBase, source);
13881
14021
  let dirents;
13882
14022
  try {
13883
14023
  dirents = readdirSync2(pluginRoot);
@@ -13897,11 +14037,11 @@ function resolvePlugin(marketplacePath, pluginName) {
13897
14037
  function listResolvablePlugins(marketplacePath) {
13898
14038
  let manifestPath = null;
13899
14039
  if (marketplacePath) {
13900
- manifestPath = marketplacePath.endsWith("marketplace.json") ? resolve(marketplacePath) : resolve(join4(marketplacePath, "marketplace.json"));
14040
+ manifestPath = marketplacePath.endsWith("marketplace.json") ? resolve2(marketplacePath) : resolve2(join4(marketplacePath, "marketplace.json"));
13901
14041
  if (!existsSync4(manifestPath))
13902
14042
  return [];
13903
14043
  } else {
13904
- const cwdManifest = resolve(".claude-plugin", "marketplace.json");
14044
+ const cwdManifest = resolve2(".claude-plugin", "marketplace.json");
13905
14045
  if (existsSync4(cwdManifest))
13906
14046
  manifestPath = cwdManifest;
13907
14047
  }
@@ -14041,7 +14181,7 @@ var init_migrate = __esm(() => {
14041
14181
  });
14042
14182
 
14043
14183
  // ../../packages/core/src/operations/package.ts
14044
- import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync3, statSync as statSync3 } from "fs";
14184
+ import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync3, rmSync as rmSync3, statSync as statSync2 } from "fs";
14045
14185
  import { basename as basename2, dirname as dirname3, join as join5 } from "path";
14046
14186
  import { cwd as cwd3 } from "process";
14047
14187
  function resolveSkillDir(name) {
@@ -14049,7 +14189,7 @@ function resolveSkillDir(name) {
14049
14189
  if (!skillPath) {
14050
14190
  throw Object.assign(new Error(`Skill not found: ${name}`), { code: "ENOENT" });
14051
14191
  }
14052
- const dir = statSync3(skillPath).isDirectory() ? skillPath : dirname3(skillPath);
14192
+ const dir = statSync2(skillPath).isDirectory() ? skillPath : dirname3(skillPath);
14053
14193
  return { dir, name: basename2(dir) };
14054
14194
  }
14055
14195
  function copyDirIfExists(src, dest) {
@@ -14065,6 +14205,9 @@ function copyFileIfExists(src, dest) {
14065
14205
  async function packageSkill(name, opts = {}) {
14066
14206
  const { dir: skillDir, name: skillName } = resolveSkillDir(name);
14067
14207
  const outputDir = join5(opts.output ?? cwd3(), skillName);
14208
+ if (existsSync6(outputDir)) {
14209
+ rmSync3(outputDir, { recursive: true, force: true });
14210
+ }
14068
14211
  mkdirSync3(outputDir, { recursive: true });
14069
14212
  copyFileIfExists(join5(skillDir, "SKILL.md"), join5(outputDir, "SKILL.md"));
14070
14213
  copyDirIfExists(join5(skillDir, "references"), join5(outputDir, "references"));
@@ -14087,7 +14230,7 @@ var init_package = __esm(() => {
14087
14230
 
14088
14231
  // ../../packages/core/src/operations/scaffold.ts
14089
14232
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
14090
- import { homedir as homedir2 } from "os";
14233
+ import { homedir as homedir3 } from "os";
14091
14234
  import { join as join6 } from "path";
14092
14235
  import { cwd as cwd4 } from "process";
14093
14236
  function parseList(value) {
@@ -14127,8 +14270,10 @@ function mergeFrontmatterList(content, key, items) {
14127
14270
  return content.slice(0, fmStart) + newFmBody + content.slice(closePos);
14128
14271
  }
14129
14272
  function resolveTemplate(type, tier) {
14130
- const homeDir = process.env.HOME ?? homedir2();
14273
+ const homeDir = process.env.HOME ?? homedir3();
14131
14274
  const tierName = tier?.trim();
14275
+ if (tierName)
14276
+ assertSafePathSegment(tierName, "template tier");
14132
14277
  if (tierName && tierName !== "default") {
14133
14278
  const userTierPath = join6(homeDir, ".superskill", "templates", type, `${tierName}.md`);
14134
14279
  if (existsSync7(userTierPath)) {
@@ -14231,10 +14376,7 @@ function scoreClarityFromDensities(body) {
14231
14376
  function parseFrontmatterSafe(content) {
14232
14377
  try {
14233
14378
  return parseFrontmatter(content).data;
14234
- } catch (e) {
14235
- if (e instanceof FrontmatterError) {
14236
- return null;
14237
- }
14379
+ } catch {
14238
14380
  return null;
14239
14381
  }
14240
14382
  }
@@ -14348,7 +14490,7 @@ function parseHookEntries(raw) {
14348
14490
  function scoreCorrectness(entries) {
14349
14491
  let valid = 0;
14350
14492
  for (const e of entries) {
14351
- if (e.type === "command" && e.command.length > 0 && e.matcher.length > 0)
14493
+ if ((e.type === "command" || e.type === "prompt") && e.command.length > 0 && e.matcher.length > 0)
14352
14494
  valid++;
14353
14495
  }
14354
14496
  const score = entries.length > 0 ? clamp(valid / entries.length) : 0;
@@ -14358,7 +14500,7 @@ function scoreCorrectness(entries) {
14358
14500
  function scoreEventCoverage(entries) {
14359
14501
  const events = new Set(entries.map((e) => e.event));
14360
14502
  const covered = KNOWN_HOOK_EVENTS.filter((e) => events.has(e)).length;
14361
- const score = clamp(Math.min(events.size / 3, 1));
14503
+ const score = clamp(Math.min(covered / 3, 1));
14362
14504
  const note = `${covered} of ${KNOWN_HOOK_EVENTS.length} known events covered (${events.size} total)`;
14363
14505
  return { score, note };
14364
14506
  }
@@ -14513,7 +14655,7 @@ var init_hook = __esm(() => {
14513
14655
  });
14514
14656
 
14515
14657
  // ../../packages/core/src/operations/validate.ts
14516
- import { existsSync as existsSync8, statSync as statSync4 } from "fs";
14658
+ import { existsSync as existsSync8, statSync as statSync3 } from "fs";
14517
14659
  import { dirname as dirname4, join as join7 } from "path";
14518
14660
  function checkBodyLinks(body, baseDir) {
14519
14661
  const findings = [];
@@ -14551,7 +14693,7 @@ async function validate(type, nameOrPath, opts) {
14551
14693
  }
14552
14694
  let stat;
14553
14695
  try {
14554
- stat = statSync4(resolvedPath);
14696
+ stat = statSync3(resolvedPath);
14555
14697
  } catch {
14556
14698
  return sentinelResult(`File not found: ${resolvedPath}`);
14557
14699
  }
@@ -14573,13 +14715,14 @@ async function validate(type, nameOrPath, opts) {
14573
14715
  const baseDir = dirname4(resolvedPath);
14574
14716
  const result = _validateContent(type, content, {
14575
14717
  ...opts,
14576
- referenceChecker: (refType, refName) => resolveContentPath(refType, refName, { baseDir }) !== null
14718
+ referenceChecker: opts?.referenceChecker ?? ((refType, refName) => resolveContentPath(refType, refName, { baseDir }) !== null)
14577
14719
  });
14578
- const bodyStart = content.indexOf(`
14579
- ---
14580
- `);
14581
- const body = bodyStart >= 0 ? content.slice(bodyStart + 5) : content;
14582
- const linkFindings = checkBodyLinks(body, baseDir);
14720
+ let bodyForLinks = content;
14721
+ try {
14722
+ const { body } = parseFrontmatter(content);
14723
+ bodyForLinks = body;
14724
+ } catch {}
14725
+ const linkFindings = checkBodyLinks(bodyForLinks, baseDir);
14583
14726
  result.findings.push(...linkFindings);
14584
14727
  return result;
14585
14728
  }
@@ -14587,7 +14730,9 @@ function _validateContent(type, content, opts) {
14587
14730
  const findings = [];
14588
14731
  let data;
14589
14732
  let body;
14590
- const frontmatterPresent = /^---\s*$/m.test(content);
14733
+ const frontmatterPresent = content.startsWith(`---
14734
+ `) || content.startsWith(`---\r
14735
+ `);
14591
14736
  try {
14592
14737
  if (frontmatterPresent) {
14593
14738
  const parsed = parseFrontmatter(content);
@@ -14767,7 +14912,12 @@ function strictChecks(type, data, body) {
14767
14912
  message: `Body content is too short (${trimmedBody.length} chars). Recommended minimum is 20 characters.`
14768
14913
  });
14769
14914
  }
14770
- for (const key of Object.keys(data)) {
14915
+ const recognized = new Set([
14916
+ ...Object.keys(FIELD_TYPES[type] ?? {}),
14917
+ ...REQUIRED_FIELDS[type],
14918
+ ...KNOWN_OPTIONAL[type] ?? []
14919
+ ]);
14920
+ for (const [key, value] of Object.entries(data)) {
14771
14921
  const replacement = DEPRECATED_FIELDS[key];
14772
14922
  if (replacement) {
14773
14923
  findings.push({
@@ -14776,31 +14926,20 @@ function strictChecks(type, data, body) {
14776
14926
  message: `'${key}' is deprecated. ${replacement}`
14777
14927
  });
14778
14928
  }
14779
- }
14780
- for (const [field, value] of Object.entries(data)) {
14781
14929
  if (typeof value === "string" && value !== value.trimEnd()) {
14782
14930
  findings.push({
14783
14931
  severity: "warning",
14784
- field,
14785
- message: `'${field}' has trailing whitespace`
14932
+ field: key,
14933
+ message: `'${key}' has trailing whitespace`
14934
+ });
14935
+ }
14936
+ if (!recognized.has(key) && DEPRECATED_FIELDS[key] === undefined) {
14937
+ findings.push({
14938
+ severity: "warning",
14939
+ field: key,
14940
+ message: `Unknown frontmatter key '${key}'`
14786
14941
  });
14787
14942
  }
14788
- }
14789
- const recognized = new Set([
14790
- ...Object.keys(FIELD_TYPES[type] ?? {}),
14791
- ...REQUIRED_FIELDS[type],
14792
- ...KNOWN_OPTIONAL[type] ?? []
14793
- ]);
14794
- for (const key of Object.keys(data)) {
14795
- if (recognized.has(key))
14796
- continue;
14797
- if (DEPRECATED_FIELDS[key] !== undefined)
14798
- continue;
14799
- findings.push({
14800
- severity: "warning",
14801
- field: key,
14802
- message: `Unknown frontmatter key '${key}'`
14803
- });
14804
14943
  }
14805
14944
  return findings;
14806
14945
  }
@@ -17225,8 +17364,12 @@ function getTelemetryConfig(configPartial = {}) {
17225
17364
  function getResolvedConfig() {
17226
17365
  return resolvedConfig;
17227
17366
  }
17228
- var CONFIG_DEFAULTS, resolvedConfig;
17367
+ function getTracer() {
17368
+ return import_api.trace.getTracer(TRACER_NAME, TRACER_VERSION);
17369
+ }
17370
+ var import_api, CONFIG_DEFAULTS, TRACER_NAME = "@gobing-ai/ts-infra", TRACER_VERSION = "0.1.0", resolvedConfig;
17229
17371
  var init_sdk = __esm(() => {
17372
+ import_api = __toESM(require_src(), 1);
17230
17373
  CONFIG_DEFAULTS = {
17231
17374
  enabled: true,
17232
17375
  serviceName: "ts-libs",
@@ -17235,13 +17378,41 @@ var init_sdk = __esm(() => {
17235
17378
  resolvedConfig = getTelemetryConfig();
17236
17379
  });
17237
17380
 
17381
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.3.21+3246782889eb34e0/node_modules/@gobing-ai/ts-infra/dist/telemetry/tracing.js
17382
+ function isSuppressed(tracer) {
17383
+ return tracer === undefined && !getResolvedConfig().enabled;
17384
+ }
17385
+ function nonRecordingSpan() {
17386
+ return import_api2.trace.wrapSpanContext(import_api2.INVALID_SPAN_CONTEXT);
17387
+ }
17388
+ async function traceAsync(name, fn, options2, tracer) {
17389
+ if (isSuppressed(tracer))
17390
+ return fn(nonRecordingSpan());
17391
+ const resolvedTracer = tracer ?? getTracer();
17392
+ return resolvedTracer.startActiveSpan(name, options2 ?? {}, async (span) => {
17393
+ try {
17394
+ return await fn(span);
17395
+ } catch (err) {
17396
+ span.setStatus({ code: 2, message: err instanceof Error ? err.message : String(err) });
17397
+ throw err;
17398
+ } finally {
17399
+ span.end();
17400
+ }
17401
+ });
17402
+ }
17403
+ var import_api2;
17404
+ var init_tracing = __esm(() => {
17405
+ init_sdk();
17406
+ import_api2 = __toESM(require_src(), 1);
17407
+ });
17408
+
17238
17409
  // ../../node_modules/.bun/@gobing-ai+ts-infra@0.3.21+3246782889eb34e0/node_modules/@gobing-ai/ts-infra/dist/telemetry/metrics.js
17239
17410
  function getMeter() {
17240
- return import_api.metrics.getMeter(METER_NAME, METER_VERSION);
17411
+ return import_api3.metrics.getMeter(METER_NAME, METER_VERSION);
17241
17412
  }
17242
17413
  function noopCounter() {
17243
17414
  if (!_noopCounter)
17244
- _noopCounter = import_api.createNoopMeter().createCounter("noop");
17415
+ _noopCounter = import_api3.createNoopMeter().createCounter("noop");
17245
17416
  return _noopCounter;
17246
17417
  }
17247
17418
  function getOrCreateCounter(key, name, description, unit = "{operation}") {
@@ -17258,10 +17429,10 @@ function getEventbusEmitsTotal() {
17258
17429
  function getEventbusErrorsTotal() {
17259
17430
  return getOrCreateCounter("ebErr", "eventbus.errors.total", "Event bus errors", "{error}");
17260
17431
  }
17261
- var import_api, METER_NAME = "@gobing-ai/ts-infra", METER_VERSION = "0.1.0", instruments, _noopCounter;
17432
+ var import_api3, METER_NAME = "@gobing-ai/ts-infra", METER_VERSION = "0.1.0", instruments, _noopCounter;
17262
17433
  var init_metrics = __esm(() => {
17263
17434
  init_sdk();
17264
- import_api = __toESM(require_src(), 1);
17435
+ import_api3 = __toESM(require_src(), 1);
17265
17436
  instruments = {};
17266
17437
  });
17267
17438
 
@@ -17515,10 +17686,16 @@ var init_event_bus2 = __esm(() => {
17515
17686
  init_event_bus();
17516
17687
  });
17517
17688
 
17689
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.3.21+3246782889eb34e0/node_modules/@gobing-ai/ts-infra/dist/telemetry/index.js
17690
+ var init_telemetry = __esm(() => {
17691
+ init_tracing();
17692
+ });
17693
+
17518
17694
  // ../../node_modules/.bun/@gobing-ai+ts-infra@0.3.21+3246782889eb34e0/node_modules/@gobing-ai/ts-infra/dist/index.js
17519
17695
  var init_dist3 = __esm(() => {
17520
17696
  init_event_bus2();
17521
17697
  init_logger2();
17698
+ init_telemetry();
17522
17699
  });
17523
17700
 
17524
17701
  // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.3.21+5a4f8cc6c6b198a4/node_modules/@gobing-ai/ts-ai-runner/dist/agents/shims.js
@@ -32451,7 +32628,7 @@ var init_config = __esm(() => {
32451
32628
  });
32452
32629
 
32453
32630
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.3.21/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
32454
- import { appendFileSync, cpSync as cpSync2, createWriteStream, existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync6, renameSync, rmSync as rmSync2, statSync as statSync5, writeFileSync as writeFileSync4 } from "fs";
32631
+ import { appendFileSync, cpSync as cpSync2, createWriteStream, existsSync as existsSync9, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync6, renameSync, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
32455
32632
  import { dirname as dirname5, resolve as resolvePath } from "path";
32456
32633
  function createNodeFileSystem(root) {
32457
32634
  const projectRoot = root ?? findProjectRoot(process.cwd());
@@ -32473,7 +32650,7 @@ function createNodeFileSystem(root) {
32473
32650
  },
32474
32651
  readDir: (path) => readdirSync3(path),
32475
32652
  deleteFile: (path) => {
32476
- rmSync2(path, { recursive: true, force: true });
32653
+ rmSync4(path, { recursive: true, force: true });
32477
32654
  },
32478
32655
  rename: (src, dest) => {
32479
32656
  renameSync(src, dest);
@@ -32487,7 +32664,7 @@ function createNodeFileSystem(root) {
32487
32664
  },
32488
32665
  stat: (path) => {
32489
32666
  try {
32490
- const s = statSync5(path);
32667
+ const s = statSync4(path);
32491
32668
  return {
32492
32669
  isFile: () => s.isFile(),
32493
32670
  isDirectory: () => s.isDirectory(),
@@ -33453,12 +33630,12 @@ var require_isexe = __commonJS((exports, module) => {
33453
33630
  if (typeof Promise !== "function") {
33454
33631
  throw new TypeError("callback not provided");
33455
33632
  }
33456
- return new Promise(function(resolve2, reject) {
33633
+ return new Promise(function(resolve3, reject) {
33457
33634
  isexe(path, options2 || {}, function(er, is) {
33458
33635
  if (er) {
33459
33636
  reject(er);
33460
33637
  } else {
33461
- resolve2(is);
33638
+ resolve3(is);
33462
33639
  }
33463
33640
  });
33464
33641
  });
@@ -33520,27 +33697,27 @@ var require_which = __commonJS((exports, module) => {
33520
33697
  opt = {};
33521
33698
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
33522
33699
  const found = [];
33523
- const step = (i) => new Promise((resolve2, reject) => {
33700
+ const step = (i) => new Promise((resolve3, reject) => {
33524
33701
  if (i === pathEnv.length)
33525
- return opt.all && found.length ? resolve2(found) : reject(getNotFoundError(cmd));
33702
+ return opt.all && found.length ? resolve3(found) : reject(getNotFoundError(cmd));
33526
33703
  const ppRaw = pathEnv[i];
33527
33704
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
33528
33705
  const pCmd = path.join(pathPart, cmd);
33529
33706
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
33530
- resolve2(subStep(p, i, 0));
33707
+ resolve3(subStep(p, i, 0));
33531
33708
  });
33532
- const subStep = (p, i, ii) => new Promise((resolve2, reject) => {
33709
+ const subStep = (p, i, ii) => new Promise((resolve3, reject) => {
33533
33710
  if (ii === pathExt.length)
33534
- return resolve2(step(i + 1));
33711
+ return resolve3(step(i + 1));
33535
33712
  const ext = pathExt[ii];
33536
33713
  isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
33537
33714
  if (!er && is) {
33538
33715
  if (opt.all)
33539
33716
  found.push(p + ext);
33540
33717
  else
33541
- return resolve2(p + ext);
33718
+ return resolve3(p + ext);
33542
33719
  }
33543
- return resolve2(subStep(p, i, ii + 1));
33720
+ return resolve3(subStep(p, i, ii + 1));
33544
33721
  });
33545
33722
  });
33546
33723
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -34346,7 +34523,7 @@ var normalizeForceKillAfterDelay = (forceKillAfterDelay) => {
34346
34523
  throw new TypeError(`Expected the \`forceKillAfterDelay\` option to be a non-negative integer, got \`${forceKillAfterDelay}\` (${typeof forceKillAfterDelay})`);
34347
34524
  }
34348
34525
  return forceKillAfterDelay;
34349
- }, DEFAULT_FORCE_KILL_TIMEOUT, subprocessKill = ({ kill, options: { forceKillAfterDelay, killSignal }, onInternalError, context, controller }, signalOrError, errorArgument) => {
34526
+ }, DEFAULT_FORCE_KILL_TIMEOUT, subprocessKill = ({ kill, options: { forceKillAfterDelay, killSignal }, onInternalError, context: context2, controller }, signalOrError, errorArgument) => {
34350
34527
  const { signal, error: error51 } = parseKillArguments(signalOrError, errorArgument, killSignal);
34351
34528
  emitKillError(error51, onInternalError);
34352
34529
  const killResult = kill(signal);
@@ -34356,7 +34533,7 @@ var normalizeForceKillAfterDelay = (forceKillAfterDelay) => {
34356
34533
  forceKillAfterDelay,
34357
34534
  killSignal,
34358
34535
  killResult,
34359
- context,
34536
+ context: context2,
34360
34537
  controller
34361
34538
  });
34362
34539
  return killResult;
@@ -34373,23 +34550,23 @@ var normalizeForceKillAfterDelay = (forceKillAfterDelay) => {
34373
34550
  if (error51 !== undefined) {
34374
34551
  onInternalError.reject(error51);
34375
34552
  }
34376
- }, setKillTimeout = async ({ kill, signal, forceKillAfterDelay, killSignal, killResult, context, controller }) => {
34553
+ }, setKillTimeout = async ({ kill, signal, forceKillAfterDelay, killSignal, killResult, context: context2, controller }) => {
34377
34554
  if (signal === killSignal && killResult) {
34378
34555
  killOnTimeout({
34379
34556
  kill,
34380
34557
  forceKillAfterDelay,
34381
- context,
34558
+ context: context2,
34382
34559
  controllerSignal: controller.signal
34383
34560
  });
34384
34561
  }
34385
- }, killOnTimeout = async ({ kill, forceKillAfterDelay, context, controllerSignal }) => {
34562
+ }, killOnTimeout = async ({ kill, forceKillAfterDelay, context: context2, controllerSignal }) => {
34386
34563
  if (forceKillAfterDelay === false) {
34387
34564
  return;
34388
34565
  }
34389
34566
  try {
34390
34567
  await setTimeout2(forceKillAfterDelay, undefined, { signal: controllerSignal });
34391
34568
  if (kill("SIGKILL")) {
34392
- context.isForcefullyTerminated ??= true;
34569
+ context2.isForcefullyTerminated ??= true;
34393
34570
  }
34394
34571
  } catch {}
34395
34572
  };
@@ -34413,9 +34590,9 @@ var validateCancelSignal = ({ cancelSignal }) => {
34413
34590
  if (cancelSignal !== undefined && Object.prototype.toString.call(cancelSignal) !== "[object AbortSignal]") {
34414
34591
  throw new Error(`The \`cancelSignal\` option must be an AbortSignal: ${String(cancelSignal)}`);
34415
34592
  }
34416
- }, throwOnCancel = ({ subprocess, cancelSignal, gracefulCancel, context, controller }) => cancelSignal === undefined || gracefulCancel ? [] : [terminateOnCancel(subprocess, cancelSignal, context, controller)], terminateOnCancel = async (subprocess, cancelSignal, context, { signal }) => {
34593
+ }, throwOnCancel = ({ subprocess, cancelSignal, gracefulCancel, context: context2, controller }) => cancelSignal === undefined || gracefulCancel ? [] : [terminateOnCancel(subprocess, cancelSignal, context2, controller)], terminateOnCancel = async (subprocess, cancelSignal, context2, { signal }) => {
34417
34594
  await onAbortedSignal(cancelSignal, signal);
34418
- context.terminationReason ??= "cancel";
34595
+ context2.terminationReason ??= "cancel";
34419
34596
  subprocess.kill();
34420
34597
  throw cancelSignal.reason;
34421
34598
  };
@@ -34479,8 +34656,8 @@ var init_validation = __esm(() => {
34479
34656
  // ../../node_modules/.bun/execa@9.6.1/node_modules/execa/lib/utils/deferred.js
34480
34657
  var createDeferred = () => {
34481
34658
  const methods = {};
34482
- const promise2 = new Promise((resolve2, reject) => {
34483
- Object.assign(methods, { resolve: resolve2, reject });
34659
+ const promise2 = new Promise((resolve3, reject) => {
34660
+ Object.assign(methods, { resolve: resolve3, reject });
34484
34661
  });
34485
34662
  return Object.assign(promise2, methods);
34486
34663
  };
@@ -34940,25 +35117,25 @@ var validateGracefulCancel = ({ gracefulCancel, cancelSignal, ipc, serialization
34940
35117
  cancelSignal,
34941
35118
  gracefulCancel,
34942
35119
  forceKillAfterDelay,
34943
- context,
35120
+ context: context2,
34944
35121
  controller
34945
35122
  }) => gracefulCancel ? [sendOnAbort({
34946
35123
  subprocess,
34947
35124
  cancelSignal,
34948
35125
  forceKillAfterDelay,
34949
- context,
35126
+ context: context2,
34950
35127
  controller
34951
- })] : [], sendOnAbort = async ({ subprocess, cancelSignal, forceKillAfterDelay, context, controller: { signal } }) => {
35128
+ })] : [], sendOnAbort = async ({ subprocess, cancelSignal, forceKillAfterDelay, context: context2, controller: { signal } }) => {
34952
35129
  await onAbortedSignal(cancelSignal, signal);
34953
35130
  const reason = getReason(cancelSignal);
34954
35131
  await sendAbort(subprocess, reason);
34955
35132
  killOnTimeout({
34956
35133
  kill: subprocess.kill,
34957
35134
  forceKillAfterDelay,
34958
- context,
35135
+ context: context2,
34959
35136
  controllerSignal: signal
34960
35137
  });
34961
- context.terminationReason ??= "gracefulCancel";
35138
+ context2.terminationReason ??= "gracefulCancel";
34962
35139
  throw cancelSignal.reason;
34963
35140
  }, getReason = ({ reason }) => {
34964
35141
  if (!(reason instanceof DOMException)) {
@@ -34985,9 +35162,9 @@ var validateTimeout = ({ timeout }) => {
34985
35162
  if (timeout !== undefined && (!Number.isFinite(timeout) || timeout < 0)) {
34986
35163
  throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`);
34987
35164
  }
34988
- }, throwOnTimeout = (subprocess, timeout, context, controller) => timeout === 0 || timeout === undefined ? [] : [killAfterTimeout(subprocess, timeout, context, controller)], killAfterTimeout = async (subprocess, timeout, context, { signal }) => {
35165
+ }, throwOnTimeout = (subprocess, timeout, context2, controller) => timeout === 0 || timeout === undefined ? [] : [killAfterTimeout(subprocess, timeout, context2, controller)], killAfterTimeout = async (subprocess, timeout, context2, { signal }) => {
34989
35166
  await setTimeout3(timeout, undefined, { signal });
34990
- context.terminationReason ??= "timeout";
35167
+ context2.terminationReason ??= "timeout";
34991
35168
  subprocess.kill();
34992
35169
  throw new DiscardedError;
34993
35170
  };
@@ -35115,7 +35292,7 @@ var init_encoding_option = __esm(() => {
35115
35292
  });
35116
35293
 
35117
35294
  // ../../node_modules/.bun/execa@9.6.1/node_modules/execa/lib/arguments/cwd.js
35118
- import { statSync as statSync6 } from "fs";
35295
+ import { statSync as statSync5 } from "fs";
35119
35296
  import path4 from "path";
35120
35297
  import process6 from "process";
35121
35298
  var normalizeCwd = (cwd5 = getDefaultCwd()) => {
@@ -35135,7 +35312,7 @@ ${error51.message}`;
35135
35312
  }
35136
35313
  let cwdStat;
35137
35314
  try {
35138
- cwdStat = statSync6(cwd5);
35315
+ cwdStat = statSync5(cwd5);
35139
35316
  } catch (error51) {
35140
35317
  return `The "cwd" option is invalid: ${cwd5}.
35141
35318
  ${error51.message}
@@ -37344,9 +37521,9 @@ var init_all_sync = __esm(() => {
37344
37521
 
37345
37522
  // ../../node_modules/.bun/execa@9.6.1/node_modules/execa/lib/resolve/exit-async.js
37346
37523
  import { once as once4 } from "events";
37347
- var waitForExit = async (subprocess, context) => {
37524
+ var waitForExit = async (subprocess, context2) => {
37348
37525
  const [exitCode, signal] = await waitForExitOrError(subprocess);
37349
- context.isForcefullyTerminated ??= false;
37526
+ context2.isForcefullyTerminated ??= false;
37350
37527
  return [exitCode, signal];
37351
37528
  }, waitForExitOrError = async (subprocess) => {
37352
37529
  const [spawnPayload, exitPayload] = await Promise.allSettled([
@@ -38955,14 +39132,14 @@ var waitForSubprocessResult = async ({
38955
39132
  ipc,
38956
39133
  ipcInput
38957
39134
  },
38958
- context,
39135
+ context: context2,
38959
39136
  verboseInfo,
38960
39137
  fileDescriptors,
38961
39138
  originalStreams,
38962
39139
  onInternalError,
38963
39140
  controller
38964
39141
  }) => {
38965
- const exitPromise = waitForExit(subprocess, context);
39142
+ const exitPromise = waitForExit(subprocess, context2);
38966
39143
  const streamInfo = {
38967
39144
  originalStreams,
38968
39145
  fileDescriptors,
@@ -39015,12 +39192,12 @@ var waitForSubprocessResult = async ({
39015
39192
  ]),
39016
39193
  onInternalError,
39017
39194
  throwOnSubprocessError(subprocess, controller),
39018
- ...throwOnTimeout(subprocess, timeout, context, controller),
39195
+ ...throwOnTimeout(subprocess, timeout, context2, controller),
39019
39196
  ...throwOnCancel({
39020
39197
  subprocess,
39021
39198
  cancelSignal,
39022
39199
  gracefulCancel,
39023
- context,
39200
+ context: context2,
39024
39201
  controller
39025
39202
  }),
39026
39203
  ...throwOnGracefulCancel({
@@ -39028,12 +39205,12 @@ var waitForSubprocessResult = async ({
39028
39205
  cancelSignal,
39029
39206
  gracefulCancel,
39030
39207
  forceKillAfterDelay,
39031
- context,
39208
+ context: context2,
39032
39209
  controller
39033
39210
  })
39034
39211
  ]);
39035
39212
  } catch (error51) {
39036
- context.terminationReason ??= "other";
39213
+ context2.terminationReason ??= "other";
39037
39214
  return Promise.all([
39038
39215
  { error: error51 },
39039
39216
  exitPromise,
@@ -39079,10 +39256,10 @@ var initializeConcurrentStreams = () => ({
39079
39256
  const promises = weakMap.get(stream);
39080
39257
  const promise2 = createDeferred();
39081
39258
  promises.push(promise2);
39082
- const resolve2 = promise2.resolve.bind(promise2);
39083
- return { resolve: resolve2, promises };
39084
- }, waitForConcurrentStreams = async ({ resolve: resolve2, promises }, subprocess) => {
39085
- resolve2();
39259
+ const resolve3 = promise2.resolve.bind(promise2);
39260
+ return { resolve: resolve3, promises };
39261
+ }, waitForConcurrentStreams = async ({ resolve: resolve3, promises }, subprocess) => {
39262
+ resolve3();
39086
39263
  const [isSubprocessExit] = await Promise.race([
39087
39264
  Promise.allSettled([true, subprocess]),
39088
39265
  Promise.all([false, ...promises])
@@ -39464,13 +39641,13 @@ var execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => {
39464
39641
  const originalStreams = [...subprocess.stdio];
39465
39642
  pipeOutputAsync(subprocess, fileDescriptors, controller);
39466
39643
  cleanupOnExit(subprocess, options2, controller);
39467
- const context = {};
39644
+ const context2 = {};
39468
39645
  const onInternalError = createDeferred();
39469
39646
  subprocess.kill = subprocessKill.bind(undefined, {
39470
39647
  kill: subprocess.kill.bind(subprocess),
39471
39648
  options: options2,
39472
39649
  onInternalError,
39473
- context,
39650
+ context: context2,
39474
39651
  controller
39475
39652
  });
39476
39653
  subprocess.all = makeAllStream(subprocess, options2);
@@ -39485,12 +39662,12 @@ var execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => {
39485
39662
  originalStreams,
39486
39663
  command,
39487
39664
  escapedCommand,
39488
- context,
39665
+ context: context2,
39489
39666
  onInternalError,
39490
39667
  controller
39491
39668
  });
39492
39669
  return { subprocess, promise: promise2 };
39493
- }, handlePromise = async ({ subprocess, options: options2, startTime, verboseInfo, fileDescriptors, originalStreams, command, escapedCommand, context, onInternalError, controller }) => {
39670
+ }, handlePromise = async ({ subprocess, options: options2, startTime, verboseInfo, fileDescriptors, originalStreams, command, escapedCommand, context: context2, onInternalError, controller }) => {
39494
39671
  const [
39495
39672
  errorInfo,
39496
39673
  [exitCode, signal],
@@ -39500,7 +39677,7 @@ var execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => {
39500
39677
  ] = await waitForSubprocessResult({
39501
39678
  subprocess,
39502
39679
  options: options2,
39503
- context,
39680
+ context: context2,
39504
39681
  verboseInfo,
39505
39682
  fileDescriptors,
39506
39683
  originalStreams,
@@ -39518,22 +39695,22 @@ var execaCoreAsync = (rawFile, rawArguments, rawOptions, createNested) => {
39518
39695
  stdio,
39519
39696
  all,
39520
39697
  ipcOutput,
39521
- context,
39698
+ context: context2,
39522
39699
  options: options2,
39523
39700
  command,
39524
39701
  escapedCommand,
39525
39702
  startTime
39526
39703
  });
39527
39704
  return handleResult2(result, verboseInfo, options2);
39528
- }, getAsyncResult = ({ errorInfo, exitCode, signal, stdio, all, ipcOutput, context, options: options2, command, escapedCommand, startTime }) => ("error" in errorInfo) ? makeError({
39705
+ }, getAsyncResult = ({ errorInfo, exitCode, signal, stdio, all, ipcOutput, context: context2, options: options2, command, escapedCommand, startTime }) => ("error" in errorInfo) ? makeError({
39529
39706
  error: errorInfo.error,
39530
39707
  command,
39531
39708
  escapedCommand,
39532
- timedOut: context.terminationReason === "timeout",
39533
- isCanceled: context.terminationReason === "cancel" || context.terminationReason === "gracefulCancel",
39534
- isGracefullyCanceled: context.terminationReason === "gracefulCancel",
39709
+ timedOut: context2.terminationReason === "timeout",
39710
+ isCanceled: context2.terminationReason === "cancel" || context2.terminationReason === "gracefulCancel",
39711
+ isGracefullyCanceled: context2.terminationReason === "gracefulCancel",
39535
39712
  isMaxBuffer: errorInfo.error instanceof MaxBufferError,
39536
- isForcefullyTerminated: context.isForcefullyTerminated,
39713
+ isForcefullyTerminated: context2.isForcefullyTerminated,
39537
39714
  exitCode,
39538
39715
  signal,
39539
39716
  stdio,
@@ -39838,18 +40015,18 @@ class ObservedPipeProcess {
39838
40015
  inner;
39839
40016
  killedWith;
39840
40017
  exited;
39841
- constructor(inner, events, context) {
40018
+ constructor(inner, events, context2) {
39842
40019
  this.inner = inner;
39843
40020
  this.exited = inner.exited.then((exitCode) => {
39844
40021
  events?.emit("process.exited", {
39845
- command: context.command,
39846
- args: context.args,
40022
+ command: context2.command,
40023
+ args: context2.args,
39847
40024
  exitCode,
39848
40025
  ...this.killedWith !== undefined ? { signal: String(this.killedWith) } : {},
39849
- durationMs: Date.now() - context.startedAt,
40026
+ durationMs: Date.now() - context2.startedAt,
39850
40027
  reason: this.killedWith !== undefined ? "signal" : "exit",
39851
40028
  timestamp: new Date().toISOString(),
39852
- ...context.label !== undefined ? { label: context.label } : {}
40029
+ ...context2.label !== undefined ? { label: context2.label } : {}
39853
40030
  });
39854
40031
  return exitCode;
39855
40032
  });
@@ -39936,8 +40113,11 @@ function isTimedOut(error51) {
39936
40113
  function errorMessage(error51) {
39937
40114
  return error51 instanceof Error ? error51.message : String(error51);
39938
40115
  }
40116
+ var NodeProcessExecutor;
39939
40117
  var init_process_executor = __esm(() => {
39940
40118
  init_execa();
40119
+ NodeProcessExecutor = class NodeProcessExecutor extends ProcessExecutor {
40120
+ };
39941
40121
  });
39942
40122
 
39943
40123
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.3.21/node_modules/@gobing-ai/ts-runtime/dist/context.js
@@ -40094,6 +40274,7 @@ var init_types3 = () => {};
40094
40274
  var init_dist4 = __esm(() => {
40095
40275
  init_file_system_node();
40096
40276
  init_process_executor();
40277
+ init_process_executor();
40097
40278
  init_config();
40098
40279
  init_context2();
40099
40280
  init_path();
@@ -40169,19 +40350,101 @@ var init_slash_command = __esm(() => {
40169
40350
  });
40170
40351
 
40171
40352
  // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.3.21+5a4f8cc6c6b198a4/node_modules/@gobing-ai/ts-ai-runner/dist/ai-runner.js
40353
+ class AiRunner {
40354
+ processExecutor;
40355
+ defaultCwd;
40356
+ defaultTimeout;
40357
+ logger;
40358
+ events;
40359
+ constructor(options2 = {}) {
40360
+ this.processExecutor = options2.processExecutor ?? new NodeProcessExecutor({
40361
+ ...options2.processEvents !== undefined ? {
40362
+ events: {
40363
+ emit: (event, detail) => {
40364
+ options2.processEvents?.emit(event, detail);
40365
+ }
40366
+ }
40367
+ } : {},
40368
+ tracer: options2.tracer ?? {
40369
+ traceAsync: async (name, fn) => await traceAsync(name, (span) => fn(span))
40370
+ }
40371
+ });
40372
+ this.defaultCwd = options2.defaultCwd;
40373
+ this.defaultTimeout = options2.defaultTimeout;
40374
+ this.logger = options2.logger ?? getLogger2("ai-runner");
40375
+ this.events = options2.events;
40376
+ }
40377
+ runHelpCommand(agent, options2 = {}) {
40378
+ return this.invoke(agent, "help", getAgentShim(agent).getHelpCommand(), options2, true);
40379
+ }
40380
+ runVersionCommand(agent, options2 = {}) {
40381
+ return this.invoke(agent, "version", getAgentShim(agent).getVersionCommand(), options2, true);
40382
+ }
40383
+ runPromptCommand(agent, promptOptions, options2 = {}) {
40384
+ return this.invoke(agent, "prompt", this.buildPromptCommand(agent, promptOptions, options2), options2, false);
40385
+ }
40386
+ runSlashCommand(agent, input, promptOptions, options2 = {}) {
40387
+ return this.runPromptCommand(agent, { ...promptOptions, input: translateSlashCommand(agent, input) }, options2);
40388
+ }
40389
+ buildPromptCommand(agent, promptOptions, options2 = {}) {
40390
+ return buildAgentCommand(agent, promptOptions, {
40391
+ workspace: options2.cwd ?? this.defaultCwd ?? getProcessCwd()
40392
+ });
40393
+ }
40394
+ runAuthCommand(agent, options2 = {}) {
40395
+ const command = getAgentShim(agent).getAuthCommand();
40396
+ return command === null ? null : this.invoke(agent, "auth", command, options2, true);
40397
+ }
40398
+ async invoke(agent, operation, command, options2, forceBuffered) {
40399
+ const label = `ai-runner.${agent}.${operation}`;
40400
+ this.logger.debug("invoke", { label, command: command.command, args: command.args.join(" ") });
40401
+ this.events?.emit("agent.invoke.start", { agent, operation, label });
40402
+ const result = await this.processExecutor.run({
40403
+ command: command.command,
40404
+ args: command.args,
40405
+ label,
40406
+ rejectOnError: false,
40407
+ forceBuffered,
40408
+ cwd: options2.cwd ?? this.defaultCwd,
40409
+ timeout: options2.timeout ?? this.defaultTimeout
40410
+ });
40411
+ if (result.exitCode !== 0) {
40412
+ this.logger.error("invoke exited non-zero", {
40413
+ label,
40414
+ exitCode: result.exitCode,
40415
+ signal: result.signal
40416
+ });
40417
+ }
40418
+ this.events?.emit("agent.invoke.exit", {
40419
+ agent,
40420
+ operation,
40421
+ label,
40422
+ exitCode: result.exitCode,
40423
+ ...result.signal !== undefined ? { signal: result.signal } : {},
40424
+ durationMs: result.durationMs
40425
+ });
40426
+ return {
40427
+ exitCode: result.exitCode,
40428
+ stdout: result.stdout,
40429
+ stderr: result.stderr,
40430
+ ...result.signal !== undefined ? { signal: result.signal } : {},
40431
+ durationMs: result.durationMs
40432
+ };
40433
+ }
40434
+ }
40172
40435
  function hasIdentityOptions(options2) {
40173
40436
  return options2.purpose !== undefined || options2.systemPrompt !== undefined || options2.taskId !== undefined || options2.peers !== undefined && options2.peers.length > 0;
40174
40437
  }
40175
- function buildAgentCommand(agent, promptOptions, context2) {
40176
- return getAgentShim(agent).getPromptCommand(applyIdentityPreamble(agent, promptOptions, context2));
40438
+ function buildAgentCommand(agent, promptOptions, context3) {
40439
+ return getAgentShim(agent).getPromptCommand(applyIdentityPreamble(agent, promptOptions, context3));
40177
40440
  }
40178
- function applyIdentityPreamble(agent, promptOptions, context2) {
40441
+ function applyIdentityPreamble(agent, promptOptions, context3) {
40179
40442
  if (!hasIdentityOptions(promptOptions))
40180
40443
  return promptOptions;
40181
40444
  const preamble = buildIdentityPreamble({
40182
40445
  agentId: agent,
40183
40446
  agentType: agent,
40184
- workspace: context2.workspace,
40447
+ workspace: context3.workspace,
40185
40448
  purpose: promptOptions.purpose,
40186
40449
  systemPrompt: promptOptions.systemPrompt,
40187
40450
  taskId: promptOptions.taskId,
@@ -40192,8 +40455,11 @@ ${promptOptions.input}`;
40192
40455
  return { ...promptOptions, input };
40193
40456
  }
40194
40457
  var init_ai_runner = __esm(() => {
40458
+ init_dist3();
40459
+ init_dist4();
40195
40460
  init_shims();
40196
40461
  init_identity2();
40462
+ init_slash_command();
40197
40463
  });
40198
40464
 
40199
40465
  // ../../node_modules/.bun/@gobing-ai+ts-ai-runner@0.3.21+5a4f8cc6c6b198a4/node_modules/@gobing-ai/ts-ai-runner/dist/agent-detector.js
@@ -40344,8 +40610,8 @@ class TeamAgentProcess {
40344
40610
  this.warn("stdin close failed", "stop.endStdin", error51);
40345
40611
  }
40346
40612
  process11.kill("SIGTERM");
40347
- const timeout = new Promise((resolve2) => {
40348
- setTimeout(() => resolve2("timeout"), 5000);
40613
+ const timeout = new Promise((resolve3) => {
40614
+ setTimeout(() => resolve3("timeout"), 5000);
40349
40615
  });
40350
40616
  const result = await Promise.race([process11.exited, timeout]);
40351
40617
  if (result === "timeout") {
@@ -40577,14 +40843,14 @@ var init_targets = __esm(() => {
40577
40843
  ];
40578
40844
  TARGET_TO_RULESYNC = {
40579
40845
  codex: "codexcli",
40580
- pi: "pi",
40846
+ pi: "codexcli",
40581
40847
  opencode: "opencode",
40582
- "antigravity-cli": "antigravity-cli",
40583
- "antigravity-ide": "antigravity-ide"
40848
+ "antigravity-cli": "codexcli",
40849
+ "antigravity-ide": "codexcli"
40584
40850
  };
40585
40851
  TARGET_SKILLS_RELDIR = {
40586
40852
  codex: ".agents/skills",
40587
- pi: ".pi/skills",
40853
+ pi: ".agents/skills",
40588
40854
  opencode: ".opencode/skills",
40589
40855
  "antigravity-cli": ".agents/skills",
40590
40856
  "antigravity-ide": ".agents/skills"
@@ -40701,7 +40967,7 @@ function scoreSkillLinkage(body) {
40701
40967
  function scoreModelFit(data) {
40702
40968
  const model = data.model;
40703
40969
  const recognizedAliases = { inherit: true, sonnet: true, opus: true, haiku: true };
40704
- const wellFormedPattern = /^claude-(sonnet|opus|haiku)-/i;
40970
+ const wellFormedPattern = /^claude-(\d+-\d+-)?(sonnet|opus|haiku)-/i;
40705
40971
  let score;
40706
40972
  let note;
40707
40973
  if (typeof model === "string") {
@@ -40892,6 +41158,127 @@ var init_command3 = __esm(() => {
40892
41158
  init_types2();
40893
41159
  });
40894
41160
 
41161
+ // ../../packages/core/src/quality/eval-cases.ts
41162
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
41163
+ import { join as join8 } from "path";
41164
+ function isRuleJudge(value) {
41165
+ return typeof value === "object" && value !== null && "checks" in value && Array.isArray(value.checks);
41166
+ }
41167
+ function isRubricRef(value) {
41168
+ return typeof value === "object" && value !== null && "criterion" in value && typeof value.criterion === "string" && !("checks" in value);
41169
+ }
41170
+ function resolveEvalCasesPath(name, opts) {
41171
+ if (opts?.path) {
41172
+ if (!existsSync10(opts.path))
41173
+ return null;
41174
+ return opts.path;
41175
+ }
41176
+ assertSafePathSegment(name, "eval cases skill name");
41177
+ const coLocated = join8(process.cwd(), "skills", name, "eval", "cases.yaml");
41178
+ if (existsSync10(coLocated))
41179
+ return coLocated;
41180
+ return null;
41181
+ }
41182
+ function loadEvalCases(name, opts) {
41183
+ const resolvedPath = resolveEvalCasesPath(name, opts);
41184
+ if (!resolvedPath)
41185
+ return null;
41186
+ const raw = readFileSync9(resolvedPath, "utf-8");
41187
+ let parsed;
41188
+ try {
41189
+ parsed = $parse(raw);
41190
+ } catch (e) {
41191
+ throw new EvalCaseError(resolvedPath, null, `Failed to parse YAML: ${e instanceof Error ? e.message : String(e)}`);
41192
+ }
41193
+ const result = EvalCaseSetSchema.safeParse(parsed);
41194
+ if (!result.success) {
41195
+ const issue2 = result.error.issues[0];
41196
+ if (!issue2) {
41197
+ throw new EvalCaseError(resolvedPath, null, "Schema validation failed with no issue reported.");
41198
+ }
41199
+ const caseId = extractCaseIdFromPath(issue2.path, parsed);
41200
+ const field = issue2.path.length > 0 ? issue2.path.join(".") : "root";
41201
+ throw new EvalCaseError(resolvedPath, caseId, `Schema validation failed at "${field}": ${issue2.message}`);
41202
+ }
41203
+ const caseSet = result.data;
41204
+ const seen = new Set;
41205
+ for (const c3 of caseSet.cases) {
41206
+ if (seen.has(c3.id)) {
41207
+ throw new EvalCaseError(resolvedPath, c3.id, `Duplicate case id "${c3.id}"`);
41208
+ }
41209
+ seen.add(c3.id);
41210
+ }
41211
+ return caseSet;
41212
+ }
41213
+ function extractCaseIdFromPath(path7, parsed) {
41214
+ const casesIdx = path7.indexOf("cases");
41215
+ if (casesIdx >= 0 && path7.length > casesIdx + 1 && typeof path7[casesIdx + 1] === "number") {
41216
+ const caseIndex = path7[casesIdx + 1];
41217
+ if (typeof parsed === "object" && parsed !== null && "cases" in parsed && Array.isArray(parsed.cases)) {
41218
+ const candidate = parsed.cases[caseIndex];
41219
+ if (typeof candidate === "object" && candidate !== null && "id" in candidate && typeof candidate.id === "string") {
41220
+ return candidate.id;
41221
+ }
41222
+ }
41223
+ return `cases[${caseIndex}]`;
41224
+ }
41225
+ return null;
41226
+ }
41227
+ var RuleCheckSchema, RubricRefSchema, RuleJudgeSchema, EvalCaseSchema, EvalCaseSetSchema, EvalCaseError;
41228
+ var init_eval_cases = __esm(() => {
41229
+ init_dist2();
41230
+ init_zod();
41231
+ init_identity();
41232
+ RuleCheckSchema = exports_external.object({
41233
+ op: exports_external.enum(["contains", "regex", "equals", "not_contains", "tool_called"]),
41234
+ arg: exports_external.string().min(1)
41235
+ });
41236
+ RubricRefSchema = exports_external.object({
41237
+ criterion: exports_external.string().min(1),
41238
+ excellent: exports_external.string().optional(),
41239
+ poor: exports_external.string().optional()
41240
+ });
41241
+ RuleJudgeSchema = exports_external.object({
41242
+ checks: exports_external.array(RuleCheckSchema).min(1)
41243
+ });
41244
+ EvalCaseSchema = exports_external.object({
41245
+ id: exports_external.string().min(1),
41246
+ split: exports_external.enum(["train", "holdout"]),
41247
+ prompt: exports_external.string().min(1),
41248
+ reference_kind: exports_external.enum(["exact", "rule", "rubric"]),
41249
+ reference: exports_external.union([exports_external.string().min(1), RuleJudgeSchema, RubricRefSchema]),
41250
+ tags: exports_external.array(exports_external.string().min(1)).optional()
41251
+ }).refine((c3) => {
41252
+ if (c3.reference_kind === "exact" && typeof c3.reference !== "string") {
41253
+ return false;
41254
+ }
41255
+ if (c3.reference_kind === "rule" && !isRuleJudge(c3.reference)) {
41256
+ return false;
41257
+ }
41258
+ if (c3.reference_kind === "rubric" && !isRubricRef(c3.reference)) {
41259
+ return false;
41260
+ }
41261
+ return true;
41262
+ }, {
41263
+ message: 'reference must match reference_kind: string for "exact", RuleJudge for "rule", RubricRef for "rubric"'
41264
+ });
41265
+ EvalCaseSetSchema = exports_external.object({
41266
+ version: exports_external.literal(1),
41267
+ cases: exports_external.array(EvalCaseSchema).min(1)
41268
+ });
41269
+ EvalCaseError = class EvalCaseError extends Error {
41270
+ file;
41271
+ caseId;
41272
+ constructor(file2, caseId, message) {
41273
+ const prefix = caseId ? `${file2}: case "${caseId}" \u2014 ` : `${file2}: `;
41274
+ super(`${prefix}${message}`);
41275
+ this.file = file2;
41276
+ this.caseId = caseId;
41277
+ this.name = "EvalCaseError";
41278
+ }
41279
+ };
41280
+ });
41281
+
40895
41282
  // ../../packages/core/src/quality/magent.ts
40896
41283
  function scoreCompleteness3(body) {
40897
41284
  let found = 0;
@@ -40928,7 +41315,7 @@ function scorePlatformCoverage(data, body) {
40928
41315
  [/opencode/i, "opencode"],
40929
41316
  [/openclaw/i, "openclaw"],
40930
41317
  [/antigravity/i, "antigravity"],
40931
- [/pi\b/i, "pi"]
41318
+ [/\bpi\b/i, "pi"]
40932
41319
  ];
40933
41320
  for (const [re, name] of platformPatterns) {
40934
41321
  if (re.test(body))
@@ -40973,7 +41360,9 @@ function scoreSafety2(body) {
40973
41360
  }
40974
41361
  function evaluateMagent(content, target) {
40975
41362
  const body = extractBody(content);
40976
- const hasFrontmatter = /^---\s*$/m.test(content);
41363
+ const hasFrontmatter = content.startsWith(`---
41364
+ `) || content.startsWith(`---\r
41365
+ `);
40977
41366
  const fmResult = hasFrontmatter ? parseFrontmatterSafe(content) : undefined;
40978
41367
  const data = fmResult ?? {};
40979
41368
  const fmNote = hasFrontmatter && fmResult === null ? parseErrorNote(content, "Frontmatter parse error") : null;
@@ -41115,7 +41504,7 @@ function countTriggerPhrases(body) {
41115
41504
  if (headingMatch) {
41116
41505
  const depth = headingMatch[1]?.length ?? 0;
41117
41506
  const title = (headingMatch[2] ?? "").toLowerCase();
41118
- if (/\btrigger|when to use/i.test(title)) {
41507
+ if (/\b(?:trigger|when to use)/i.test(title)) {
41119
41508
  inTriggerSection = true;
41120
41509
  sectionDepth = depth;
41121
41510
  } else if (inTriggerSection && depth <= sectionDepth) {
@@ -41131,7 +41520,7 @@ function countTriggerPhrases(body) {
41131
41520
  }
41132
41521
  if (count2 === 0) {
41133
41522
  for (const line of lines) {
41134
- if (/^\s*[-*+]\s/.test(line)) {
41523
+ if (/^\s*[-*+]\s/.test(line) || /^\s*\d+[.)]\s/.test(line)) {
41135
41524
  count2++;
41136
41525
  }
41137
41526
  }
@@ -41163,29 +41552,77 @@ var init_evaluate = __esm(() => {
41163
41552
  };
41164
41553
  });
41165
41554
 
41555
+ // ../../packages/core/src/quality/replay.ts
41556
+ function scoreExact(output2, reference) {
41557
+ const normOut = normalize(output2);
41558
+ const normRef = normalize(reference);
41559
+ if (normOut === normRef)
41560
+ return 1;
41561
+ if (normOut.includes(normRef))
41562
+ return 1;
41563
+ return 0;
41564
+ }
41565
+ function scoreRule(output2, judge, toolsCalled) {
41566
+ for (const check2 of judge.checks) {
41567
+ if (!evaluateCheck(output2, check2.op, check2.arg, toolsCalled))
41568
+ return 0;
41569
+ }
41570
+ return 1;
41571
+ }
41572
+ function aggregateHard(scores) {
41573
+ if (scores.length === 0)
41574
+ return 0;
41575
+ const sum = scores.reduce((acc, s) => acc + s, 0);
41576
+ return sum / scores.length;
41577
+ }
41578
+ function normalize(text) {
41579
+ return text.trim().toLowerCase().replace(/\s+/g, " ");
41580
+ }
41581
+ function evaluateCheck(output2, op, arg, toolsCalled) {
41582
+ switch (op) {
41583
+ case "contains":
41584
+ return output2.toLowerCase().includes(arg.toLowerCase());
41585
+ case "regex": {
41586
+ try {
41587
+ return new RegExp(arg).test(output2);
41588
+ } catch {
41589
+ return false;
41590
+ }
41591
+ }
41592
+ case "equals":
41593
+ return normalize(output2) === normalize(arg);
41594
+ case "not_contains":
41595
+ return !output2.toLowerCase().includes(arg.toLowerCase());
41596
+ case "tool_called":
41597
+ return (toolsCalled ?? []).includes(arg);
41598
+ default:
41599
+ return false;
41600
+ }
41601
+ }
41602
+
41166
41603
  // ../../packages/core/src/quality/rubric.ts
41167
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
41168
- import { homedir as homedir3 } from "os";
41169
- import { join as join8 } from "path";
41604
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
41605
+ import { homedir as homedir4 } from "os";
41606
+ import { join as join9 } from "path";
41170
41607
  function resolveRubricContent(type, opts) {
41171
41608
  if (opts?.path) {
41172
- if (!existsSync10(opts.path)) {
41609
+ if (!existsSync11(opts.path)) {
41173
41610
  throw new RubricError("path", `Rubric file not found: ${opts.path}`, opts.path);
41174
41611
  }
41175
- return readFileSync9(opts.path, "utf-8");
41612
+ return readFileSync10(opts.path, "utf-8");
41176
41613
  }
41177
- const homeDir = process.env.HOME ?? homedir3();
41178
- const userPath = join8(homeDir, ".superskill", "rubrics", `${type}.yaml`);
41179
- if (existsSync10(userPath)) {
41180
- return readFileSync9(userPath, "utf-8");
41614
+ const homeDir = process.env.HOME || homedir4();
41615
+ const userPath = join9(homeDir, ".superskill", "rubrics", `${type}.yaml`);
41616
+ if (existsSync11(userPath)) {
41617
+ return readFileSync10(userPath, "utf-8");
41181
41618
  }
41182
- const devPath = join8(import.meta.dir, "..", "rubrics", `${type}.yaml`);
41183
- if (existsSync10(devPath)) {
41184
- return readFileSync9(devPath, "utf-8");
41619
+ const devPath = join9(import.meta.dir, "..", "rubrics", `${type}.yaml`);
41620
+ if (existsSync11(devPath)) {
41621
+ return readFileSync10(devPath, "utf-8");
41185
41622
  }
41186
- const prodPath = join8(import.meta.dir, "..", "..", "rubrics", `${type}.yaml`);
41187
- if (existsSync10(prodPath)) {
41188
- return readFileSync9(prodPath, "utf-8");
41623
+ const prodPath = join9(import.meta.dir, "..", "..", "rubrics", `${type}.yaml`);
41624
+ if (existsSync11(prodPath)) {
41625
+ return readFileSync10(prodPath, "utf-8");
41189
41626
  }
41190
41627
  throw new RubricError("path", `No rubric found for type "${type}". Searched: ${opts?.path ?? "(no explicit path)"}, ${userPath}, ${devPath}, ${prodPath}`, type);
41191
41628
  }
@@ -47014,11 +47451,11 @@ var require_out = __commonJS((exports) => {
47014
47451
  async.read(path7, getSettings(optionsOrSettingsOrCallback), callback);
47015
47452
  }
47016
47453
  exports.stat = stat;
47017
- function statSync7(path7, optionsOrSettings) {
47454
+ function statSync6(path7, optionsOrSettings) {
47018
47455
  const settings = getSettings(optionsOrSettings);
47019
47456
  return sync.read(path7, settings);
47020
47457
  }
47021
- exports.statSync = statSync7;
47458
+ exports.statSync = statSync6;
47022
47459
  function getSettings(settingsOrOptions = {}) {
47023
47460
  if (settingsOrOptions instanceof settings_1.default) {
47024
47461
  return settingsOrOptions;
@@ -47422,11 +47859,11 @@ var require_reusify = __commonJS((exports, module) => {
47422
47859
  // ../../node_modules/.bun/fastq@1.20.1/node_modules/fastq/queue.js
47423
47860
  var require_queue = __commonJS((exports, module) => {
47424
47861
  var reusify = require_reusify();
47425
- function fastqueue(context2, worker, _concurrency) {
47426
- if (typeof context2 === "function") {
47862
+ function fastqueue(context3, worker, _concurrency) {
47863
+ if (typeof context3 === "function") {
47427
47864
  _concurrency = worker;
47428
- worker = context2;
47429
- context2 = null;
47865
+ worker = context3;
47866
+ context3 = null;
47430
47867
  }
47431
47868
  if (!(_concurrency >= 1)) {
47432
47869
  throw new Error("fastqueue concurrency must be equal to or greater than 1");
@@ -47513,7 +47950,7 @@ var require_queue = __commonJS((exports, module) => {
47513
47950
  }
47514
47951
  function push(value, done) {
47515
47952
  var current = cache.get();
47516
- current.context = context2;
47953
+ current.context = context3;
47517
47954
  current.release = release;
47518
47955
  current.value = value;
47519
47956
  current.callback = done || noop4;
@@ -47529,12 +47966,12 @@ var require_queue = __commonJS((exports, module) => {
47529
47966
  }
47530
47967
  } else {
47531
47968
  _running++;
47532
- worker.call(context2, current.value, current.worked);
47969
+ worker.call(context3, current.value, current.worked);
47533
47970
  }
47534
47971
  }
47535
47972
  function unshift(value, done) {
47536
47973
  var current = cache.get();
47537
- current.context = context2;
47974
+ current.context = context3;
47538
47975
  current.release = release;
47539
47976
  current.value = value;
47540
47977
  current.callback = done || noop4;
@@ -47550,7 +47987,7 @@ var require_queue = __commonJS((exports, module) => {
47550
47987
  }
47551
47988
  } else {
47552
47989
  _running++;
47553
- worker.call(context2, current.value, current.worked);
47990
+ worker.call(context3, current.value, current.worked);
47554
47991
  }
47555
47992
  }
47556
47993
  function release(holder) {
@@ -47565,7 +48002,7 @@ var require_queue = __commonJS((exports, module) => {
47565
48002
  }
47566
48003
  queueHead = next.next;
47567
48004
  next.next = null;
47568
- worker.call(context2, next.value, next.worked);
48005
+ worker.call(context3, next.value, next.worked);
47569
48006
  if (queueTail === null) {
47570
48007
  self2.empty();
47571
48008
  }
@@ -47596,14 +48033,14 @@ var require_queue = __commonJS((exports, module) => {
47596
48033
  var callback = current.callback;
47597
48034
  var errorHandler2 = current.errorHandler;
47598
48035
  var val = current.value;
47599
- var context3 = current.context;
48036
+ var context4 = current.context;
47600
48037
  current.value = null;
47601
48038
  current.callback = noop4;
47602
48039
  current.errorHandler = null;
47603
48040
  if (errorHandler2) {
47604
48041
  errorHandler2(new Error("abort"), val);
47605
48042
  }
47606
- callback.call(context3, new Error("abort"));
48043
+ callback.call(context4, new Error("abort"));
47607
48044
  current.release(current);
47608
48045
  current = next;
47609
48046
  }
@@ -47635,18 +48072,18 @@ var require_queue = __commonJS((exports, module) => {
47635
48072
  self2.release(self2);
47636
48073
  };
47637
48074
  }
47638
- function queueAsPromised(context2, worker, _concurrency) {
47639
- if (typeof context2 === "function") {
48075
+ function queueAsPromised(context3, worker, _concurrency) {
48076
+ if (typeof context3 === "function") {
47640
48077
  _concurrency = worker;
47641
- worker = context2;
47642
- context2 = null;
48078
+ worker = context3;
48079
+ context3 = null;
47643
48080
  }
47644
48081
  function asyncWrapper(arg, cb) {
47645
48082
  worker.call(this, arg).then(function(res) {
47646
48083
  cb(null, res);
47647
48084
  }, cb);
47648
48085
  }
47649
- var queue = fastqueue(context2, asyncWrapper, _concurrency);
48086
+ var queue = fastqueue(context3, asyncWrapper, _concurrency);
47650
48087
  var pushCb = queue.push;
47651
48088
  var unshiftCb = queue.unshift;
47652
48089
  queue.push = push;
@@ -47654,42 +48091,42 @@ var require_queue = __commonJS((exports, module) => {
47654
48091
  queue.drained = drained;
47655
48092
  return queue;
47656
48093
  function push(value) {
47657
- var p = new Promise(function(resolve2, reject) {
48094
+ var p = new Promise(function(resolve3, reject) {
47658
48095
  pushCb(value, function(err, result) {
47659
48096
  if (err) {
47660
48097
  reject(err);
47661
48098
  return;
47662
48099
  }
47663
- resolve2(result);
48100
+ resolve3(result);
47664
48101
  });
47665
48102
  });
47666
48103
  p.catch(noop4);
47667
48104
  return p;
47668
48105
  }
47669
48106
  function unshift(value) {
47670
- var p = new Promise(function(resolve2, reject) {
48107
+ var p = new Promise(function(resolve3, reject) {
47671
48108
  unshiftCb(value, function(err, result) {
47672
48109
  if (err) {
47673
48110
  reject(err);
47674
48111
  return;
47675
48112
  }
47676
- resolve2(result);
48113
+ resolve3(result);
47677
48114
  });
47678
48115
  });
47679
48116
  p.catch(noop4);
47680
48117
  return p;
47681
48118
  }
47682
48119
  function drained() {
47683
- var p = new Promise(function(resolve2) {
48120
+ var p = new Promise(function(resolve3) {
47684
48121
  process.nextTick(function() {
47685
48122
  if (queue.idle()) {
47686
- resolve2();
48123
+ resolve3();
47687
48124
  } else {
47688
48125
  var previousDrain = queue.drain;
47689
48126
  queue.drain = function() {
47690
48127
  if (typeof previousDrain === "function")
47691
48128
  previousDrain();
47692
- resolve2();
48129
+ resolve3();
47693
48130
  queue.drain = previousDrain;
47694
48131
  };
47695
48132
  }
@@ -48150,9 +48587,9 @@ var require_stream3 = __commonJS((exports) => {
48150
48587
  });
48151
48588
  }
48152
48589
  _getStat(filepath) {
48153
- return new Promise((resolve2, reject) => {
48590
+ return new Promise((resolve3, reject) => {
48154
48591
  this._stat(filepath, this._fsStatSettings, (error51, stats) => {
48155
- return error51 === null ? resolve2(stats) : reject(error51);
48592
+ return error51 === null ? resolve3(stats) : reject(error51);
48156
48593
  });
48157
48594
  });
48158
48595
  }
@@ -48174,10 +48611,10 @@ var require_async5 = __commonJS((exports) => {
48174
48611
  this._readerStream = new stream_1.default(this._settings);
48175
48612
  }
48176
48613
  dynamic(root, options2) {
48177
- return new Promise((resolve2, reject) => {
48614
+ return new Promise((resolve3, reject) => {
48178
48615
  this._walkAsync(root, options2, (error51, entries) => {
48179
48616
  if (error51 === null) {
48180
- resolve2(entries);
48617
+ resolve3(entries);
48181
48618
  } else {
48182
48619
  reject(error51);
48183
48620
  }
@@ -48187,10 +48624,10 @@ var require_async5 = __commonJS((exports) => {
48187
48624
  async static(patterns, options2) {
48188
48625
  const entries = [];
48189
48626
  const stream = this._readerStream.static(patterns, options2);
48190
- return new Promise((resolve2, reject) => {
48627
+ return new Promise((resolve3, reject) => {
48191
48628
  stream.once("error", reject);
48192
48629
  stream.on("data", (entry) => entries.push(entry));
48193
- stream.once("end", () => resolve2(entries));
48630
+ stream.once("end", () => resolve3(entries));
48194
48631
  });
48195
48632
  }
48196
48633
  }
@@ -49718,7 +50155,7 @@ var import_fast_glob2, import_ignore, defaultIgnoredDirectories, ignoreFilesGlob
49718
50155
  }
49719
50156
  throw createGitConfigReadError(normalizedPath, error51);
49720
50157
  }
49721
- }, getExcludesFileFromGitConfigSync = (filePath, readFileSync10, gitDirectory, options2 = {}) => {
50158
+ }, getExcludesFileFromGitConfigSync = (filePath, readFileSync11, gitDirectory, options2 = {}) => {
49722
50159
  const { suppressErrors, includeStack = new Set, depth = 0 } = options2;
49723
50160
  const normalizedPath = path9.resolve(filePath);
49724
50161
  if (includeStack.has(normalizedPath)) {
@@ -49728,14 +50165,14 @@ var import_fast_glob2, import_ignore, defaultIgnoredDirectories, ignoreFilesGlob
49728
50165
  return;
49729
50166
  }
49730
50167
  includeStack.add(normalizedPath);
49731
- const content = readGitConfigFile(normalizedPath, readFileSync10, suppressErrors);
50168
+ const content = readGitConfigFile(normalizedPath, readFileSync11, suppressErrors);
49732
50169
  if (content === undefined) {
49733
50170
  includeStack.delete(normalizedPath);
49734
50171
  return;
49735
50172
  }
49736
50173
  let { excludesFile, includePaths } = parseGitConfigForExcludesFile(content, normalizedPath, gitDirectory);
49737
50174
  for (const includePath of includePaths) {
49738
- const includedExcludesFile = getExcludesFileFromGitConfigSync(includePath, readFileSync10, gitDirectory, { suppressErrors, includeStack, depth: depth + 1 });
50175
+ const includedExcludesFile = getExcludesFileFromGitConfigSync(includePath, readFileSync11, gitDirectory, { suppressErrors, includeStack, depth: depth + 1 });
49739
50176
  if (includedExcludesFile !== undefined) {
49740
50177
  excludesFile = includedExcludesFile;
49741
50178
  }
@@ -49777,13 +50214,13 @@ var import_fast_glob2, import_ignore, defaultIgnoredDirectories, ignoreFilesGlob
49777
50214
  return gitFilePath;
49778
50215
  }
49779
50216
  return path9.resolve(path9.dirname(gitFilePath), match[1]);
49780
- }, getGitDirectorySync = (gitRoot, readFileSync10) => {
50217
+ }, getGitDirectorySync = (gitRoot, readFileSync11) => {
49781
50218
  if (!gitRoot) {
49782
50219
  return;
49783
50220
  }
49784
50221
  const gitFilePath = path9.join(gitRoot, ".git");
49785
50222
  try {
49786
- return resolveGitDirectoryFromFile(gitFilePath, readFileSync10(gitFilePath, "utf8"));
50223
+ return resolveGitDirectoryFromFile(gitFilePath, readFileSync11(gitFilePath, "utf8"));
49787
50224
  } catch {
49788
50225
  return gitFilePath;
49789
50226
  }
@@ -49826,18 +50263,18 @@ var import_fast_glob2, import_ignore, defaultIgnoredDirectories, ignoreFilesGlob
49826
50263
  }
49827
50264
  }, getGlobalGitignoreFile = (options2 = {}) => {
49828
50265
  const cwd5 = toPath2(options2.cwd) ?? process11.cwd();
49829
- const readFileSync10 = getReadFileSyncMethod(options2.fs);
50266
+ const readFileSync11 = getReadFileSyncMethod(options2.fs);
49830
50267
  const gitRoot = findGitRootSync(cwd5, options2.fs);
49831
- const gitDirectory = getGitDirectorySync(gitRoot, readFileSync10);
50268
+ const gitDirectory = getGitDirectorySync(gitRoot, readFileSync11);
49832
50269
  let excludesFileConfig;
49833
50270
  for (const gitConfigPath of getGitConfigPaths()) {
49834
- const value = getExcludesFileFromGitConfigSync(gitConfigPath, readFileSync10, gitDirectory, { suppressErrors: options2.suppressErrors });
50271
+ const value = getExcludesFileFromGitConfigSync(gitConfigPath, readFileSync11, gitDirectory, { suppressErrors: options2.suppressErrors });
49835
50272
  if (value !== undefined) {
49836
50273
  excludesFileConfig = value;
49837
50274
  }
49838
50275
  }
49839
50276
  const filePath = resolveExcludesFilePath(excludesFileConfig);
49840
- return filePath === undefined ? undefined : readGlobalGitignoreContent(filePath, readFileSync10, options2.suppressErrors);
50277
+ return filePath === undefined ? undefined : readGlobalGitignoreContent(filePath, readFileSync11, options2.suppressErrors);
49841
50278
  }, getGlobalGitignoreFileAsync = async (options2 = {}) => {
49842
50279
  const cwd5 = toPath2(options2.cwd) ?? process11.cwd();
49843
50280
  const readFile = getReadFileMethod(options2.fs);
@@ -58177,7 +58614,7 @@ import {
58177
58614
  writeFile
58178
58615
  } from "fs/promises";
58179
58616
  import os2 from "os";
58180
- import { dirname as dirname6, isAbsolute, join as join22, relative, resolve as resolve2 } from "path";
58617
+ import { dirname as dirname6, isAbsolute, join as join22, relative, resolve as resolve4 } from "path";
58181
58618
  import { isAbsolute as isAbsolute2, resolve as resolve22 } from "path";
58182
58619
  import { basename as basename3, join as join44, relative as relative3 } from "path";
58183
58620
  import { extname as extname2 } from "path";
@@ -58185,8 +58622,8 @@ import { isDeepStrictEqual } from "util";
58185
58622
  import { join as join62 } from "path";
58186
58623
  import { join as join42 } from "path";
58187
58624
  import { join as join52 } from "path";
58188
- import path10, { relative as relative2, resolve as resolve4 } from "path";
58189
- import { basename as basename4, join as join9 } from "path";
58625
+ import path10, { relative as relative2, resolve as resolve42 } from "path";
58626
+ import { basename as basename4, join as join92 } from "path";
58190
58627
  import { join as join72 } from "path";
58191
58628
  import { join as join82 } from "path";
58192
58629
  import { join as join10 } from "path";
@@ -58270,7 +58707,7 @@ import { join as join88 } from "path";
58270
58707
  import { join as join89 } from "path";
58271
58708
  import { join as join90 } from "path";
58272
58709
  import { join as join91 } from "path";
58273
- import { join as join92 } from "path";
58710
+ import { join as join922 } from "path";
58274
58711
  import { join as join93 } from "path";
58275
58712
  import { join as join94 } from "path";
58276
58713
  import { join as join95 } from "path";
@@ -58445,9 +58882,9 @@ function checkPathTraversal({
58445
58882
  if (segments.includes("..")) {
58446
58883
  throw new Error(`Path traversal detected: ${relativePath}`);
58447
58884
  }
58448
- const resolved = resolve2(intendedRootDir, relativePath);
58885
+ const resolved = resolve4(intendedRootDir, relativePath);
58449
58886
  const rel = relative(intendedRootDir, resolved);
58450
- if (rel.startsWith("..") || resolve2(resolved) !== resolved) {
58887
+ if (rel.startsWith("..") || resolve4(resolved) !== resolved) {
58451
58888
  throw new Error(`Path traversal detected: ${relativePath}`);
58452
58889
  }
58453
58890
  }
@@ -58455,7 +58892,7 @@ function resolvePath3(relativePath, outputRoot) {
58455
58892
  if (!outputRoot)
58456
58893
  return relativePath;
58457
58894
  checkPathTraversal({ relativePath, intendedRootDir: outputRoot });
58458
- return resolve2(outputRoot, relativePath);
58895
+ return resolve4(outputRoot, relativePath);
58459
58896
  }
58460
58897
  async function directoryExists(dirPath) {
58461
58898
  try {
@@ -58568,7 +59005,7 @@ function validateOutputRoot(outputRoot) {
58568
59005
  if (segments.includes("..")) {
58569
59006
  throw new Error(`Path traversal detected: ${outputRoot}`);
58570
59007
  }
58571
- const normalized = resolve2(outputRoot);
59008
+ const normalized = resolve4(outputRoot);
58572
59009
  if (normalized !== outputRoot) {
58573
59010
  throw new Error(`outputRoot must be a normalized absolute path: ${outputRoot} (normalized: ${normalized})`);
58574
59011
  }
@@ -62960,8 +63397,8 @@ var import_gray_matter, BaseLogger = class {
62960
63397
  }
62961
63398
  getFilePath() {
62962
63399
  const fullPath = path10.join(this.outputRoot, this.relativeDirPath, this.relativeFilePath);
62963
- const resolvedFull = resolve4(fullPath);
62964
- const resolvedBase = resolve4(this.outputRoot);
63400
+ const resolvedFull = resolve42(fullPath);
63401
+ const resolvedBase = resolve42(this.outputRoot);
62965
63402
  const rel = relative2(resolvedBase, resolvedFull);
62966
63403
  if (rel.startsWith("..") || path10.isAbsolute(rel)) {
62967
63404
  throw new Error(`Path traversal detected: Final path escapes outputRoot. outputRoot="${this.outputRoot}", relativeDirPath="${this.relativeDirPath}", relativeFilePath="${this.relativeFilePath}"`);
@@ -63893,7 +64330,7 @@ var init_chunk_QKQNZ6C3 = __esm(() => {
63893
64330
  if (rest2.validate) {
63894
64331
  const result = AntigravityCommandFrontmatterSchema.safeParse(frontmatter);
63895
64332
  if (!result.success) {
63896
- throw new Error(`Invalid frontmatter in ${join9(rest2.relativeDirPath, rest2.relativeFilePath)}: ${formatError2(result.error)}`);
64333
+ throw new Error(`Invalid frontmatter in ${join92(rest2.relativeDirPath, rest2.relativeFilePath)}: ${formatError2(result.error)}`);
63897
64334
  }
63898
64335
  }
63899
64336
  super({
@@ -63989,7 +64426,7 @@ ${body}${turboDirective}`;
63989
64426
  } else {
63990
64427
  return {
63991
64428
  success: false,
63992
- error: new Error(`Invalid frontmatter in ${join9(this.relativeDirPath, this.relativeFilePath)}: ${formatError2(result.error)}`)
64429
+ error: new Error(`Invalid frontmatter in ${join92(this.relativeDirPath, this.relativeFilePath)}: ${formatError2(result.error)}`)
63993
64430
  };
63994
64431
  }
63995
64432
  }
@@ -64004,7 +64441,7 @@ ${body}${turboDirective}`;
64004
64441
  relativeFilePath,
64005
64442
  validate: validate2 = true
64006
64443
  }) {
64007
- const filePath = join9(outputRoot, _AntigravityCommand.getSettablePaths().relativeDirPath, relativeFilePath);
64444
+ const filePath = join92(outputRoot, _AntigravityCommand.getSettablePaths().relativeDirPath, relativeFilePath);
64008
64445
  const fileContent = await readFileContent(filePath);
64009
64446
  const { frontmatter, body: content } = parseFrontmatter2(fileContent, filePath);
64010
64447
  const result = AntigravityCommandFrontmatterSchema.safeParse(frontmatter);
@@ -71193,7 +71630,7 @@ prompt = ""`;
71193
71630
  try {
71194
71631
  this.json = JSON.parse(this.fileContent);
71195
71632
  } catch (error51) {
71196
- throw new Error(`Failed to parse Cursor MCP config at ${join92(this.relativeDirPath, this.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71633
+ throw new Error(`Failed to parse Cursor MCP config at ${join922(this.relativeDirPath, this.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71197
71634
  }
71198
71635
  } else {
71199
71636
  this.json = {};
@@ -71217,13 +71654,13 @@ prompt = ""`;
71217
71654
  global: global3 = false
71218
71655
  }) {
71219
71656
  const paths = this.getSettablePaths({ global: global3 });
71220
- const filePath = join92(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
71657
+ const filePath = join922(outputRoot, paths.relativeDirPath, paths.relativeFilePath);
71221
71658
  const fileContent = await readFileContentOrNull(filePath) ?? '{"mcpServers":{}}';
71222
71659
  let json3;
71223
71660
  try {
71224
71661
  json3 = JSON.parse(fileContent);
71225
71662
  } catch (error51) {
71226
- throw new Error(`Failed to parse Cursor MCP config at ${join92(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71663
+ throw new Error(`Failed to parse Cursor MCP config at ${join922(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71227
71664
  }
71228
71665
  const newJson = { ...json3, mcpServers: json3.mcpServers ?? {} };
71229
71666
  return new _CursorMcp({
@@ -71242,12 +71679,12 @@ prompt = ""`;
71242
71679
  global: global3 = false
71243
71680
  }) {
71244
71681
  const paths = this.getSettablePaths({ global: global3 });
71245
- const fileContent = await readOrInitializeFileContent(join92(outputRoot, paths.relativeDirPath, paths.relativeFilePath), JSON.stringify({ mcpServers: {} }, null, 2));
71682
+ const fileContent = await readOrInitializeFileContent(join922(outputRoot, paths.relativeDirPath, paths.relativeFilePath), JSON.stringify({ mcpServers: {} }, null, 2));
71246
71683
  let json3;
71247
71684
  try {
71248
71685
  json3 = JSON.parse(fileContent);
71249
71686
  } catch (error51) {
71250
- throw new Error(`Failed to parse Cursor MCP config at ${join92(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71687
+ throw new Error(`Failed to parse Cursor MCP config at ${join922(paths.relativeDirPath, paths.relativeFilePath)}: ${formatError2(error51)}`, { cause: error51 });
71251
71688
  }
71252
71689
  const mcpServers = rulesyncMcp.getMcpServers();
71253
71690
  const transformedServers = convertEnvVarRefsToToolFormat({
@@ -89227,7 +89664,7 @@ var init_dist9 = __esm(() => {
89227
89664
  });
89228
89665
 
89229
89666
  // ../../packages/core/src/rulesync.ts
89230
- import { homedir as homedir4 } from "os";
89667
+ import { homedir as homedir5 } from "os";
89231
89668
  async function runRulesync(targets, features, inputRoot, options2) {
89232
89669
  const mappedTargets = [];
89233
89670
  for (const target of targets) {
@@ -89257,7 +89694,7 @@ async function runRulesync(targets, features, inputRoot, options2) {
89257
89694
  hasDiff: false
89258
89695
  };
89259
89696
  }
89260
- const root = options2.outputRoot ?? (options2.global ? homedir4() : process.cwd());
89697
+ const root = options2.outputRoot ?? (options2.global ? homedir5() : process.cwd());
89261
89698
  const rulesyncGlobal = options2.outputRoot ? false : options2.global;
89262
89699
  return generate2({
89263
89700
  targets: mappedTargets,
@@ -89296,6 +89733,7 @@ var init_src = __esm(() => {
89296
89733
  init_slash_command2();
89297
89734
  init_agent();
89298
89735
  init_command3();
89736
+ init_eval_cases();
89299
89737
  init_evaluate();
89300
89738
  init_heuristics();
89301
89739
  init_hook();
@@ -89675,7 +90113,7 @@ var init_version = () => {};
89675
90113
 
89676
90114
  // ../../node_modules/.bun/drizzle-orm@0.44.7+a0473b45aab9bf33/node_modules/drizzle-orm/tracing.js
89677
90115
  var otel, rawTracer, tracer;
89678
- var init_tracing = __esm(() => {
90116
+ var init_tracing2 = __esm(() => {
89679
90117
  init_tracing_utils();
89680
90118
  init_version();
89681
90119
  tracer = {
@@ -89765,7 +90203,7 @@ var init_sql = __esm(() => {
89765
90203
  init_entity();
89766
90204
  init_enum();
89767
90205
  init_subquery();
89768
- init_tracing();
90206
+ init_tracing2();
89769
90207
  init_view_common();
89770
90208
  init_column();
89771
90209
  init_table();
@@ -94902,13 +95340,13 @@ __export(exports_db, {
94902
95340
  openStore: () => openStore,
94903
95341
  getDBPath: () => getDBPath
94904
95342
  });
94905
- import { existsSync as existsSync11, mkdirSync as mkdirSync6 } from "fs";
95343
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6 } from "fs";
94906
95344
  import { dirname as dirname7 } from "path";
94907
95345
  async function openStore(opts) {
94908
95346
  const url3 = getDBPath(opts);
94909
95347
  if (url3 !== ":memory:") {
94910
95348
  const dir = dirname7(url3);
94911
- if (!existsSync11(dir)) {
95349
+ if (!existsSync12(dir)) {
94912
95350
  mkdirSync6(dir, { recursive: true });
94913
95351
  }
94914
95352
  }
@@ -94935,7 +95373,7 @@ var init_db2 = __esm(() => {
94935
95373
  });
94936
95374
 
94937
95375
  // src/cli.ts
94938
- import { readFileSync as readFileSync15 } from "fs";
95376
+ import { readFileSync as readFileSync16 } from "fs";
94939
95377
  import { join as join226 } from "path";
94940
95378
 
94941
95379
  // ../../node_modules/.bun/commander@14.0.3/node_modules/commander/esm.mjs
@@ -94961,7 +95399,7 @@ init_dist();
94961
95399
  init_src();
94962
95400
  init_dist();
94963
95401
  init_db2();
94964
- import { readFileSync as readFileSync10 } from "fs";
95402
+ import { readFileSync as readFileSync11 } from "fs";
94965
95403
 
94966
95404
  // src/store/evaluations.ts
94967
95405
  init_dist10();
@@ -95157,7 +95595,7 @@ async function ingestScores(type, resolvedPath, resolvedTarget, opts) {
95157
95595
  }
95158
95596
  let raw;
95159
95597
  try {
95160
- raw = readFileSync10(ingestPath, "utf-8");
95598
+ raw = readFileSync11(ingestPath, "utf-8");
95161
95599
  } catch {
95162
95600
  throw Object.assign(new Error(`Cannot read scores file: ${ingestPath}`), { code: 2 });
95163
95601
  }
@@ -95277,7 +95715,7 @@ function formatEvaluationReport(report, json3) {
95277
95715
  // src/operations/evolve.ts
95278
95716
  init_src();
95279
95717
  init_dist();
95280
- import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync11, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
95718
+ import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync12, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
95281
95719
  import { join as join220 } from "path";
95282
95720
  import { createInterface } from "readline";
95283
95721
 
@@ -95345,6 +95783,149 @@ function deserializeProposal(row) {
95345
95783
  };
95346
95784
  }
95347
95785
 
95786
+ // src/operations/pairwise-judge.ts
95787
+ init_src();
95788
+ init_dist5();
95789
+ class TsAiRunnerJudgeBackend {
95790
+ runner;
95791
+ agent;
95792
+ constructor(agent2 = "claude", runner) {
95793
+ this.runner = runner ?? new AiRunner;
95794
+ this.agent = agent2;
95795
+ }
95796
+ async judge(rubric2, prompt, candOutput, baseOutput, options2) {
95797
+ const candidateFirst = options2?.order !== "baseline-first";
95798
+ const outputA = candidateFirst ? candOutput : baseOutput;
95799
+ const outputB = candidateFirst ? baseOutput : candOutput;
95800
+ const systemPrompt = [
95801
+ "You are a strict pairwise behavior judge.",
95802
+ "Compare two outputs for the same task against the rubric criterion.",
95803
+ 'Return only JSON: {"winner":"A"|"B"|"tie","margin":number}.',
95804
+ "The margin must be a number from 0 to 1."
95805
+ ].join(`
95806
+ `);
95807
+ const input = [
95808
+ `Criterion: ${rubric2.criterion}`,
95809
+ rubric2.excellent ? `Excellent anchor: ${rubric2.excellent}` : "",
95810
+ rubric2.poor ? `Poor anchor: ${rubric2.poor}` : "",
95811
+ `Task prompt:
95812
+ ${prompt}`,
95813
+ `Output A:
95814
+ ${outputA}`,
95815
+ `Output B:
95816
+ ${outputB}`
95817
+ ].filter(Boolean).join(`
95818
+
95819
+ `);
95820
+ const result = await this.runner.runPromptCommand(this.agent, {
95821
+ input,
95822
+ systemPrompt,
95823
+ ...options2?.seed !== undefined ? { seed: options2.seed } : {},
95824
+ ...options2?.temperature !== undefined ? { temperature: options2.temperature } : {}
95825
+ });
95826
+ return parseJudgeResponse(result.stdout, candidateFirst);
95827
+ }
95828
+ }
95829
+ function createJudgeBackend(target, injected) {
95830
+ return injected ?? new TsAiRunnerJudgeBackend(TARGET_TO_AGENT_NAME[target]);
95831
+ }
95832
+ async function pairwiseJudge(backend, rubric2, casePrompt, candOutput, baseOutput, options2 = {}) {
95833
+ const order = options2.order ?? (options2.seed !== undefined && options2.seed % 2 === 1 ? "baseline-first" : "candidate-first");
95834
+ return backend.judge(rubric2, casePrompt, candOutput, baseOutput, { ...options2, order });
95835
+ }
95836
+ function signedMargin(verdict) {
95837
+ if (verdict.winner === "candidate")
95838
+ return verdict.margin;
95839
+ if (verdict.winner === "baseline")
95840
+ return -verdict.margin;
95841
+ return 0;
95842
+ }
95843
+ function parseJudgeResponse(stdout, candidateFirst) {
95844
+ let parsed;
95845
+ try {
95846
+ parsed = JSON.parse(stdout.trim());
95847
+ } catch {
95848
+ throw new Error(`Pairwise judge returned invalid JSON: ${stdout.slice(0, 200)}`);
95849
+ }
95850
+ if (typeof parsed !== "object" || parsed === null) {
95851
+ throw new Error("Pairwise judge returned a non-object JSON payload.");
95852
+ }
95853
+ const value = parsed;
95854
+ if (value.winner !== "A" && value.winner !== "B" && value.winner !== "tie") {
95855
+ throw new Error('Pairwise judge JSON must include winner "A", "B", or "tie".');
95856
+ }
95857
+ if (typeof value.margin !== "number" || value.margin < 0 || value.margin > 1) {
95858
+ throw new Error("Pairwise judge JSON must include margin in [0,1].");
95859
+ }
95860
+ if (value.winner === "tie")
95861
+ return { winner: "tie", margin: 0 };
95862
+ if (value.winner === "A") {
95863
+ return { winner: candidateFirst ? "candidate" : "baseline", margin: value.margin };
95864
+ }
95865
+ return { winner: candidateFirst ? "baseline" : "candidate", margin: value.margin };
95866
+ }
95867
+
95868
+ // src/operations/noise-floor.ts
95869
+ async function estimateNoiseFloor(judge, rubric2, casePrompt, candOutput, baseOutput, n2 = 5) {
95870
+ const margins = [];
95871
+ for (let i2 = 0;i2 < n2; i2++) {
95872
+ const verdict = await pairwiseJudge(judge, rubric2, casePrompt, candOutput, baseOutput, {
95873
+ seed: i2 + 1,
95874
+ temperature: 0
95875
+ });
95876
+ margins.push(signedMargin(verdict));
95877
+ }
95878
+ if (margins.length < 2)
95879
+ return 0;
95880
+ const mean2 = margins.reduce((a2, b) => a2 + b, 0) / margins.length;
95881
+ const variance = margins.reduce((sum2, m) => sum2 + (m - mean2) ** 2, 0) / margins.length;
95882
+ return Math.sqrt(variance);
95883
+ }
95884
+ function rejectsWithinNoise(measuredDelta, noiseFloor) {
95885
+ return Math.abs(measuredDelta) < noiseFloor;
95886
+ }
95887
+
95888
+ // src/operations/replay-runner.ts
95889
+ init_src();
95890
+ init_dist5();
95891
+ class TsAiRunnerBackend {
95892
+ runner;
95893
+ agent;
95894
+ constructor(agent2 = "claude", runner) {
95895
+ this.runner = runner ?? new AiRunner;
95896
+ this.agent = agent2;
95897
+ }
95898
+ async run(systemPrompt, userPrompt) {
95899
+ const result = await this.runner.runPromptCommand(this.agent, {
95900
+ input: userPrompt,
95901
+ systemPrompt
95902
+ });
95903
+ return result.stdout;
95904
+ }
95905
+ }
95906
+ function createReplayBackend(target, injected) {
95907
+ return injected ?? new TsAiRunnerBackend(TARGET_TO_AGENT_NAME[target]);
95908
+ }
95909
+ async function replayCase(backend, skill2, ev, toolsCalled) {
95910
+ const prompt = `[case:${ev.id}] ${ev.prompt}`;
95911
+ const output2 = await backend.run(skill2, prompt);
95912
+ let hard;
95913
+ if (ev.reference_kind === "exact") {
95914
+ hard = scoreExact(output2, ev.reference);
95915
+ } else {
95916
+ hard = scoreRule(output2, ev.reference, toolsCalled);
95917
+ }
95918
+ return { hard, output: output2 };
95919
+ }
95920
+ async function replaySplit(backend, skill2, cases, split, toolsCalled) {
95921
+ const splitCases = cases.filter((c3) => c3.split === split);
95922
+ if (splitCases.length === 0)
95923
+ return { hard: 0, n: 0 };
95924
+ const results = await Promise.all(splitCases.map((c3) => replayCase(backend, skill2, c3, toolsCalled)));
95925
+ const scores = results.map((r) => r.hard);
95926
+ return { hard: aggregateHard(scores), n: splitCases.length };
95927
+ }
95928
+
95348
95929
  // src/operations/validate.ts
95349
95930
  init_src();
95350
95931
 
@@ -95526,6 +96107,106 @@ async function runGate(input) {
95526
96107
  reason: `\u0394-margin gate failed: \u0394${delta >= 0 ? "+" : ""}${delta.toFixed(2)} < required margin ${input.margin.toFixed(2)}.`
95527
96108
  };
95528
96109
  }
96110
+ let empiricalScores;
96111
+ if (input.evalGate) {
96112
+ const cases = loadEvalCases(input.evalGate.name);
96113
+ if (cases) {
96114
+ const holdout = cases.cases.filter((c3) => c3.split === "holdout");
96115
+ const rubricCases = holdout.filter((c3) => c3.reference_kind === "rubric");
96116
+ const detCases = holdout.filter((c3) => c3.reference_kind !== "rubric");
96117
+ const maxModelCalls = input.evalGate.judgeBudget?.maxModelCalls ?? Number.POSITIVE_INFINITY;
96118
+ let modelCalls = 0;
96119
+ const consumeModelCalls = (count3, reason) => {
96120
+ modelCalls += count3;
96121
+ if (modelCalls > maxModelCalls) {
96122
+ return {
96123
+ ok: false,
96124
+ failedGate: "empirical",
96125
+ reason: `Empirical gate budget cap hit: ${modelCalls} model call(s) for ${reason} exceeds max ${maxModelCalls}.`
96126
+ };
96127
+ }
96128
+ return null;
96129
+ };
96130
+ const replayBackend = createReplayBackend(input.evalGate.target, input.evalGate.replayBackend);
96131
+ let detBaseScore = 0;
96132
+ let detCandScore = 0;
96133
+ let detN = 0;
96134
+ if (detCases.length > 0) {
96135
+ const budgetResult = consumeModelCalls(detCases.length * 2, "deterministic replay");
96136
+ if (budgetResult)
96137
+ return budgetResult;
96138
+ const baseDet = await replaySplit(replayBackend, input.evalGate.baselineSkillText, detCases, "holdout");
96139
+ const candDet = await replaySplit(replayBackend, input.evalGate.candidateSkillText, detCases, "holdout");
96140
+ detBaseScore = baseDet.hard;
96141
+ detCandScore = candDet.hard;
96142
+ detN = detCases.length;
96143
+ }
96144
+ let rubricBaseScore = 0;
96145
+ let rubricCandScore = 0;
96146
+ let maxNoiseFloor = 0;
96147
+ let signedDeltaTotal = 0;
96148
+ let rubricN = 0;
96149
+ if (rubricCases.length > 0) {
96150
+ const judge = createJudgeBackend(input.evalGate.target, input.evalGate.judgeBackend);
96151
+ const judgeReplays = input.evalGate.judgeReplays ?? 3;
96152
+ for (const rc of rubricCases) {
96153
+ const replayBudget = consumeModelCalls(2, `rubric replay for ${rc.id}`);
96154
+ if (replayBudget)
96155
+ return replayBudget;
96156
+ const prompt = `[case:${rc.id}] ${rc.prompt}`;
96157
+ const [candOutput, baseOutput] = await Promise.all([
96158
+ replayBackend.run(input.evalGate.candidateSkillText, prompt),
96159
+ replayBackend.run(input.evalGate.baselineSkillText, prompt)
96160
+ ]);
96161
+ const rubricRef = rc.reference;
96162
+ const judgeBudget = consumeModelCalls(1, `pairwise rubric judge for ${rc.id}`);
96163
+ if (judgeBudget)
96164
+ return judgeBudget;
96165
+ const verdict = await pairwiseJudge(judge, rubricRef, prompt, candOutput, baseOutput, {
96166
+ seed: 0,
96167
+ temperature: 0
96168
+ });
96169
+ const noiseBudget = consumeModelCalls(judgeReplays, `noise-floor replay for ${rc.id}`);
96170
+ if (noiseBudget)
96171
+ return noiseBudget;
96172
+ const noiseFloor = await estimateNoiseFloor(judge, rubricRef, prompt, candOutput, baseOutput, judgeReplays);
96173
+ const delta2 = signedMargin(verdict);
96174
+ maxNoiseFloor = Math.max(maxNoiseFloor, noiseFloor);
96175
+ signedDeltaTotal += delta2;
96176
+ if (rejectsWithinNoise(delta2, noiseFloor)) {
96177
+ rubricCandScore += 0.5;
96178
+ rubricBaseScore += 0.5;
96179
+ } else if (verdict.winner === "candidate") {
96180
+ rubricCandScore += 1;
96181
+ } else if (verdict.winner === "baseline") {
96182
+ rubricBaseScore += 1;
96183
+ } else {
96184
+ rubricCandScore += 0.5;
96185
+ rubricBaseScore += 0.5;
96186
+ }
96187
+ rubricN++;
96188
+ }
96189
+ }
96190
+ const totalN = detN + rubricN;
96191
+ const baseHard = totalN > 0 ? (detBaseScore * detN + rubricBaseScore / Math.max(rubricN, 1) * rubricN) / totalN : 0;
96192
+ const candHard = totalN > 0 ? (detCandScore * detN + rubricCandScore / Math.max(rubricN, 1) * rubricN) / totalN : 0;
96193
+ const rubricDelta = rubricN > 0 ? signedDeltaTotal / rubricN : undefined;
96194
+ if (!(candHard > baseHard && candHard - baseHard >= input.evalGate.margin)) {
96195
+ return {
96196
+ ok: false,
96197
+ failedGate: "empirical",
96198
+ reason: `Empirical gate failed: candidate behavior ${candHard.toFixed(2)} \u2264 baseline ${baseHard.toFixed(2)} (margin ${input.evalGate.margin.toFixed(2)}${rubricDelta !== undefined ? `, rubric_delta=${rubricDelta.toFixed(2)}, noise_floor=${maxNoiseFloor.toFixed(2)}` : ""}).`
96199
+ };
96200
+ }
96201
+ const trainCases = cases.cases.filter((c3) => c3.split === "train");
96202
+ empiricalScores = {
96203
+ hard: candHard,
96204
+ holdout_n: totalN,
96205
+ train_n: trainCases.length,
96206
+ ...rubricN > 0 ? { noise_floor: maxNoiseFloor, rubric_delta: rubricDelta ?? 0 } : {}
96207
+ };
96208
+ }
96209
+ }
95529
96210
  if (input.ingestedAnchorHash !== undefined && input.baselineAnchorHash !== undefined) {
95530
96211
  if (input.ingestedAnchorHash !== input.baselineAnchorHash) {
95531
96212
  return {
@@ -95543,7 +96224,7 @@ async function runGate(input) {
95543
96224
  reason: `Skeptic gate failed: the Skeptic reported an anchor/invariant violation.${violations}`
95544
96225
  };
95545
96226
  }
95546
- return { ok: true };
96227
+ return { ok: true, ...empiricalScores ? { empirical: empiricalScores } : {} };
95547
96228
  }
95548
96229
  function emitGenerationEnvelope(type, resolvedPath, content, baseline, trends) {
95549
96230
  const rubric2 = loadRubric(type);
@@ -95601,7 +96282,7 @@ function emitGenerationEnvelope(type, resolvedPath, content, baseline, trends) {
95601
96282
  async function ingestProposal(db2, type, name, resolvedPath, ingestPath, opts, baselineScore) {
95602
96283
  let raw;
95603
96284
  try {
95604
- raw = readFileSync11(ingestPath, "utf-8");
96285
+ raw = readFileSync12(ingestPath, "utf-8");
95605
96286
  } catch {
95606
96287
  throw Object.assign(new Error(`Cannot read proposal file: ${ingestPath}`), { code: 2 });
95607
96288
  }
@@ -95643,10 +96324,22 @@ async function ingestProposal(db2, type, name, resolvedPath, ingestPath, opts, b
95643
96324
  if (opts?.acceptId) {
95644
96325
  const backupPath = await backupFile(resolvedPath);
95645
96326
  const appliedCount = await stepApply(parsed.changes, resolvedPath, proposalRecord.id, db2);
96327
+ const evalGate = opts?.evalGate ? {
96328
+ name,
96329
+ candidateSkillText: await Bun.file(resolvedPath).text(),
96330
+ baselineSkillText: readFileSync12(backupPath, "utf-8"),
96331
+ margin: opts?.margin ?? 0.05,
96332
+ target: opts?.target ?? "claude",
96333
+ replayBackend: opts?.replayBackend,
96334
+ judgeBackend: opts?.judgeBackend,
96335
+ judgeReplays: opts?.judgeReplays,
96336
+ judgeBudget: opts?.judgeBudget
96337
+ } : undefined;
95646
96338
  const verdict = await stepVerify(type, name, resolvedPath, baselineScore, proposalRecord.id, opts, db2, {
95647
96339
  backupPath,
95648
96340
  ingestedAnchorHash: parsed.anchor_hash,
95649
- skeptic: parsed.skeptic
96341
+ skeptic: parsed.skeptic,
96342
+ evalGate
95650
96343
  });
95651
96344
  if (!verdict.rejected && verdict.backupPath) {
95652
96345
  await persistVersionSnapshot(verdict.backupPath, resolvedPath, proposalId);
@@ -95863,7 +96556,7 @@ async function stepVerify(type, name, filePath, baselineScore, proposalDbId, opt
95863
96556
  const delta = postScore - baselineScore;
95864
96557
  if (gate) {
95865
96558
  const margin = opts?.margin ?? 0.05;
95866
- const baselineAnchorHash = gate.ingestedAnchorHash !== undefined ? computeBaselineAnchorHash(readFileSync11(gate.backupPath, "utf-8")) : undefined;
96559
+ const baselineAnchorHash = gate.ingestedAnchorHash !== undefined ? computeBaselineAnchorHash(readFileSync12(gate.backupPath, "utf-8")) : undefined;
95867
96560
  const gateResult = await runGate({
95868
96561
  type,
95869
96562
  resolvedPath: filePath,
@@ -95872,7 +96565,8 @@ async function stepVerify(type, name, filePath, baselineScore, proposalDbId, opt
95872
96565
  margin,
95873
96566
  ingestedAnchorHash: gate.ingestedAnchorHash,
95874
96567
  baselineAnchorHash,
95875
- skeptic: gate.skeptic
96568
+ skeptic: gate.skeptic,
96569
+ evalGate: gate.evalGate
95876
96570
  });
95877
96571
  if (!gateResult.ok) {
95878
96572
  await restoreFromBackup(gate.backupPath, filePath);
@@ -95880,6 +96574,31 @@ async function stepVerify(type, name, filePath, baselineScore, proposalDbId, opt
95880
96574
  echoError(`Gate rejected proposal \u2014 ${gateResult.reason} File restored; proposal stays draft.`);
95881
96575
  return { postScore: baselineScore, delta: 0, rejected: true, reason: gateResult.reason };
95882
96576
  }
96577
+ if (gateResult.empirical) {
96578
+ try {
96579
+ await new EvaluationDao(db2).insertEvaluation({
96580
+ content_type: type,
96581
+ content_name: name,
96582
+ target_agent: opts?.target ?? "claude",
96583
+ operation: "evolve",
96584
+ aggregate: gateResult.empirical.hard,
96585
+ dimensions: {
96586
+ empirical: {
96587
+ score: gateResult.empirical.hard,
96588
+ hard: gateResult.empirical.hard,
96589
+ holdout_n: gateResult.empirical.holdout_n,
96590
+ train_n: gateResult.empirical.train_n,
96591
+ ...gateResult.empirical.noise_floor !== undefined ? { noise_floor: gateResult.empirical.noise_floor } : {},
96592
+ ...gateResult.empirical.rubric_delta !== undefined ? { rubric_delta: gateResult.empirical.rubric_delta } : {},
96593
+ note: `Behavior gate: holdout_n=${gateResult.empirical.holdout_n}, train_n=${gateResult.empirical.train_n}${gateResult.empirical.noise_floor !== undefined ? `, noise_floor=${gateResult.empirical.noise_floor.toFixed(2)}` : ""}${gateResult.empirical.rubric_delta !== undefined ? `, rubric_delta=${gateResult.empirical.rubric_delta.toFixed(2)}` : ""}`
96594
+ }
96595
+ }
96596
+ });
96597
+ echo(`Empirical behavior: holdout ${gateResult.empirical.hard.toFixed(2)} (holdout_n=${gateResult.empirical.holdout_n}, train_n=${gateResult.empirical.train_n}${gateResult.empirical.noise_floor !== undefined ? `, noise_floor=${gateResult.empirical.noise_floor.toFixed(2)}` : ""})`);
96598
+ } catch {
96599
+ echoError("Cannot persist empirical behavior score.");
96600
+ }
96601
+ }
95883
96602
  }
95884
96603
  try {
95885
96604
  const verifyEval = await new EvaluationDao(db2).getLatestEvaluation(type, name);
@@ -95909,7 +96628,7 @@ function formatAnalyze(name, analysis) {
95909
96628
  const { trends, baselineScore, baselineDate, evaluations: evaluations2 } = analysis;
95910
96629
  const grade = scoreToGrade(baselineScore);
95911
96630
  const verdict = baselineScore >= 0.7 ? "PASS" : "FAIL";
95912
- const gitAvailable = existsSync12(join220(process.cwd(), ".git"));
96631
+ const gitAvailable = existsSync13(join220(process.cwd(), ".git"));
95913
96632
  const lines = [];
95914
96633
  lines.push("=== Evolution Analysis ===");
95915
96634
  lines.push(`Target: ${name} Score: ${(baselineScore * 100).toFixed(0)}% (${grade}) Status: ${verdict}`);
@@ -95939,12 +96658,12 @@ function formatAnalyze(name, analysis) {
95939
96658
  async function persistVersionSnapshot(backupPath, resolvedPath, proposalId) {
95940
96659
  const versionPath = `${resolvedPath}.version-${proposalId}`;
95941
96660
  await Bun.write(versionPath, Bun.file(backupPath));
95942
- rmSync3(backupPath, { force: true });
96661
+ rmSync5(backupPath, { force: true });
95943
96662
  return versionPath;
95944
96663
  }
95945
96664
  async function evolve(type, name, opts) {
95946
96665
  const resolvedPath = resolveContentPath(type, name);
95947
- if (!resolvedPath || !existsSync12(resolvedPath)) {
96666
+ if (!resolvedPath || !existsSync13(resolvedPath)) {
95948
96667
  echoError(`File not found: ${name}`);
95949
96668
  return { baselineScore: 0, postScore: 0, delta: 0, changesApplied: 0, proposalPath: "" };
95950
96669
  }
@@ -95979,7 +96698,7 @@ async function evolve(type, name, opts) {
95979
96698
  const versionId = proposalId2 ?? `#${p.id}`;
95980
96699
  const appliedAt = p.applied_at ?? "unknown";
95981
96700
  const versionPath = `${resolvedPath}.version-${versionId}`;
95982
- const hasSnapshot = existsSync12(versionPath) ? "\u2713" : "\u2717";
96701
+ const hasSnapshot = existsSync13(versionPath) ? "\u2713" : "\u2717";
95983
96702
  lines.push(`| ${versionId} | ${appliedAt} | ${hasSnapshot} |`);
95984
96703
  }
95985
96704
  echo(lines.join(`
@@ -95992,7 +96711,7 @@ async function evolve(type, name, opts) {
95992
96711
  return { baselineScore: 0, postScore: 0, delta: 0, changesApplied: 0, proposalPath: "" };
95993
96712
  }
95994
96713
  const versionPath = `${resolvedPath}.version-${opts.rollback}`;
95995
- if (!existsSync12(versionPath)) {
96714
+ if (!existsSync13(versionPath)) {
95996
96715
  echoError(`Version snapshot not found: ${opts.rollback}`);
95997
96716
  return { baselineScore: 0, postScore: 0, delta: 0, changesApplied: 0, proposalPath: "" };
95998
96717
  }
@@ -96072,10 +96791,22 @@ async function evolve(type, name, opts) {
96072
96791
  }
96073
96792
  const backupPath2 = await backupFile(resolvedPath);
96074
96793
  const appliedCount = await stepApply(acceptedFromStore, resolvedPath, target.id, db2);
96794
+ const evalGateCtx2 = opts?.evalGate ? {
96795
+ name: contentName,
96796
+ candidateSkillText: await Bun.file(resolvedPath).text(),
96797
+ baselineSkillText: readFileSync12(backupPath2, "utf-8"),
96798
+ margin: opts?.margin ?? 0.05,
96799
+ target: opts?.target ?? "claude",
96800
+ replayBackend: opts?.replayBackend,
96801
+ judgeBackend: opts?.judgeBackend,
96802
+ judgeReplays: opts?.judgeReplays,
96803
+ judgeBudget: opts?.judgeBudget
96804
+ } : undefined;
96075
96805
  const verdict = await stepVerify(type, contentName, resolvedPath, baselineScore, target.id, opts, db2, {
96076
96806
  backupPath: backupPath2,
96077
96807
  ingestedAnchorHash: storedAnchorHash,
96078
- skeptic: storedSkeptic
96808
+ skeptic: storedSkeptic,
96809
+ evalGate: evalGateCtx2
96079
96810
  });
96080
96811
  if (!verdict.rejected && verdict.backupPath) {
96081
96812
  await persistVersionSnapshot(verdict.backupPath, resolvedPath, opts.acceptId);
@@ -96098,7 +96829,18 @@ async function evolve(type, name, opts) {
96098
96829
  const { accepted: acceptedChanges } = await interactiveReview(changes, trends);
96099
96830
  const backupPath = await backupFile(resolvedPath);
96100
96831
  const changesApplied = await stepApply(acceptedChanges, resolvedPath, proposalDbId, db2);
96101
- const { postScore, delta } = await stepVerify(type, contentName, resolvedPath, baselineScore, proposalDbId, opts, db2);
96832
+ const evalGateCtx = opts?.evalGate ? {
96833
+ name: contentName,
96834
+ candidateSkillText: await Bun.file(resolvedPath).text(),
96835
+ baselineSkillText: readFileSync12(backupPath, "utf-8"),
96836
+ margin: opts?.margin ?? 0.05,
96837
+ target: opts?.target ?? "claude",
96838
+ replayBackend: opts?.replayBackend,
96839
+ judgeBackend: opts?.judgeBackend,
96840
+ judgeReplays: opts?.judgeReplays,
96841
+ judgeBudget: opts?.judgeBudget
96842
+ } : undefined;
96843
+ const { postScore, delta } = await stepVerify(type, contentName, resolvedPath, baselineScore, proposalDbId, opts, db2, evalGateCtx ? { backupPath, evalGate: evalGateCtx } : undefined);
96102
96844
  await persistVersionSnapshot(backupPath, resolvedPath, proposalId);
96103
96845
  return { baselineScore, postScore, delta, changesApplied, proposalPath };
96104
96846
  }
@@ -96515,7 +97257,7 @@ function addScaffoldOptions(cmd) {
96515
97257
  return cmd.option("-d, --description <text>", "Content description").option("-t, --target <agent>", "Target agent platform", "claude").option("-o, --output <dir>", "Output directory (default: cwd)").option("--template <tier>", "Template tier (e.g. minimal / standard / specialist)").option("--tools <list>", "Comma-separated tool names to pre-populate frontmatter").option("--force", "Overwrite existing file if present");
96516
97258
  }
96517
97259
  function addEvolveOptions(cmd) {
96518
- return cmd.option("-t, --target <agent>", "Target agent platform", "claude").option("--from <date>", "Analyze evaluations since date (ISO 8601)").option("--propose-only", "Generate proposal without applying").option("--accept <id>", "Accept a specific proposal by ID").option("--reject <id>", "Reject a specific proposal").option("--json", "Output machine-readable JSON (envelope-out with --propose-only)").option("--ingest <file>", "Agent-authored proposal JSON (ingest-in mode)").option("--margin <n>", "\u0394-margin gate threshold for accept (default 0.05)", Number.parseFloat, 0.05).option("--analyze", "Print analysis summary (trends, score, data sources) without writing a proposal").option("--history", "List applied proposal versions from the store").option("--rollback <id>", "Rollback to a prior version by proposal_id (requires --confirm)").option("--confirm", "Confirm a destructive operation (required for --rollback)");
97260
+ return cmd.option("-t, --target <agent>", "Target agent platform", "claude").option("--from <date>", "Analyze evaluations since date (ISO 8601)").option("--propose-only", "Generate proposal without applying").option("--accept <id>", "Accept a specific proposal by ID").option("--reject <id>", "Reject a specific proposal").option("--json", "Output machine-readable JSON (envelope-out with --propose-only)").option("--ingest <file>", "Agent-authored proposal JSON (ingest-in mode)").option("--margin <n>", "\u0394-margin gate threshold for accept (default 0.05)", Number.parseFloat, 0.05).option("--eval-gate", "Enable empirical behavior gate (requires skills/<name>/eval/cases.yaml)").option("--analyze", "Print analysis summary (trends, score, data sources) without writing a proposal").option("--history", "List applied proposal versions from the store").option("--rollback <id>", "Rollback to a prior version by proposal_id (requires --confirm)").option("--confirm", "Confirm a destructive operation (required for --rollback)");
96519
97261
  }
96520
97262
  function addHookEvolveOptions(cmd) {
96521
97263
  return cmd.option("-t, --target <agent>", "Target agent platform", "claude").option("--from <date>", "Analyze evaluations since date (ISO 8601)").option("--analyze", "Print analysis summary (trends, score, data sources) \u2014 analyze-only, no apply").option("--json", "Output machine-readable JSON");
@@ -96624,7 +97366,8 @@ async function agentEvolve(opts) {
96624
97366
  analyze: opts.analyze,
96625
97367
  history: opts.history,
96626
97368
  rollback: opts.rollback,
96627
- confirm: opts.confirm
97369
+ confirm: opts.confirm,
97370
+ evalGate: opts.evalGate
96628
97371
  });
96629
97372
  return;
96630
97373
  }
@@ -96720,7 +97463,8 @@ async function commandEvolve(opts) {
96720
97463
  analyze: opts.analyze,
96721
97464
  history: opts.history,
96722
97465
  rollback: opts.rollback,
96723
- confirm: opts.confirm
97466
+ confirm: opts.confirm,
97467
+ evalGate: opts.evalGate
96724
97468
  });
96725
97469
  return;
96726
97470
  }
@@ -96761,7 +97505,7 @@ function registerCommand(program2) {
96761
97505
  // src/commands/hook.ts
96762
97506
  init_src();
96763
97507
  init_dist();
96764
- import { homedir as homedir6 } from "os";
97508
+ import { homedir as homedir7 } from "os";
96765
97509
  import { join as join225 } from "path";
96766
97510
 
96767
97511
  // src/commands/install.ts
@@ -96769,19 +97513,19 @@ init_src();
96769
97513
  init_dist();
96770
97514
  import {
96771
97515
  copyFileSync as copyFileSync2,
96772
- existsSync as existsSync14,
97516
+ existsSync as existsSync15,
96773
97517
  mkdirSync as mkdirSync9,
96774
97518
  readdirSync as readdirSync4,
96775
- readFileSync as readFileSync13,
96776
- rmSync as rmSync4,
96777
- statSync as statSync7,
97519
+ readFileSync as readFileSync14,
97520
+ rmSync as rmSync6,
97521
+ statSync as statSync6,
96778
97522
  writeFileSync as writeFileSync8
96779
97523
  } from "fs";
96780
- import { homedir as homedir5 } from "os";
97524
+ import { homedir as homedir6 } from "os";
96781
97525
  import { join as join223 } from "path";
96782
97526
 
96783
97527
  // src/hooks.ts
96784
- import { copyFileSync, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "fs";
97528
+ import { copyFileSync, existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "fs";
96785
97529
  import { join as join221 } from "path";
96786
97530
  var CANONICAL_TO_PI_EVENT = {
96787
97531
  sessionStart: "session_start",
@@ -96825,10 +97569,10 @@ function convertCanonicalToPiHooks(config3) {
96825
97569
  }
96826
97570
  function readCanonicalHooks(rulesyncDir) {
96827
97571
  const hooksPath = join221(rulesyncDir, "hooks.json");
96828
- if (!existsSync13(hooksPath))
97572
+ if (!existsSync14(hooksPath))
96829
97573
  return null;
96830
97574
  try {
96831
- return JSON.parse(readFileSync12(hooksPath, "utf-8"));
97575
+ return JSON.parse(readFileSync13(hooksPath, "utf-8"));
96832
97576
  } catch {
96833
97577
  return null;
96834
97578
  }
@@ -96986,7 +97730,7 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
96986
97730
  echo(` Skills written: ${resultCounts.skillsCount}, Commands: ${resultCounts.commandsCount}, Subagents: ${resultCounts.subagentsCount}, Hooks: ${resultCounts.hooksCount}`);
96987
97731
  }
96988
97732
  }
96989
- const outputRoot = options2.outputRoot ?? (options2.global ? homedir5() : process.cwd());
97733
+ const outputRoot = options2.outputRoot ?? (options2.global ? homedir6() : process.cwd());
96990
97734
  const hookEmitResults = [];
96991
97735
  for (const target of targets2) {
96992
97736
  if (target === "claude") {
@@ -96995,9 +97739,9 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
96995
97739
  if (!options2.dryRun) {
96996
97740
  const marketplaceName = resolution.marketplaceName ?? "superskill";
96997
97741
  const marketplaceRoot = resolution.marketplaceRoot ?? process.cwd();
96998
- const cacheDir = join223(homedir5(), ".claude", "plugins", "cache", marketplaceName);
96999
- if (existsSync14(cacheDir))
97000
- rmSync4(cacheDir, { recursive: true, force: true });
97742
+ const cacheDir = join223(homedir6(), ".claude", "plugins", "cache", marketplaceName);
97743
+ if (existsSync15(cacheDir))
97744
+ rmSync6(cacheDir, { recursive: true, force: true });
97001
97745
  await runClaudeInstallImpl(marketplaceRoot, marketplaceName, plugin);
97002
97746
  }
97003
97747
  }
@@ -97014,13 +97758,7 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
97014
97758
  echo(` ${hookResult.message}`);
97015
97759
  }
97016
97760
  if (target === "omp") {
97017
- const srcTarget = "pi";
97018
- const dest = join223(outputRoot, ".omp", "agent", "skills");
97019
- if (options2.verbose)
97020
- echo(`Copying to omp (via pi rulesync): ${dest}...`);
97021
- if (!options2.dryRun)
97022
- copyDirectory(join223(rulesyncSourceRoot(targetInputRoots.get(srcTarget), outputDir), "skills"), dest);
97023
- const hookResult = emitPiStyleHooks(rulesyncSourceRoot(targetInputRoots.get(srcTarget), outputDir), outputRoot, ".omp", "omp", { dryRun: options2.dryRun, global: options2.global });
97761
+ const hookResult = emitPiStyleHooks(rulesyncSourceRoot(targetInputRoots.get("pi"), outputDir), outputRoot, ".omp", "omp", { dryRun: options2.dryRun, global: options2.global });
97024
97762
  hookEmitResults.push(hookResult);
97025
97763
  if (options2.verbose)
97026
97764
  echo(` ${hookResult.message}`);
@@ -97031,7 +97769,7 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
97031
97769
  if (options2.verbose)
97032
97770
  echo(` ${hookResult.message}`);
97033
97771
  const agentsDir = join223(pluginRoot, "agents");
97034
- if (existsSync14(agentsDir) && !options2.dryRun) {
97772
+ if (existsSync15(agentsDir) && !options2.dryRun) {
97035
97773
  const piAgentsDir = join223(outputRoot, ".pi", "agent", "agents");
97036
97774
  mkdirSync9(piAgentsDir, { recursive: true });
97037
97775
  for (const entry of readdirSync4(agentsDir)) {
@@ -97039,8 +97777,8 @@ async function executeInstall(plugin, targets2, options2, dependencies = {}) {
97039
97777
  continue;
97040
97778
  const agentName = entry.replace(/\.md$/, "");
97041
97779
  const expectedName = `${plugin}-${agentName}`;
97042
- const source = readFileSync13(join223(agentsDir, entry), "utf-8");
97043
- const skillExists = (bare) => existsSync14(join223(pluginRoot, "skills", bare));
97780
+ const source = readFileSync14(join223(agentsDir, entry), "utf-8");
97781
+ const skillExists = (bare) => existsSync15(join223(pluginRoot, "skills", bare));
97044
97782
  const adapted = adaptSubagentToPi(source, expectedName, plugin, skillExists);
97045
97783
  writeFileSync8(join223(piAgentsDir, `${expectedName}.md`), adapted);
97046
97784
  }
@@ -97089,9 +97827,9 @@ function resolvePluginRoot(plugin, marketplacePath) {
97089
97827
  const manifestRoot = resolved.marketplaceRoot;
97090
97828
  const manifestPath = join223(manifestRoot, ".claude-plugin", "marketplace.json");
97091
97829
  let marketplaceName;
97092
- if (existsSync14(manifestPath)) {
97830
+ if (existsSync15(manifestPath)) {
97093
97831
  try {
97094
- const raw = readFileSync13(manifestPath, "utf-8");
97832
+ const raw = readFileSync14(manifestPath, "utf-8");
97095
97833
  const parsed = JSON.parse(raw);
97096
97834
  marketplaceName = parsed.name;
97097
97835
  } catch {}
@@ -97099,7 +97837,7 @@ function resolvePluginRoot(plugin, marketplacePath) {
97099
97837
  return { pluginRoot: resolved.pluginRoot, marketplaceRoot: manifestRoot, marketplaceName };
97100
97838
  }
97101
97839
  const fallback = join223("plugins", plugin);
97102
- if (existsSync14(fallback) && readdirSync4(fallback).some((d) => ["skills", "commands", "agents", "hooks", "hooks.json"].includes(d)))
97840
+ if (existsSync15(fallback) && readdirSync4(fallback).some((d) => ["skills", "commands", "agents", "hooks", "hooks.json"].includes(d)))
97103
97841
  return { pluginRoot: fallback };
97104
97842
  const available = listResolvablePlugins(marketplacePath);
97105
97843
  const msg = available.length > 0 ? `Available: ${available.join(", ")}` : "No marketplace manifest found and no plugins/<name>/ directory.";
@@ -97108,7 +97846,7 @@ function resolvePluginRoot(plugin, marketplacePath) {
97108
97846
  function prepareTargetRulesyncInput(sourceRoot, target, pluginName) {
97109
97847
  const targetRoot = join223(sourceRoot, ".targets", target);
97110
97848
  const targetRulesyncRoot = join223(targetRoot, ".rulesync");
97111
- rmSync4(targetRoot, { recursive: true, force: true });
97849
+ rmSync6(targetRoot, { recursive: true, force: true });
97112
97850
  copyDirectory(sourceRoot, targetRulesyncRoot, { skipDirectoryNames: new Set([".targets"]) });
97113
97851
  transformRulesyncMarkdown(targetRulesyncRoot, target, pluginName);
97114
97852
  return targetRoot;
@@ -97134,25 +97872,25 @@ function transformRulesyncMarkdown(root, target, pluginName) {
97134
97872
  transformMarkdownDirectory(join223(root, "skills"), target, pluginName);
97135
97873
  }
97136
97874
  function transformMarkdownDirectory(dir, target, pluginName) {
97137
- if (!existsSync14(dir))
97875
+ if (!existsSync15(dir))
97138
97876
  return;
97139
97877
  for (const entry of readdirSync4(dir)) {
97140
97878
  const path11 = join223(dir, entry);
97141
- const stats = statSync7(path11);
97879
+ const stats = statSync6(path11);
97142
97880
  if (stats.isDirectory()) {
97143
97881
  transformMarkdownDirectory(path11, target, pluginName);
97144
97882
  continue;
97145
97883
  }
97146
97884
  if (!entry.endsWith(".md"))
97147
97885
  continue;
97148
- const content = readFileSync13(path11, "utf-8");
97886
+ const content = readFileSync14(path11, "utf-8");
97149
97887
  const slashTranslated = translateSlashCommands(content, target);
97150
97888
  const transformed = rewriteSkillReferences(slashTranslated, pluginName);
97151
97889
  writeFileSync8(path11, transformed);
97152
97890
  }
97153
97891
  }
97154
97892
  function copyDirectory(source, destination, options2 = {}) {
97155
- if (!existsSync14(source))
97893
+ if (!existsSync15(source))
97156
97894
  return;
97157
97895
  mkdirSync9(destination, { recursive: true });
97158
97896
  for (const entry of readdirSync4(source)) {
@@ -97160,7 +97898,7 @@ function copyDirectory(source, destination, options2 = {}) {
97160
97898
  continue;
97161
97899
  const sourcePath = join223(source, entry);
97162
97900
  const destinationPath = join223(destination, entry);
97163
- if (statSync7(sourcePath).isDirectory()) {
97901
+ if (statSync6(sourcePath).isDirectory()) {
97164
97902
  copyDirectory(sourcePath, destinationPath, options2);
97165
97903
  } else {
97166
97904
  copyFileSync2(sourcePath, destinationPath);
@@ -97199,7 +97937,7 @@ async function emitHook(name, opts) {
97199
97937
  const target = resolveTarget(opts);
97200
97938
  const global3 = opts.global !== false;
97201
97939
  const dryRun = opts.dryRun === true;
97202
- const outputRoot = global3 ? homedir6() : process.cwd();
97940
+ const outputRoot = global3 ? homedir7() : process.cwd();
97203
97941
  const pluginRoot = resolvePluginRoot(name).pluginRoot;
97204
97942
  const outputDir = ".rulesync";
97205
97943
  mapPluginToRulesync(pluginRoot, name, outputDir);
@@ -97327,7 +98065,8 @@ async function magentEvolve(opts) {
97327
98065
  analyze: opts.analyze,
97328
98066
  history: opts.history,
97329
98067
  rollback: opts.rollback,
97330
- confirm: opts.confirm
98068
+ confirm: opts.confirm,
98069
+ evalGate: opts.evalGate
97331
98070
  });
97332
98071
  return;
97333
98072
  }
@@ -97371,9 +98110,9 @@ init_dist();
97371
98110
  // src/operations/migrate.ts
97372
98111
  init_src();
97373
98112
  init_dist();
97374
- import { readFileSync as readFileSync14 } from "fs";
98113
+ import { readFileSync as readFileSync15 } from "fs";
97375
98114
  function readProposalId(proposalPath) {
97376
- const raw = readFileSync14(proposalPath, "utf-8");
98115
+ const raw = readFileSync15(proposalPath, "utf-8");
97377
98116
  const parsed = JSON.parse(raw);
97378
98117
  if (parsed !== null && typeof parsed === "object" && "proposal_id" in parsed) {
97379
98118
  const id = parsed.proposal_id;
@@ -97478,7 +98217,8 @@ async function skillEvolve(opts) {
97478
98217
  analyze: opts.analyze,
97479
98218
  history: opts.history,
97480
98219
  rollback: opts.rollback,
97481
- confirm: opts.confirm
98220
+ confirm: opts.confirm,
98221
+ evalGate: opts.evalGate
97482
98222
  });
97483
98223
  return;
97484
98224
  }
@@ -97542,7 +98282,7 @@ function getPackageVersion() {
97542
98282
  if (packageVersion)
97543
98283
  return packageVersion;
97544
98284
  const packageJsonPath = join226(import.meta.dir, "..", "package.json");
97545
- const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
98285
+ const packageJson = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
97546
98286
  if (typeof packageJson.version !== "string" || packageJson.version.length === 0) {
97547
98287
  throw new Error(`Invalid package version in ${packageJsonPath}`);
97548
98288
  }