@moda-ai/cli 1.55.84 → 1.55.85

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.
@@ -3947,6 +3947,121 @@ import {
3947
3947
  import { basename as basename6, delimiter, dirname as dirname8, join as join11, relative as relative9, resolve as resolve9, sep as sep5 } from "node:path";
3948
3948
  import { confirm, select } from "@inquirer/prompts";
3949
3949
 
3950
+ // ../../packages/harness-bundle/src/agent-identity.ts
3951
+ var normalizeName = (value) => (value ?? "").split(/\s*\(/)[0].replace(/[^a-z0-9]/gi, "").toLowerCase();
3952
+ var normalizePath2 = (value) => value.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
3953
+ var sourceFile = (value) => /\.[cm]?[jt]sx?$|\.py$/.test(value);
3954
+ var DECLARATION = /^\s*(?:export\s+)?(?:default\s+)?(?:(?:abstract|async)\s+)?(class|function)\s+([\w$]+)(?=\s*(?:extends\b|implements\b|[{(<]))/i;
3955
+ var isDefinitionEvidence = (reason) => /^\s*(?:class|entrypoint)\s*$|(?:class|function|route) (?:definition|declaration)|concrete agent|function or route owns|entrypoint definition/i.test(reason ?? "") || DECLARATION.test(reason ?? "");
3956
+ function definingEvidence(agent) {
3957
+ const root = agent.root && sourceFile(agent.root) ? normalizePath2(agent.root) : undefined;
3958
+ let definitions = (agent.evidence ?? []).filter((entry) => isDefinitionEvidence(entry.reason) && entry.path && sourceFile(entry.path) && (!root || normalizePath2(entry.path) === root));
3959
+ const ownNames = new Set([agent.name, agent.className ?? ""].map(normalizeName).filter(Boolean));
3960
+ const named = definitions.filter((entry) => {
3961
+ const symbol = DECLARATION.exec(entry.reason ?? "")?.[2];
3962
+ return symbol && ownNames.has(normalizeName(symbol));
3963
+ });
3964
+ if (named.length)
3965
+ definitions = named;
3966
+ const files = new Set(definitions.map((entry) => normalizePath2(entry.path)));
3967
+ const lines = new Set(definitions.flatMap((entry) => entry.line !== undefined ? [entry.line] : []));
3968
+ const symbols = new Set(definitions.flatMap((entry) => DECLARATION.exec(entry.reason ?? "")?.[2] ?? []));
3969
+ if (files.size > 1 || lines.size > 1 || symbols.size > 1)
3970
+ return;
3971
+ return definitions;
3972
+ }
3973
+ function definitionKinds(agent) {
3974
+ const kinds = new Set;
3975
+ for (const evidence of definingEvidence(agent) ?? []) {
3976
+ const reason = evidence.reason?.trim() ?? "";
3977
+ const declared = DECLARATION.exec(reason)?.[1]?.toLowerCase();
3978
+ if (declared)
3979
+ kinds.add(declared);
3980
+ else if (/^class\b|^concrete agent.*class\b/i.test(reason))
3981
+ kinds.add("class");
3982
+ else if (/^(?:function|route)\b/i.test(reason))
3983
+ kinds.add("function");
3984
+ }
3985
+ return kinds;
3986
+ }
3987
+ function identityNames(agent) {
3988
+ return new Set([agent.name, agent.className ?? ""].map(normalizeName).filter(Boolean));
3989
+ }
3990
+ function paths(agent) {
3991
+ const definitions = definingEvidence(agent);
3992
+ if (!definitions)
3993
+ return new Set;
3994
+ if (agent.root && sourceFile(agent.root))
3995
+ return new Set([normalizePath2(agent.root)]);
3996
+ return new Set(definitions.flatMap((entry) => entry.path ? [normalizePath2(entry.path)] : []));
3997
+ }
3998
+ function matchHarnessAgentIds(source, target) {
3999
+ const mapping = new Map;
4000
+ const sourcePaths = new Map(source.map((agent) => [agent.id, paths(agent)]));
4001
+ const targetPaths = new Map(target.map((agent) => [agent.id, paths(agent)]));
4002
+ const targetIds = new Set(target.map((agent) => agent.id));
4003
+ const kinds = new Map([...source, ...target].map((agent) => [agent, definitionKinds(agent)]));
4004
+ const names = new Map([...source, ...target].map((agent) => [agent, identityNames(agent)]));
4005
+ for (const agent of source) {
4006
+ if (targetIds.has(agent.id)) {
4007
+ mapping.set(agent.id, agent.id);
4008
+ continue;
4009
+ }
4010
+ const ownPaths = sourcePaths.get(agent.id);
4011
+ const ownKinds = kinds.get(agent);
4012
+ const overlapping = target.filter((candidate) => {
4013
+ const otherKinds = kinds.get(candidate);
4014
+ const compatible = ownKinds.size === 0 || otherKinds.size === 0 || [...ownKinds].some((kind) => otherKinds.has(kind));
4015
+ return compatible && [...targetPaths.get(candidate.id)].some((path) => ownPaths.has(path));
4016
+ });
4017
+ const ownNames = names.get(agent);
4018
+ const named = overlapping.filter((candidate) => [...names.get(candidate)].some((name) => ownNames.has(name)));
4019
+ if (named.length === 1 && source.filter((other) => [...names.get(other)].some((name) => ownNames.has(name)) && [...sourcePaths.get(other.id)].some((path) => targetPaths.get(named[0].id).has(path))).length === 1) {
4020
+ mapping.set(agent.id, named[0].id);
4021
+ continue;
4022
+ }
4023
+ const anchored = overlapping.filter((candidate) => (definingEvidence(agent) ?? []).some((entry) => isDefinitionEvidence(entry.reason) && entry.path && entry.line !== undefined && (definingEvidence(candidate) ?? []).some((other) => isDefinitionEvidence(other.reason) && other.line === entry.line && other.path && normalizePath2(other.path) === normalizePath2(entry.path)) && source.filter((identity) => (definingEvidence(identity) ?? []).some((definition) => isDefinitionEvidence(definition.reason) && definition.path && definition.line === entry.line && normalizePath2(definition.path) === normalizePath2(entry.path))).length === 1));
4024
+ if (anchored.length === 1) {
4025
+ mapping.set(agent.id, anchored[0].id);
4026
+ continue;
4027
+ }
4028
+ if (named.length > 1)
4029
+ continue;
4030
+ const coordinateConflict = overlapping.length === 1 && (definingEvidence(agent) ?? []).some((entry) => entry.line !== undefined) && (definingEvidence(overlapping[0]) ?? []).some((entry) => entry.line !== undefined) && !(definingEvidence(agent) ?? []).some((entry) => entry.path && entry.line !== undefined && (definingEvidence(overlapping[0]) ?? []).some((other) => other.path && other.line === entry.line && normalizePath2(other.path) === normalizePath2(entry.path)));
4031
+ if (!coordinateConflict && overlapping.length === 1 && overlapping[0].root && sourceFile(overlapping[0].root) && [...ownPaths].some((path) => targetPaths.get(overlapping[0].id).has(path) && source.filter((other) => sourcePaths.get(other.id).has(path)).length === 1)) {
4032
+ mapping.set(agent.id, overlapping[0].id);
4033
+ }
4034
+ }
4035
+ return mapping;
4036
+ }
4037
+ function harnessAgentIdentities(value) {
4038
+ if (!Array.isArray(value))
4039
+ return [];
4040
+ return value.flatMap((entry) => {
4041
+ if (!entry || typeof entry !== "object")
4042
+ return [];
4043
+ const item = entry;
4044
+ if (typeof item.id !== "string" || typeof item.name !== "string")
4045
+ return [];
4046
+ return [{
4047
+ id: item.id,
4048
+ name: item.name,
4049
+ ...typeof item.root === "string" ? { root: item.root } : {},
4050
+ ...typeof item.className === "string" ? { className: item.className } : {},
4051
+ evidence: Array.isArray(item.evidence) ? item.evidence.flatMap((raw) => {
4052
+ if (!raw || typeof raw !== "object")
4053
+ return [];
4054
+ const ev = raw;
4055
+ return typeof ev.path === "string" ? [{
4056
+ path: ev.path,
4057
+ ...typeof ev.line === "number" ? { line: ev.line } : {},
4058
+ ...typeof ev.reason === "string" ? { reason: ev.reason } : {}
4059
+ }] : [];
4060
+ }) : []
4061
+ }];
4062
+ });
4063
+ }
4064
+
3950
4065
  // src/analyst-tui.ts
3951
4066
  class AnalystTui {
3952
4067
  state;
@@ -6017,10 +6132,10 @@ function ignoredPaths(root) {
6017
6132
  }
6018
6133
  function locallyIgnored(root, entries) {
6019
6134
  const out = new Map;
6020
- const paths = entries.map((entry) => entry.replace(/\/+$/, "")).filter((entry) => entry !== "");
6021
- if (paths.length === 0)
6135
+ const paths2 = entries.map((entry) => entry.replace(/\/+$/, "")).filter((entry) => entry !== "");
6136
+ if (paths2.length === 0)
6022
6137
  return out;
6023
- const result = git(root, ["check-ignore", "--verbose", "-z", "--stdin"], `${paths.join("\x00")}\x00`);
6138
+ const result = git(root, ["check-ignore", "--verbose", "-z", "--stdin"], `${paths2.join("\x00")}\x00`);
6024
6139
  if (result.status === 1)
6025
6140
  return out;
6026
6141
  if (result.status !== 0)
@@ -7458,17 +7573,17 @@ var LANGUAGE_BY_EXT = {
7458
7573
  sol: "solidity",
7459
7574
  gleam: "gleam"
7460
7575
  };
7461
- function detectToolchain(paths, readText, harnessRoot) {
7462
- const pathSet = new Set(paths);
7576
+ function detectToolchain(paths2, readText, harnessRoot) {
7577
+ const pathSet = new Set(paths2);
7463
7578
  return {
7464
- languages: detectLanguages(paths),
7465
- packageManagers: detectPackageManagers(paths, pathSet, readText),
7466
- ...detectVersions(paths, readText, harnessRoot)
7579
+ languages: detectLanguages(paths2),
7580
+ packageManagers: detectPackageManagers(paths2, pathSet, readText),
7581
+ ...detectVersions(paths2, readText, harnessRoot)
7467
7582
  };
7468
7583
  }
7469
- function detectLanguages(paths) {
7584
+ function detectLanguages(paths2) {
7470
7585
  const counts = new Map;
7471
- for (const path of paths) {
7586
+ for (const path of paths2) {
7472
7587
  const categories = categorize({ path, encoding: "text" });
7473
7588
  if (categories.includes("generated"))
7474
7589
  continue;
@@ -7544,10 +7659,10 @@ function resolveMembers(rootDir, patterns, manifestDirs) {
7544
7659
  }
7545
7660
  return [...members].sort();
7546
7661
  }
7547
- function detectPackageManagers(paths, pathSet, readText) {
7662
+ function detectPackageManagers(paths2, pathSet, readText) {
7548
7663
  const out = [];
7549
7664
  const memberOf = new Set;
7550
- const byName = (name) => paths.filter((p) => basenameOf(p) === name).map(dirnameOf).sort((a, b) => a.length - b.length || (a < b ? -1 : 1));
7665
+ const byName = (name) => paths2.filter((p) => basenameOf(p) === name).map(dirnameOf).sort((a, b) => a.length - b.length || (a < b ? -1 : 1));
7551
7666
  const firstExisting = (dir, names) => names.map((n) => join3(dir, n)).find((p) => pathSet.has(p));
7552
7667
  const nodeDirs = byName("package.json");
7553
7668
  for (const dir of nodeDirs) {
@@ -7604,7 +7719,7 @@ function detectPackageManagers(paths, pathSet, readText) {
7604
7719
  for (const dir of byName(name))
7605
7720
  pyDirs.add(dir);
7606
7721
  }
7607
- for (const path of paths) {
7722
+ for (const path of paths2) {
7608
7723
  if (/^requirements([-_.].+)?\.txt$/i.test(basenameOf(path)))
7609
7724
  pyDirs.add(dirnameOf(path));
7610
7725
  }
@@ -7615,7 +7730,7 @@ function detectPackageManagers(paths, pathSet, readText) {
7615
7730
  continue;
7616
7731
  const pyproject = readText(join3(dir, "pyproject.toml"));
7617
7732
  let kind = "pip";
7618
- let manifest = firstExisting(dir, ["pyproject.toml", "Pipfile", "requirements.txt", "setup.py", "environment.yml", "environment.yaml"]) ?? paths.find((p) => dirnameOf(p) === dir && /^requirements([-_.].+)?\.txt$/i.test(basenameOf(p)));
7733
+ let manifest = firstExisting(dir, ["pyproject.toml", "Pipfile", "requirements.txt", "setup.py", "environment.yml", "environment.yaml"]) ?? paths2.find((p) => dirnameOf(p) === dir && /^requirements([-_.].+)?\.txt$/i.test(basenameOf(p)));
7619
7734
  let lockfile;
7620
7735
  if (pathSet.has(join3(dir, "uv.lock")) || /^\[tool\.uv/m.test(pyproject ?? "")) {
7621
7736
  kind = "uv";
@@ -7706,7 +7821,7 @@ function detectPackageManagers(paths, pathSet, readText) {
7706
7821
  out.push({ kind, root: rootLabel(dir), manifest, ...lockfile ? { lockfile } : {} });
7707
7822
  }
7708
7823
  }
7709
- for (const path of paths) {
7824
+ for (const path of paths2) {
7710
7825
  if (/\.(csproj|fsproj)$/i.test(path)) {
7711
7826
  const dir = dirnameOf(path);
7712
7827
  const lockfile = firstExisting(dir, ["packages.lock.json"]);
@@ -7782,7 +7897,7 @@ function flowSequence(src) {
7782
7897
  function cleanVersion(raw) {
7783
7898
  return raw.trim().replace(/^["']|["']$/g, "").replace(/^v(?=\d)/, "");
7784
7899
  }
7785
- function detectVersions(paths, readText, harnessRoot) {
7900
+ function detectVersions(paths2, readText, harnessRoot) {
7786
7901
  const candidates = [];
7787
7902
  const push = (key, value, source, priority) => {
7788
7903
  if (!value)
@@ -7793,7 +7908,7 @@ function detectVersions(paths, readText, harnessRoot) {
7793
7908
  candidates.push({ key, value: cleaned, source, priority });
7794
7909
  }
7795
7910
  };
7796
- for (const path of paths) {
7911
+ for (const path of paths2) {
7797
7912
  const name = basenameOf(path).toLowerCase();
7798
7913
  const isWorkflow = /^\.github\/workflows\/[^/]+\.ya?ml$/.test(path);
7799
7914
  const isDocker = /^(dockerfile|containerfile)([.-].+)?$/.test(name) || /\.dockerfile$/.test(name);
@@ -14485,8 +14600,8 @@ function inferAgentEntrypoints(input, map, roots) {
14485
14600
  set.add(hit.path);
14486
14601
  byRoot.set(root, set);
14487
14602
  }
14488
- for (const [root, paths] of [...byRoot.entries()].sort(([a], [b]) => cmp(a, b))) {
14489
- const files = [...paths].sort();
14603
+ for (const [root, paths2] of [...byRoot.entries()].sort(([a], [b]) => cmp(a, b))) {
14604
+ const files = [...paths2].sort();
14490
14605
  const mains = files.filter((f) => MAIN_FILE.test(f));
14491
14606
  const pick = mains.sort((a, b) => a.split("/").length - b.split("/").length)[0] ?? (files.length === 1 ? files[0] : undefined);
14492
14607
  const isPy = (pick ?? files[0]).endsWith(".py");
@@ -14784,8 +14899,8 @@ function moduleSpecifiers(source, braceStartsRegex = false) {
14784
14899
  }
14785
14900
  return out;
14786
14901
  }
14787
- function readOptions(cfg, paths, read, depth = 0) {
14788
- if (depth > 8 || !paths.has(cfg))
14902
+ function readOptions(cfg, paths2, read, depth = 0) {
14903
+ if (depth > 8 || !paths2.has(cfg))
14789
14904
  return null;
14790
14905
  const json = parseJsonLoose(read(cfg) ?? "");
14791
14906
  if (!isRecord(json))
@@ -14795,7 +14910,7 @@ function readOptions(cfg, paths, read, depth = 0) {
14795
14910
  const extendsList = (Array.isArray(json.extends) ? json.extends : [json.extends]).filter((e) => typeof e === "string" && e.startsWith("."));
14796
14911
  for (const e of extendsList) {
14797
14912
  const target = joinPath(dir, e);
14798
- const parent = readOptions(target.endsWith(".json") ? target : `${target}.json`, paths, read, depth + 1);
14913
+ const parent = readOptions(target.endsWith(".json") ? target : `${target}.json`, paths2, read, depth + 1);
14799
14914
  if (parent?.baseUrl !== undefined)
14800
14915
  merged.baseUrl = parent.baseUrl;
14801
14916
  if (parent?.paths !== undefined)
@@ -14820,36 +14935,36 @@ function readOptions(cfg, paths, read, depth = 0) {
14820
14935
  }
14821
14936
  return merged;
14822
14937
  }
14823
- function readTsconfig(cfg, paths, read) {
14824
- const options = readOptions(cfg, paths, read);
14938
+ function readTsconfig(cfg, paths2, read) {
14939
+ const options = readOptions(cfg, paths2, read);
14825
14940
  if (!options || options.baseUrl === undefined && options.paths === undefined)
14826
14941
  return null;
14827
14942
  return { baseUrl: options.baseUrl, pathsBase: options.paths?.base ?? options.baseUrl ?? dirname5(cfg), paths: options.paths?.list ?? [] };
14828
14943
  }
14829
- function aliasesFor(dir, paths, read, cache) {
14944
+ function aliasesFor(dir, paths2, read, cache) {
14830
14945
  for (let d = dir;; d = dirname5(d)) {
14831
14946
  const cfg = joinPath(d, "tsconfig.json");
14832
14947
  if (!cache.has(cfg))
14833
- cache.set(cfg, readTsconfig(cfg, paths, read));
14948
+ cache.set(cfg, readTsconfig(cfg, paths2, read));
14834
14949
  const hit = cache.get(cfg);
14835
14950
  if (hit)
14836
14951
  return hit;
14837
- if (paths.has(cfg))
14952
+ if (paths2.has(cfg))
14838
14953
  return null;
14839
14954
  if (d === "." || d === "")
14840
14955
  return null;
14841
14956
  }
14842
14957
  }
14843
- function resolveFile(candidate, paths) {
14958
+ function resolveFile(candidate, paths2) {
14844
14959
  const base = candidate.replace(/\?.*$/, "");
14845
- if (paths.has(base))
14960
+ if (paths2.has(base))
14846
14961
  return base;
14847
14962
  const stem = base.replace(/\.(?:[cm]?js|jsx)$/, "");
14848
14963
  for (const ext of EXTENSIONS)
14849
- if (paths.has(`${stem}${ext}`))
14964
+ if (paths2.has(`${stem}${ext}`))
14850
14965
  return `${stem}${ext}`;
14851
14966
  for (const ext of EXTENSIONS)
14852
- if (paths.has(`${base}/index${ext}`))
14967
+ if (paths2.has(`${base}/index${ext}`))
14853
14968
  return `${base}/index${ext}`;
14854
14969
  return;
14855
14970
  }
@@ -14862,7 +14977,7 @@ function exportTargets(value) {
14862
14977
  return Object.values(value).flatMap(exportTargets);
14863
14978
  return [];
14864
14979
  }
14865
- function packageEntry(dir, sub, paths, read) {
14980
+ function packageEntry(dir, sub, paths2, read) {
14866
14981
  const json = parseJsonLoose(read(joinPath(dir, "package.json")) ?? "");
14867
14982
  const fields = [];
14868
14983
  if (isRecord(json)) {
@@ -14892,20 +15007,20 @@ function packageEntry(dir, sub, paths, read) {
14892
15007
  fields.push(json[k]);
14893
15008
  }
14894
15009
  }
14895
- const found = fields.map((f) => resolveFile(joinPath(dir, f), paths)).filter((f) => f !== undefined);
15010
+ const found = fields.map((f) => resolveFile(joinPath(dir, f), paths2)).filter((f) => f !== undefined);
14896
15011
  if (found.length > 0)
14897
15012
  return [...new Set(found)];
14898
- const fallback = sub ? resolveFile(joinPath(dir, sub), paths) ?? resolveFile(joinPath(dir, "src", sub), paths) : resolveFile(joinPath(dir, "src/index"), paths) ?? resolveFile(joinPath(dir, "index"), paths);
15013
+ const fallback = sub ? resolveFile(joinPath(dir, sub), paths2) ?? resolveFile(joinPath(dir, "src", sub), paths2) : resolveFile(joinPath(dir, "src/index"), paths2) ?? resolveFile(joinPath(dir, "index"), paths2);
14899
15014
  return fallback ? [fallback] : [];
14900
15015
  }
14901
15016
  function dynamicImports(source) {
14902
15017
  const text = stripJsComments(source);
14903
15018
  return [...text.matchAll(CALL_RE)].map((m) => m[1].trim()).filter((arg) => arg !== "" && !STATIC_ARG.test(arg));
14904
15019
  }
14905
- function packageImportTargets(spec, from, paths, read) {
15020
+ function packageImportTargets(spec, from, paths2, read) {
14906
15021
  for (let d = dirname5(from);; d = dirname5(d)) {
14907
15022
  const manifest = joinPath(d, "package.json");
14908
- if (paths.has(manifest)) {
15023
+ if (paths2.has(manifest)) {
14909
15024
  const json = parseJsonLoose(read(manifest) ?? "");
14910
15025
  const imports = isRecord(json) && isRecord(json.imports) ? json.imports : undefined;
14911
15026
  if (imports) {
@@ -14947,13 +15062,13 @@ function packageImport(spec, from, input) {
14947
15062
  return [];
14948
15063
  }
14949
15064
  function importClosure(input) {
14950
- const { paths, read } = input;
15065
+ const { paths: paths2, read } = input;
14951
15066
  const max = input.maxFiles ?? 20000;
14952
15067
  const files = new Set;
14953
15068
  const unresolved = [];
14954
15069
  const dynamic = [];
14955
15070
  const aliasCache = new Map;
14956
- const queue = input.entries.filter((e) => paths.has(e));
15071
+ const queue = input.entries.filter((e) => paths2.has(e));
14957
15072
  let imports = 0;
14958
15073
  while (queue.length > 0 && files.size < max) {
14959
15074
  const file = queue.shift();
@@ -14991,28 +15106,28 @@ function importClosure(input) {
14991
15106
  return { entries: input.entries, files, unresolved, imports, dynamic, truncated };
14992
15107
  }
14993
15108
  function resolveSpecifier(spec, from, input, aliasCache) {
14994
- const { paths, read } = input;
15109
+ const { paths: paths2, read } = input;
14995
15110
  if (spec.startsWith(".")) {
14996
- const hit = resolveFile(joinPath(dirname5(from), spec), paths);
15111
+ const hit = resolveFile(joinPath(dirname5(from), spec), paths2);
14997
15112
  return hit ? [hit] : [];
14998
15113
  }
14999
15114
  if (spec.startsWith("/") || /^(?:node|bun|cloudflare|workers|https?|data):/.test(spec))
15000
15115
  return;
15001
- const aliases = aliasesFor(dirname5(from), paths, read, aliasCache);
15116
+ const aliases = aliasesFor(dirname5(from), paths2, read, aliasCache);
15002
15117
  for (const alias of aliases?.paths ?? []) {
15003
15118
  const matches = alias.wildcard ? spec.startsWith(alias.prefix) && spec.endsWith(alias.suffix) : spec === alias.prefix;
15004
15119
  if (!matches)
15005
15120
  continue;
15006
15121
  const middle = alias.wildcard ? spec.slice(alias.prefix.length, spec.length - alias.suffix.length) : "";
15007
15122
  for (const target of alias.targets) {
15008
- const hit = resolveFile(joinPath(aliases.pathsBase, target.replace("*", middle)), paths);
15123
+ const hit = resolveFile(joinPath(aliases.pathsBase, target.replace("*", middle)), paths2);
15009
15124
  if (hit)
15010
15125
  return [hit];
15011
15126
  }
15012
15127
  return [];
15013
15128
  }
15014
15129
  if (aliases?.baseUrl) {
15015
- const hit = resolveFile(joinPath(aliases.baseUrl, spec), paths);
15130
+ const hit = resolveFile(joinPath(aliases.baseUrl, spec), paths2);
15016
15131
  if (hit)
15017
15132
  return [hit];
15018
15133
  }
@@ -15024,7 +15139,7 @@ function resolveSpecifier(spec, from, input, aliasCache) {
15024
15139
  if (dir === undefined)
15025
15140
  return /^(?:@\/|~\/)/.test(spec) ? [] : undefined;
15026
15141
  const sub = parts.slice(spec.startsWith("@") ? 2 : 1).join("/");
15027
- const entry = packageEntry(dir, sub, paths, read);
15142
+ const entry = packageEntry(dir, sub, paths2, read);
15028
15143
  return entry.length > 0 ? entry : [];
15029
15144
  }
15030
15145
  function isRuntimeConfigFile(path, root) {
@@ -15045,7 +15160,7 @@ var DOC_DIR2 = /(^|\/)(docs?|documentation|website)(\/|$)/;
15045
15160
  var AUXILIARY_DIR = /(^|\/)(vendor|third_party|examples?|samples?|demos?|\.devops|cloud-deployments|hack|playground)(\/|$)/;
15046
15161
  var BUNDLED_KINDS = new Set(["cloudflare_workers"]);
15047
15162
  function runtimeFiles(ctx, runtimes, packageJsons, harnessRoot, launchedScript) {
15048
- const paths = new Set(ctx.files.map((f) => f.path));
15163
+ const paths2 = new Set(ctx.files.map((f) => f.path));
15049
15164
  const read = (p2) => ctx.byPath.get(p2)?.text;
15050
15165
  const workspacePackages = new Map;
15051
15166
  for (const p2 of packageJsons)
@@ -15056,10 +15171,10 @@ function runtimeFiles(ctx, runtimes, packageJsons, harnessRoot, launchedScript)
15056
15171
  for (const rt of runtimes) {
15057
15172
  if (!BUNDLED_KINDS.has(rt.kind))
15058
15173
  continue;
15059
- const entries = uniqSorted(rt.entrypoints.map((e) => (e.handler ?? "").split("#")[0]).filter((p2) => paths.has(p2) && languageOf(p2) === "js"));
15174
+ const entries = uniqSorted(rt.entrypoints.map((e) => (e.handler ?? "").split("#")[0]).filter((p2) => paths2.has(p2) && languageOf(p2) === "js"));
15060
15175
  if (entries.length === 0)
15061
15176
  continue;
15062
- const closure = importClosure({ entries, paths, read, workspacePackages });
15177
+ const closure = importClosure({ entries, paths: paths2, read, workspacePackages });
15063
15178
  const relative6 = closure.unresolved.length;
15064
15179
  if (closure.files.size <= entries.length && relative6 > 0)
15065
15180
  continue;
@@ -15077,7 +15192,7 @@ function runtimeFiles(ctx, runtimes, packageJsons, harnessRoot, launchedScript)
15077
15192
  if (!/^[./~#]/.test(spec))
15078
15193
  pkgs.add(npmPackageOf(spec));
15079
15194
  else if (spec.startsWith("#")) {
15080
- for (const t of packageImportTargets(spec, f, paths, read)?.targets ?? [])
15195
+ for (const t of packageImportTargets(spec, f, paths2, read)?.targets ?? [])
15081
15196
  if (!t.startsWith(".") && !t.startsWith("#"))
15082
15197
  pkgs.add(npmPackageOf(t));
15083
15198
  }
@@ -15865,16 +15980,16 @@ function detectDependencies(input) {
15865
15980
  if (loaded.skipped.length > 0) {
15866
15981
  const byReason = new Map;
15867
15982
  for (const sk of loaded.skipped) {
15868
- let paths = byReason.get(sk.reason);
15869
- if (!paths)
15870
- byReason.set(sk.reason, paths = []);
15871
- paths.push(sk.path);
15983
+ let paths2 = byReason.get(sk.reason);
15984
+ if (!paths2)
15985
+ byReason.set(sk.reason, paths2 = []);
15986
+ paths2.push(sk.path);
15872
15987
  }
15873
- for (const [reason, paths] of [...byReason.entries()].sort(([a], [b]) => cmp(a, b))) {
15988
+ for (const [reason, paths2] of [...byReason.entries()].sort(([a], [b]) => cmp(a, b))) {
15874
15989
  ctx.gaps.push({
15875
15990
  kind: "skipped_files",
15876
- message: `${paths.length} file(s) not analyzed (${reason}): ${paths.slice(0, 5).map(redact).join(", ")}${paths.length > 5 ? ", ..." : ""}`,
15877
- evidence: paths.slice(0, 3).map((path) => ({ path: redact(path), detector: "files" }))
15991
+ message: `${paths2.length} file(s) not analyzed (${reason}): ${paths2.slice(0, 5).map(redact).join(", ")}${paths2.length > 5 ? ", ..." : ""}`,
15992
+ evidence: paths2.slice(0, 3).map((path) => ({ path: redact(path), detector: "files" }))
15878
15993
  });
15879
15994
  }
15880
15995
  }
@@ -16063,7 +16178,7 @@ var RUNTIME_CATEGORIES = new Set(["prompt", "schema", "migration", "seed_data",
16063
16178
  var INERT = new Set(["test", "ci"]);
16064
16179
  var INERT_DIR = /(^|\/)(\.github|\.gitlab|\.circleci|\.buildkite|\.devcontainer|\.vscode|\.idea|\.cursor|\.claude|\.codex|\.windsurf|\.agents|\.husky|\.changeset|evals?|evaluations?|benchmarks?|\.?screenshots?|[\w.-]+-out)(\/|$)/;
16065
16180
  function harnessFiles(manifest, map, read) {
16066
- const paths = new Set(manifest.files.map((f) => f.path));
16181
+ const paths2 = new Set(manifest.files.map((f) => f.path));
16067
16182
  const root = map?.harness?.root ?? (manifest.harness.root || ".");
16068
16183
  const runtime = map?.runtimes.find((r) => r.root === root && r.kind === map.harness?.runtimeKind);
16069
16184
  const reached = new Set;
@@ -16073,27 +16188,27 @@ function harnessFiles(manifest, map, read) {
16073
16188
  if (d === "." || d === "")
16074
16189
  break;
16075
16190
  }
16076
- for (const p2 of paths)
16191
+ for (const p2 of paths2)
16077
16192
  if (ancestors.has(dirname5(p2)) && dirname5(p2) !== root && WORKSPACE_INPUT.test(basename3(p2)))
16078
16193
  reached.add(p2);
16079
16194
  for (const config of runtime?.kind === "cloudflare_workers" ? runtime.configFiles : []) {
16080
16195
  for (const dir of wranglerAssetDirs(config, read(config) ?? ""))
16081
- for (const p2 of paths)
16196
+ for (const p2 of paths2)
16082
16197
  if (isUnder2(p2, dir))
16083
16198
  reached.add(p2);
16084
16199
  }
16085
16200
  if (runtime?.kind === "cloudflare_workers") {
16086
- const entries = runtime.entrypoints.map((e) => (e.handler ?? "").split("#")[0]).filter((p2) => paths.has(p2));
16201
+ const entries = runtime.entrypoints.map((e) => (e.handler ?? "").split("#")[0]).filter((p2) => paths2.has(p2));
16087
16202
  if (entries.length > 0) {
16088
16203
  const workspacePackages = new Map;
16089
- for (const p2 of paths) {
16204
+ for (const p2 of paths2) {
16090
16205
  if (basename3(p2) !== "package.json")
16091
16206
  continue;
16092
16207
  const json = parseJsonLoose(read(p2) ?? "");
16093
16208
  if (isRecord(json) && typeof json.name === "string")
16094
16209
  workspacePackages.set(json.name, dirname5(p2));
16095
16210
  }
16096
- for (const f of importClosure({ entries, paths, read, workspacePackages }).files)
16211
+ for (const f of importClosure({ entries, paths: paths2, read, workspacePackages }).files)
16097
16212
  reached.add(f);
16098
16213
  }
16099
16214
  }
@@ -17769,6 +17884,8 @@ var TEXT_PRESERVING_METHODS = new Set([
17769
17884
  ]);
17770
17885
  var ARRAY_ASSEMBLY_METHODS = new Set(["join", "concat", "flat", "filter", "slice", "reverse", "sort", "toSorted"]);
17771
17886
  var CALLBACK_METHODS = new Set(["map", "flatMap", "then", "catch"]);
17887
+ var ARRAY_ELEMENT = "<array-element>";
17888
+ var FLATMAP_ELEMENT = "<flatmap-element>";
17772
17889
  var TEST_SOURCE = /(?:^|\/)(?:__tests__|__mocks__|fixtures?|test-fixtures)\/|(?:^|\/)[^/]*\.(?:test|spec)\.[^/]+$/i;
17773
17890
  var TEXT_MODULE = /\.(?:md|mdx|txt|prompt)(?:\?raw)?$/;
17774
17891
  var LOCAL_ONLY_SITE = /^(?:scripts|evals?)\//;
@@ -18072,6 +18189,9 @@ class PromptResolver {
18072
18189
  return;
18073
18190
  }
18074
18191
  const expr = unwrap2(node);
18192
+ if (walk.project[0] === FLATMAP_ELEMENT && (import_typescript8.default.isStringLiteral(expr) || import_typescript8.default.isNoSubstitutionTemplateLiteral(expr) || import_typescript8.default.isTemplateExpression(expr) || import_typescript8.default.isObjectLiteralExpression(expr))) {
18193
+ walk = { ...walk, project: walk.project.slice(1) };
18194
+ }
18075
18195
  if (walk.project.length > 0 && (import_typescript8.default.isStringLiteral(expr) || import_typescript8.default.isNoSubstitutionTemplateLiteral(expr) || import_typescript8.default.isTemplateExpression(expr) || import_typescript8.default.isBinaryExpression(expr) && expr.operatorToken.kind === import_typescript8.default.SyntaxKind.PlusToken)) {
18076
18196
  return;
18077
18197
  }
@@ -18106,6 +18226,16 @@ class PromptResolver {
18106
18226
  return;
18107
18227
  }
18108
18228
  if (import_typescript8.default.isArrayLiteralExpression(expr)) {
18229
+ if (walk.project[0] === ARRAY_ELEMENT || walk.project[0] === FLATMAP_ELEMENT) {
18230
+ const inner = { ...walk, project: walk.project.slice(1) };
18231
+ for (const element of expr.elements) {
18232
+ if (import_typescript8.default.isSpreadElement(element))
18233
+ this.value(element.expression, owner, walk);
18234
+ else
18235
+ this.value(element, owner, inner);
18236
+ }
18237
+ return;
18238
+ }
18109
18239
  if (/^\d+$/.test(walk.project[0] ?? "")) {
18110
18240
  const [index, ...rest] = walk.project;
18111
18241
  const selected = Number(index);
@@ -18300,7 +18430,7 @@ class PromptResolver {
18300
18430
  }
18301
18431
  const table = this.objectLiteralOf(access.expression);
18302
18432
  if (!table) {
18303
- this.value(access.expression, owner, walk);
18433
+ this.value(access.expression, owner, literalKey === undefined ? walk : { ...flag(walk, "projected"), project: [literalKey, ...walk.project] });
18304
18434
  return;
18305
18435
  }
18306
18436
  const next = this.step(literalKey ? walk : flag(walk, "dynamic-key"), access, literalKey ? `table field ${literalKey}` : "every field of a table read with a dynamic key");
@@ -18332,6 +18462,49 @@ class PromptResolver {
18332
18462
  this.value(callee.expression, owner, walk);
18333
18463
  return;
18334
18464
  }
18465
+ const checker = this.context.checkerFor(this.relative(callee.expression.getSourceFile().fileName));
18466
+ const receiverType = checker?.getTypeAtLocation(callee.expression);
18467
+ const arrayReceiver = import_typescript8.default.isArrayLiteralExpression(this.objectLiteralOf(callee.expression) ?? callee.expression) || !!checker && !!receiverType && (receiverType.isUnion() ? receiverType.types : [receiverType]).every((type) => checker.isArrayType(type) || checker.isTupleType(type));
18468
+ if ((method === "find" || method === "findLast") && arrayReceiver) {
18469
+ this.value(callee.expression, owner, { ...flag(walk, "dynamic-key"), project: [ARRAY_ELEMENT, ...walk.project] });
18470
+ return;
18471
+ }
18472
+ if ((method === "map" || method === "flatMap") && arrayReceiver && call.arguments[0]) {
18473
+ const callback = unwrap2(call.arguments[0]);
18474
+ const functions2 = import_typescript8.default.isArrowFunction(callback) || import_typescript8.default.isFunctionExpression(callback) ? [callback] : this.declarationsOf(callback).map(functionOf).filter((fn) => !!fn?.body);
18475
+ const output = walk.project[0];
18476
+ const indexed = /^\d+$/.test(output ?? "");
18477
+ if (method === "flatMap" && indexed) {
18478
+ this.markUnresolved(call, "dynamic-key", walk);
18479
+ return;
18480
+ }
18481
+ const eachOutput = output === ARRAY_ELEMENT || output === FLATMAP_ELEMENT;
18482
+ const callbackProject = eachOutput ? method === "flatMap" ? [FLATMAP_ELEMENT, ...walk.project.slice(1)] : walk.project.slice(1) : indexed ? walk.project.slice(1) : walk.project;
18483
+ const sourceProject = method === "map" && indexed ? output : ARRAY_ELEMENT;
18484
+ for (const fn of functions2) {
18485
+ const next = this.step({ ...walk, project: callbackProject }, fn, `array callback at ${this.where(call)}`);
18486
+ if (!next || walk.seen.has(fn))
18487
+ continue;
18488
+ next.bindings = new Map(next.bindings);
18489
+ bindParameters(fn, [callee.expression], walk.bindings, next.bindings);
18490
+ const first2 = fn.parameters[0];
18491
+ if (first2 && import_typescript8.default.isArrayBindingPattern(first2.name)) {
18492
+ first2.name.elements.forEach((element, index) => {
18493
+ if (import_typescript8.default.isBindingElement(element) && !element.dotDotDotToken && !element.initializer) {
18494
+ next.bindings.set(element, { expr: callee.expression, bindings: walk.bindings, project: [String(index)] });
18495
+ }
18496
+ });
18497
+ }
18498
+ for (const [declaration, binding] of next.bindings) {
18499
+ if (declaration === first2 || import_typescript8.default.isBindingElement(declaration) && parameterOf(declaration) === first2) {
18500
+ next.bindings.set(declaration, { ...binding, project: [sourceProject, ...binding.project ?? []] });
18501
+ }
18502
+ }
18503
+ this.builderBody(fn, owner ?? { node: fn, kind: "builder" }, next);
18504
+ }
18505
+ if (functions2.length)
18506
+ return;
18507
+ }
18335
18508
  if (CALLBACK_METHODS.has(method)) {
18336
18509
  const callbacks = call.arguments.map(unwrap2).filter((a) => import_typescript8.default.isArrowFunction(a) || import_typescript8.default.isFunctionExpression(a));
18337
18510
  for (const callback of callbacks)
@@ -18343,6 +18516,10 @@ class PromptResolver {
18343
18516
  this.value(callee.expression, owner, walk);
18344
18517
  return;
18345
18518
  }
18519
+ if (ARRAY_ASSEMBLY_METHODS.has(method) && /^\d+$/.test(walk.project[0] ?? "")) {
18520
+ this.markUnresolved(call, "dynamic-key", walk);
18521
+ return;
18522
+ }
18346
18523
  if (TEXT_PRESERVING_METHODS.has(method) || ARRAY_ASSEMBLY_METHODS.has(method)) {
18347
18524
  this.value(callee.expression, owner, walk);
18348
18525
  if (method === "concat")
@@ -18755,7 +18932,19 @@ class PromptResolver {
18755
18932
  parameter(declaration, at, owner, walk) {
18756
18933
  const bound = walk.bindings.get(declaration);
18757
18934
  if (bound) {
18758
- this.value(bound.expr, undefined, { ...walk, bindings: bound.bindings, project: [...bound.project ?? [], ...walk.project] });
18935
+ const project = [...bound.project ?? [], ...walk.project];
18936
+ if (bound.rest) {
18937
+ const each = project[0] === ARRAY_ELEMENT;
18938
+ const index2 = /^\d+$/.test(project[0] ?? "") ? Number(project[0]) : undefined;
18939
+ const values = index2 === undefined ? bound.rest : bound.rest.slice(index2, index2 + 1);
18940
+ for (const value of values)
18941
+ this.value(value, undefined, {
18942
+ ...walk,
18943
+ bindings: bound.bindings,
18944
+ project: each || index2 !== undefined ? project.slice(1) : project
18945
+ });
18946
+ } else
18947
+ this.value(bound.expr, undefined, { ...walk, bindings: bound.bindings, project });
18759
18948
  return;
18760
18949
  }
18761
18950
  const parameter = import_typescript8.default.isParameter(declaration) ? declaration : parameterOf(declaration);
@@ -19141,6 +19330,10 @@ function bindingField(element) {
19141
19330
  function bindParameters(fn, args, outer, into) {
19142
19331
  fn.parameters.forEach((parameter, index) => {
19143
19332
  const argument = args[index];
19333
+ if (parameter.dotDotDotToken && import_typescript8.default.isIdentifier(parameter.name)) {
19334
+ into.set(parameter, { expr: argument ?? parameter.name, bindings: outer, rest: args.slice(index) });
19335
+ return;
19336
+ }
19144
19337
  if (!argument)
19145
19338
  return;
19146
19339
  if (import_typescript8.default.isIdentifier(parameter.name)) {
@@ -19484,7 +19677,7 @@ async function runHarnessCommand(context) {
19484
19677
  report: {
19485
19678
  reportId: report.reportId,
19486
19679
  reportHash,
19487
- path: normalizePath2(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19680
+ path: normalizePath3(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19488
19681
  },
19489
19682
  validation,
19490
19683
  approval: {
@@ -19630,7 +19823,7 @@ async function runHarnessCommand(context) {
19630
19823
  throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
19631
19824
  }
19632
19825
  if (context.flags["github-actions"] === "true") {
19633
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-gt4qawvp.js");
19826
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-ma33g263.js");
19634
19827
  const result = await runGithubActionsAnalyze(rootDir, {
19635
19828
  writeReport: (report2) => {
19636
19829
  const normalized = normalizeHarnessReport(report2);
@@ -19757,7 +19950,7 @@ async function runHarnessCommand(context) {
19757
19950
  report: {
19758
19951
  reportId: approval.report.reportId,
19759
19952
  reportHash: hashHarnessReport(approval.report),
19760
- path: normalizePath2(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19953
+ path: normalizePath3(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19761
19954
  },
19762
19955
  validation: approval.validation,
19763
19956
  approval: approval.approval
@@ -19779,17 +19972,17 @@ async function runHarnessCommand(context) {
19779
19972
  if (promoteOut === "true") {
19780
19973
  throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
19781
19974
  }
19782
- const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19975
+ const { artifacts, unknowns, canonicalAgentIdentities } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19783
19976
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19784
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-xhcqg43k.js");
19785
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-n43wbr24.js");
19977
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-2bctz222.js");
19978
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-jvs3ksx6.js");
19786
19979
  let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19787
19980
  if (promote === "all" || promote === "topology" || promote === "tools") {
19788
19981
  const { result, ctx } = extractHarnessWithContext2(rootDir);
19789
19982
  const found = enumerateHarnessComponents(result, ctx);
19790
19983
  components = promote === "tools" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type === "tool") } : promote === "topology" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type !== "tool") } : found;
19791
19984
  }
19792
- const promoted = { concern: promote, unknowns, ...mergeEnumeratedComponents(artifacts, components) };
19985
+ const promoted = { concern: promote, unknowns, canonicalAgentIdentities, ...mergeEnumeratedComponents(artifacts, components) };
19793
19986
  const promoteWritten = [];
19794
19987
  if (promoteOut && !context.dryRun) {
19795
19988
  const target = resolve9(context.cwd, promoteOut);
@@ -19816,8 +20009,8 @@ async function runHarnessCommand(context) {
19816
20009
  }
19817
20010
  case "extract": {
19818
20011
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
19819
- const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-xhcqg43k.js");
19820
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-n43wbr24.js");
20012
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-2bctz222.js");
20013
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-jvs3ksx6.js");
19821
20014
  const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19822
20015
  const artifacts = deterministicArtifacts(rootDir);
19823
20016
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
@@ -20379,7 +20572,7 @@ function modelIdsUsedInSource(rootDir, ids) {
20379
20572
  const walk = (current) => {
20380
20573
  if (pending.size === 0)
20381
20574
  return false;
20382
- const rel2 = normalizePath2(relative9(rootReal, current)) || ".";
20575
+ const rel2 = normalizePath3(relative9(rootReal, current)) || ".";
20383
20576
  let stat;
20384
20577
  try {
20385
20578
  stat = lstatSync7(current);
@@ -20463,9 +20656,9 @@ function mergeDeterministicReplacement(report, rootDir, options) {
20463
20656
  mergeDeterministicArtifacts(report.graph, rootDir, options);
20464
20657
  const replacements = new Map;
20465
20658
  for (const artifact of old) {
20466
- const paths = artifactPaths(artifact);
20467
- const exact = report.graph.artifacts.filter((candidate) => candidate.type === artifact.type && artifactPaths(candidate).some((path) => paths.includes(path)));
20468
- const matches = exact.length ? exact : report.graph.artifacts.filter((candidate) => candidate.type === artifact.type && candidate.type === "eval" && artifactPaths(candidate).some((path) => paths.some((source) => evalSuiteKey(source) !== undefined && evalSuiteKey(source) === evalSuiteKey(path))));
20659
+ const paths2 = artifactPaths(artifact);
20660
+ const exact = report.graph.artifacts.filter((candidate) => candidate.type === artifact.type && artifactPaths(candidate).some((path) => paths2.includes(path)));
20661
+ const matches = exact.length ? exact : report.graph.artifacts.filter((candidate) => candidate.type === artifact.type && candidate.type === "eval" && artifactPaths(candidate).some((path) => paths2.some((source) => evalSuiteKey(source) !== undefined && evalSuiteKey(source) === evalSuiteKey(path))));
20469
20662
  replacements.set(artifact.id, matches);
20470
20663
  const owners = new Set([...artifact.usedByAgentIds ?? [], ...artifact.ownedByAgentId ? [artifact.ownedByAgentId] : []]);
20471
20664
  for (const link of agentLinks)
@@ -20537,6 +20730,7 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20537
20730
  mergeDeterministicReplacement(normalized, rootDir, options);
20538
20731
  if (!options.concern || options.concern === "topology")
20539
20732
  mergeBoundRuntimeClasses(normalized.graph, rootDir);
20733
+ remapCanonicalArtifactAgents(normalized.graph, normalized.graph.artifacts, !options.concern);
20540
20734
  tagComponentStatus(normalized.graph, rootDir);
20541
20735
  hydratePromptAndToolBodies(normalized.graph, rootDir);
20542
20736
  const unverified = new Set;
@@ -20570,8 +20764,8 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20570
20764
  const testOnlyModels = normalized.graph.artifacts.filter((artifact) => {
20571
20765
  if (artifact.type !== "model_config" || unverified.has(artifact.id))
20572
20766
  return false;
20573
- const paths = artifact.evidence.map((entry) => entry.path).filter((path) => typeof path === "string" && path.length > 0);
20574
- return paths.length > 0 && paths.every((path) => TEST_PATH3.test(path));
20767
+ const paths2 = artifact.evidence.map((entry) => entry.path).filter((path) => typeof path === "string" && path.length > 0);
20768
+ return paths2.length > 0 && paths2.every((path) => TEST_PATH3.test(path));
20575
20769
  });
20576
20770
  const usedInSource = testOnlyModels.length > 0 ? modelIdsUsedInSource(rootDir, testOnlyModels.map((artifact) => (artifact.name ?? "").trim())) : new Set;
20577
20771
  for (const artifact of testOnlyModels) {
@@ -20601,6 +20795,29 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20601
20795
  if (unverified.size > 0)
20602
20796
  removeArtifacts(normalized, unverified);
20603
20797
  deriveRelationshipsFromGraph(normalized.graph);
20798
+ if (!options.concern) {
20799
+ const knownAgents = new Set(normalized.graph.runtimeAgents.map((agent) => agent.id));
20800
+ for (const artifact of normalized.graph.artifacts) {
20801
+ if (artifact.type !== "tool" || !["in_prod", "reachable"].includes(artifact.status ?? ""))
20802
+ continue;
20803
+ const owners = [
20804
+ ...artifact.usedByAgentIds ?? [],
20805
+ ...artifact.ownedByAgentId ? [artifact.ownedByAgentId] : [],
20806
+ ...normalized.graph.runtimeAgents.filter((agent) => agent.artifactIds?.includes(artifact.id)).map((agent) => agent.id),
20807
+ ...normalized.graph.relationships.filter((edge) => edge.to === artifact.id && ["uses_artifact", "owns_artifact"].includes(edge.type)).map((edge) => edge.from)
20808
+ ];
20809
+ if (owners.some((owner) => knownAgents.has(owner)))
20810
+ continue;
20811
+ const id = `unresolved_tool_owner_${createHash7("sha256").update(artifact.id).digest("hex").slice(0, 16)}`;
20812
+ if (!normalized.graph.unknowns.some((unknown) => unknown.id === id))
20813
+ normalized.graph.unknowns.push({
20814
+ id,
20815
+ question: `Tool ${artifact.name} has a source definition but no source-proven owner in the hosted topology; trace evidence is required to resolve its agent.`,
20816
+ candidateIds: [artifact.id],
20817
+ evidence: artifact.evidence
20818
+ });
20819
+ }
20820
+ }
20604
20821
  dropUnlocatedAgentCitations(normalized);
20605
20822
  if ((normalized.claims?.length ?? 0) === 0 && deterministicOnlyArtifactTypes().has("eval")) {
20606
20823
  const grounded = createHarnessReport({ graph: {
@@ -20696,8 +20913,8 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
20696
20913
  evals: new Set(["model_config", "eval"])
20697
20914
  };
20698
20915
  async function deterministicFloorGraph(rootDir, options = {}) {
20699
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-xhcqg43k.js");
20700
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-n43wbr24.js");
20916
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-2bctz222.js");
20917
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-jvs3ksx6.js");
20701
20918
  const { result, ctx } = extractHarnessWithContext2(rootDir);
20702
20919
  const items = deterministicGraphItems(rootDir);
20703
20920
  const components = mergeEnumeratedComponents(items.artifacts, enumerateHarnessComponents(result, ctx));
@@ -20726,7 +20943,7 @@ function deterministicGraphItems(rootDir, concern) {
20726
20943
  const graph = { artifacts: [], unknowns: [] };
20727
20944
  mergeDeterministicArtifacts(graph, rootDir, { concern });
20728
20945
  hydratePromptAndToolBodies(graph, rootDir);
20729
- return { artifacts: graph.artifacts, unknowns: graph.unknowns };
20946
+ return { artifacts: graph.artifacts, unknowns: graph.unknowns, canonicalAgentIdentities: graph.scan?.canonicalAgentIdentities ?? [] };
20730
20947
  }
20731
20948
  var extractedModelsCache = new WeakMap;
20732
20949
  function extractedModelItems(rootDir) {
@@ -20861,9 +21078,16 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20861
21078
  } catch {}
20862
21079
  }
20863
21080
  const extractedIds = new Set(extracted.artifacts.map((artifact) => artifact.id));
21081
+ try {
21082
+ const { result, ctx } = extractHarnessWithContext(rootDir);
21083
+ const identities = harnessAgentIdentities(enumerateAgents(result, ctx).runtimeAgents);
21084
+ graph.scan ??= {};
21085
+ graph.scan.canonicalAgentIdentities = identities;
21086
+ remapCanonicalArtifactAgents(graph, promoted);
21087
+ } catch {}
20864
21088
  backfillRefutationEvidenceReasons(graph);
20865
21089
  const refuted = analystRefutations(graph);
20866
- const candidatePaths = new Set(promoted.flatMap((artifact) => artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath2(entry.path) : "").filter(Boolean)));
21090
+ const candidatePaths = new Set(promoted.flatMap((artifact) => artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath3(entry.path) : "").filter(Boolean)));
20867
21091
  const modelLineCounts = new Map;
20868
21092
  for (const artifact of promoted) {
20869
21093
  if (artifact.type !== "model_config")
@@ -20888,6 +21112,26 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20888
21112
  added += 1;
20889
21113
  continue;
20890
21114
  }
21115
+ if (artifact.type === "prompt" && artifact.usedByAgentIds.length > 0) {
21116
+ const existing = graph.artifacts.find((candidate) => candidate.type === "prompt" && candidate.id === artifact.id);
21117
+ if (existing && !isRefutedByAnalyst(artifact, refuted, candidatePaths)) {
21118
+ const definition = artifact.evidence[0];
21119
+ const stored = existing.evidence?.[0];
21120
+ if (definition && (!stored || stored.path === definition.path && stored.line === definition.line)) {
21121
+ existing.usedByAgentIds = [...new Set([...existing.usedByAgentIds ?? [], ...artifact.usedByAgentIds])];
21122
+ if (Array.isArray(existing.staticUsedByAgentIds))
21123
+ existing.staticUsedByAgentIds = [...new Set([...existing.staticUsedByAgentIds, ...artifact.usedByAgentIds])];
21124
+ if (existing.usedByAgentIds.length > 1)
21125
+ existing.scope = "shared";
21126
+ existing.evidence ??= [];
21127
+ for (const entry of artifact.evidence) {
21128
+ if (!existing.evidence.some((known) => known.path === entry.path && known.line === entry.line && known.reason === entry.reason))
21129
+ existing.evidence.push(entry);
21130
+ }
21131
+ continue;
21132
+ }
21133
+ }
21134
+ }
20891
21135
  if (graphCoversPromotedArtifact(graph, artifact, sharedModelLines))
20892
21136
  continue;
20893
21137
  if ((artifact.type === "model_config" || artifact.type === "eval") && artifact.evidence.length > 1 && !refuted.candidateIds.has(artifact.id)) {
@@ -20915,6 +21159,50 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20915
21159
  }
20916
21160
  return { added };
20917
21161
  }
21162
+ function remapCanonicalArtifactAgents(graph, artifacts = graph.artifacts, dropUnmapped = false) {
21163
+ const identities = harnessAgentIdentities(graph.scan?.canonicalAgentIdentities);
21164
+ const mapping = matchHarnessAgentIds(identities, graph.runtimeAgents ?? []);
21165
+ const canonical = new Map(identities.map((identity2) => [identity2.id, identity2]));
21166
+ const unresolved = new Map;
21167
+ const translate = (id, artifactId) => {
21168
+ const mapped = mapping.get(id);
21169
+ if (mapped || !dropUnmapped || !canonical.has(id))
21170
+ return mapped ?? id;
21171
+ const affected = unresolved.get(id) ?? [];
21172
+ if (!affected.includes(artifactId))
21173
+ affected.push(artifactId);
21174
+ unresolved.set(id, affected);
21175
+ return;
21176
+ };
21177
+ for (const artifact of artifacts) {
21178
+ artifact.usedByAgentIds = [...new Set((artifact.usedByAgentIds ?? []).flatMap((id) => translate(id, artifact.id) ?? []))];
21179
+ for (const field of ["staticUsedByAgentIds", "traceUsedByAgentIds"]) {
21180
+ if (Array.isArray(artifact[field]))
21181
+ artifact[field] = [...new Set(artifact[field].flatMap((id) => translate(id, artifact.id) ?? []))];
21182
+ }
21183
+ if (artifact.ownedByAgentId) {
21184
+ const owner = translate(artifact.ownedByAgentId, artifact.id);
21185
+ if (owner)
21186
+ artifact.ownedByAgentId = owner;
21187
+ else {
21188
+ delete artifact.ownedByAgentId;
21189
+ artifact.scope = "shared";
21190
+ }
21191
+ }
21192
+ }
21193
+ for (const [agentId, artifactIds] of unresolved) {
21194
+ const identity2 = canonical.get(agentId);
21195
+ const id = `unresolved_agent_links_${createHash7("sha256").update(agentId).digest("hex").slice(0, 16)}`;
21196
+ if (graph.unknowns.some((unknown) => unknown.id === id))
21197
+ continue;
21198
+ graph.unknowns.push({
21199
+ id,
21200
+ question: `Ownership for ${identity2.name} could not be matched uniquely to the hosted topology; its unresolved artifact links were omitted.`,
21201
+ candidateIds: artifactIds,
21202
+ evidence: (identity2.evidence ?? []).flatMap((entry) => entry.path ? [{ path: entry.path, ...entry.line !== undefined ? { line: entry.line } : {}, reason: entry.reason ?? "Extractor agent identity" }] : [])
21203
+ });
21204
+ }
21205
+ }
20918
21206
  function withCallSitePrompts(rootDir, promoted) {
20919
21207
  if (process.env.MODA_HARNESS_CALLSITE_PROMPTS === "0")
20920
21208
  return promoted;
@@ -20985,11 +21273,11 @@ function analystRefutations(graph) {
20985
21273
  if (typeof entry?.path !== "string" || !entry.path)
20986
21274
  continue;
20987
21275
  const line = typeof entry.line === "number" ? entry.line : undefined;
20988
- result.locations.push({ path: normalizePath2(entry.path), start: line, end: line, types: refutedTypes(entry.reason, question) });
21276
+ result.locations.push({ path: normalizePath3(entry.path), start: line, end: line, types: refutedTypes(entry.reason, question) });
20989
21277
  }
20990
21278
  for (const match of question.matchAll(/([\w./-]+\.[a-z0-9]{1,5})(?::|\s+(?:lines?\s+)?)(\d+)(?:\s*[-\u2013]\s*(\d+))?/gi)) {
20991
21279
  const start = Number(match[2]);
20992
- result.locations.push({ path: normalizePath2(match[1]), start, end: match[3] ? Number(match[3]) : start, types: refutedTypes(question) });
21280
+ result.locations.push({ path: normalizePath3(match[1]), start, end: match[3] ? Number(match[3]) : start, types: refutedTypes(question) });
20993
21281
  }
20994
21282
  }
20995
21283
  return result;
@@ -21008,7 +21296,7 @@ function isRefutedByAnalyst(artifact, refuted, candidatePaths) {
21008
21296
  return artifact.evidence.some((entry) => {
21009
21297
  if (typeof entry.path !== "string")
21010
21298
  return false;
21011
- const path = normalizePath2(entry.path);
21299
+ const path = normalizePath3(entry.path);
21012
21300
  return refuted.locations.some((location) => {
21013
21301
  if (location.types && !location.types.has(artifact.type))
21014
21302
  return false;
@@ -21024,9 +21312,9 @@ function isRefutedByAnalyst(artifact, refuted, candidatePaths) {
21024
21312
  }
21025
21313
  function artifactSourceKey(artifact) {
21026
21314
  if (artifact.sourcePath)
21027
- return normalizePath2(artifact.sourcePath);
21315
+ return normalizePath3(artifact.sourcePath);
21028
21316
  const pinned = Array.isArray(artifact.evidence) ? artifact.evidence.find((entry) => typeof entry.path === "string" && entry.path.length > 0) : undefined;
21029
- return pinned ? normalizePath2(pinned.path) : undefined;
21317
+ return pinned ? normalizePath3(pinned.path) : undefined;
21030
21318
  }
21031
21319
  function mentionsModelId(text, id) {
21032
21320
  if (!id)
@@ -21035,8 +21323,8 @@ function mentionsModelId(text, id) {
21035
21323
  return new RegExp(`(?<![\\w./@-])${escaped}(?![\\w/-]|\\.\\w)`, "i").test(text);
21036
21324
  }
21037
21325
  function artifactPaths(artifact) {
21038
- const paths = Array.isArray(artifact.evidence) ? artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath2(entry.path) : "").filter(Boolean) : [];
21039
- return artifact.sourcePath ? [normalizePath2(artifact.sourcePath), ...paths] : paths;
21326
+ const paths2 = Array.isArray(artifact.evidence) ? artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath3(entry.path) : "").filter(Boolean) : [];
21327
+ return artifact.sourcePath ? [normalizePath3(artifact.sourcePath), ...paths2] : paths2;
21040
21328
  }
21041
21329
  function graphCoversPromotedArtifact(graph, promoted, sharedModelLines = new Set) {
21042
21330
  if (promoted.type === "model_config" && graph.artifacts.some((existing) => existing.type === "model_config" && mentionsModelId(`${existing.name ?? ""}
@@ -21044,7 +21332,7 @@ ${existing.body ?? ""}`, promoted.name)))
21044
21332
  return true;
21045
21333
  if (promoted.type === "eval") {
21046
21334
  const suite = new Set(artifactPaths(promoted));
21047
- const suiteKey = promoted.sourcePath ? evalSuiteKey(normalizePath2(promoted.sourcePath)) : undefined;
21335
+ const suiteKey = promoted.sourcePath ? evalSuiteKey(normalizePath3(promoted.sourcePath)) : undefined;
21048
21336
  if (graph.artifacts.some((existing) => existing.type === "eval" && artifactPaths(existing).some((path) => suite.has(path) || suiteKey !== undefined && evalSuiteKey(path.replace(/\/+$/, "")) === suiteKey)))
21049
21337
  return true;
21050
21338
  }
@@ -22042,15 +22330,15 @@ function renderExternalAnalystProtocol(concern) {
22042
22330
  function renderAnalystPreflightSection(rootDir) {
22043
22331
  if (process.env.MODA_HARNESS_ANALYST_PREFLIGHT === "0")
22044
22332
  return "";
22045
- const paths = listAnalystPreflightPaths(rootDir);
22046
- if (paths.length === 0)
22333
+ const paths2 = listAnalystPreflightPaths(rootDir);
22334
+ if (paths2.length === 0)
22047
22335
  return "";
22048
22336
  const groups = {
22049
- manifests: paths.filter((path) => isManifestLikePath(path)).slice(0, 60),
22050
- docs: paths.filter((path) => isDocLikePath(path)).slice(0, 40),
22051
- source: paths.filter((path) => isAgentNavigationPath(path)).slice(0, 160),
22052
- deploy: paths.filter((path) => isPreflightDeployLikePath(path)).slice(0, 50),
22053
- evals: paths.filter((path) => isPreflightEvalLikePath(path)).slice(0, 50)
22337
+ manifests: paths2.filter((path) => isManifestLikePath(path)).slice(0, 60),
22338
+ docs: paths2.filter((path) => isDocLikePath(path)).slice(0, 40),
22339
+ source: paths2.filter((path) => isAgentNavigationPath(path)).slice(0, 160),
22340
+ deploy: paths2.filter((path) => isPreflightDeployLikePath(path)).slice(0, 50),
22341
+ evals: paths2.filter((path) => isPreflightEvalLikePath(path)).slice(0, 50)
22054
22342
  };
22055
22343
  const lines = [
22056
22344
  "",
@@ -22065,10 +22353,10 @@ function renderAnalystPreflightSection(rootDir) {
22065
22353
  return lines.join(`
22066
22354
  `);
22067
22355
  }
22068
- function renderPreflightGroup(label, paths) {
22069
- if (paths.length === 0)
22356
+ function renderPreflightGroup(label, paths2) {
22357
+ if (paths2.length === 0)
22070
22358
  return [];
22071
- return [`${label}:`, ...paths.map((path) => `- ${path}`)];
22359
+ return [`${label}:`, ...paths2.map((path) => `- ${path}`)];
22072
22360
  }
22073
22361
  var MAX_SEED_ARTIFACT_LINES = 150;
22074
22362
  function renderAnalystSeedSection(rootDir, concern) {
@@ -22172,8 +22460,8 @@ function renderAnalystSeedLines(graph) {
22172
22460
  }
22173
22461
  function listAnalystPreflightPaths(rootDir) {
22174
22462
  const gitPaths = readGitTrackedPaths(rootDir);
22175
- const paths = gitPaths.length > 0 ? gitPaths : readDirectoryPreflightPaths(rootDir);
22176
- return [...new Set(paths.map(normalizePath2))].filter((path) => path && !shouldSkipPreflightPath(path)).sort();
22463
+ const paths2 = gitPaths.length > 0 ? gitPaths : readDirectoryPreflightPaths(rootDir);
22464
+ return [...new Set(paths2.map(normalizePath3))].filter((path) => path && !shouldSkipPreflightPath(path)).sort();
22177
22465
  }
22178
22466
  function readGitTrackedPaths(rootDir) {
22179
22467
  try {
@@ -22187,9 +22475,9 @@ function readGitTrackedPaths(rootDir) {
22187
22475
  }
22188
22476
  }
22189
22477
  function readDirectoryPreflightPaths(rootDir) {
22190
- const paths = [];
22478
+ const paths2 = [];
22191
22479
  const stack = ["."];
22192
- while (stack.length > 0 && paths.length < 2000) {
22480
+ while (stack.length > 0 && paths2.length < 2000) {
22193
22481
  const current = stack.pop() ?? ".";
22194
22482
  const absolute = current === "." ? rootDir : join11(rootDir, current);
22195
22483
  let entries;
@@ -22214,14 +22502,14 @@ function readDirectoryPreflightPaths(rootDir) {
22214
22502
  if (stat.isDirectory()) {
22215
22503
  stack.push(child);
22216
22504
  } else {
22217
- paths.push(child);
22505
+ paths2.push(child);
22218
22506
  }
22219
22507
  }
22220
22508
  }
22221
- return paths;
22509
+ return paths2;
22222
22510
  }
22223
22511
  function shouldSkipPreflightPath(path) {
22224
- const normalized = normalizePath2(path);
22512
+ const normalized = normalizePath3(path);
22225
22513
  if (!normalized || normalized.startsWith(".moda/"))
22226
22514
  return true;
22227
22515
  const parts = normalized.split("/");
@@ -22346,7 +22634,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
22346
22634
  let inventoryFileCount = 0;
22347
22635
  let inventoryTextBytes = 0;
22348
22636
  function walk(current) {
22349
- const path = normalizePath2(relative9(rootDir, current)) || ".";
22637
+ const path = normalizePath3(relative9(rootDir, current)) || ".";
22350
22638
  let stat;
22351
22639
  try {
22352
22640
  stat = lstatSync7(current);
@@ -22417,7 +22705,7 @@ function buildSourceSnapshot(rootDir) {
22417
22705
  }
22418
22706
  function buildCommandScanPlan(context, rootDir) {
22419
22707
  const explicitPath = context.flags.path !== undefined;
22420
- const rel2 = normalizePath2(relative9(context.cwd, rootDir)) || ".";
22708
+ const rel2 = normalizePath3(relative9(context.cwd, rootDir)) || ".";
22421
22709
  const scope = explicitPath && rel2 !== "." ? "narrow" : "broad";
22422
22710
  const machineReadable = context.outputMode !== "human";
22423
22711
  const approvalRequired = context.positional === "analyze" && scope === "broad" && !context.yes;
@@ -22502,7 +22790,7 @@ function writeHumanBlock(context, message) {
22502
22790
  function buildHarnessReadPlan(rootDir, pathWasExplicit) {
22503
22791
  return {
22504
22792
  scope: pathWasExplicit ? "narrow" : "broad",
22505
- rootPaths: [normalizePath2(relative9(rootDir, rootDir)) || "."],
22793
+ rootPaths: [normalizePath3(relative9(rootDir, rootDir)) || "."],
22506
22794
  willRead: [
22507
22795
  "package manifests",
22508
22796
  "source files under the selected path",
@@ -22715,7 +23003,7 @@ function findFresherHarnessReports(rootDir) {
22715
23003
  const candidate = lstatSync7(join11(child, HARNESS_REPORT_PATH));
22716
23004
  if (candidate.isFile() && candidate.mtimeMs > rootMtimeMs) {
22717
23005
  fresher.push({
22718
- path: normalizePath2(relative9(rootDir, join11(child, HARNESS_REPORT_PATH))),
23006
+ path: normalizePath3(relative9(rootDir, join11(child, HARNESS_REPORT_PATH))),
22719
23007
  mtimeMs: candidate.mtimeMs
22720
23008
  });
22721
23009
  }
@@ -22727,8 +23015,8 @@ function findFresherHarnessReports(rootDir) {
22727
23015
  return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
22728
23016
  }
22729
23017
  function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
22730
- const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath2(relative9(rootDir, resolve9(rootDir, explicitReport))) : undefined;
22731
- if (explicitReportPath && explicitReportPath !== normalizePath2(HARNESS_REPORT_PATH))
23018
+ const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative9(rootDir, resolve9(rootDir, explicitReport))) : undefined;
23019
+ if (explicitReportPath && explicitReportPath !== normalizePath3(HARNESS_REPORT_PATH))
22732
23020
  return;
22733
23021
  let fresher;
22734
23022
  try {
@@ -22739,7 +23027,7 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
22739
23027
  if (fresher.length === 0)
22740
23028
  return;
22741
23029
  const newest = fresher[0];
22742
- const subdir = normalizePath2(dirname8(dirname8(newest.path)));
23030
+ const subdir = normalizePath3(dirname8(dirname8(newest.path)));
22743
23031
  const rootState = existsSync8(join11(rootDir, HARNESS_REPORT_PATH)) ? `older ${HARNESS_REPORT_PATH}` : `no ${HARNESS_REPORT_PATH}`;
22744
23032
  writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
22745
23033
  }
@@ -22934,7 +23222,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
22934
23222
  const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
22935
23223
  let textBytes = 0;
22936
23224
  function walk(current) {
22937
- const rel2 = normalizePath2(relative9(rootReal, current)) || ".";
23225
+ const rel2 = normalizePath3(relative9(rootReal, current)) || ".";
22938
23226
  let stat;
22939
23227
  try {
22940
23228
  stat = lstatSync7(current);
@@ -23150,7 +23438,7 @@ function runtimeAgentFromAnnotation(annotation) {
23150
23438
  kind: "runtime_agent",
23151
23439
  purpose: first2(values.purpose) ?? first2(values.description),
23152
23440
  familyId: first2(values.family),
23153
- root: normalizePath2(first2(values.root) ?? dirname8(annotation.evidence.path)),
23441
+ root: normalizePath3(first2(values.root) ?? dirname8(annotation.evidence.path)),
23154
23442
  entrypointIds: values.entrypoint ?? [stableId("entry", annotation.evidence.path)],
23155
23443
  channelAdapterIds: values.channel ?? [],
23156
23444
  artifactIds: [...values.artifact ?? [], ...values.prompt ?? [], ...values.tool ?? []],
@@ -23386,7 +23674,7 @@ function inferRuntimeAgent(file, graph) {
23386
23674
  name: titleFromId(file.path.replace(/\.(ts|tsx|js|mjs|py)$/i, "")),
23387
23675
  kind: "runtime_agent",
23388
23676
  purpose: inferAgentPurpose(file),
23389
- root: normalizePath2(dirname8(file.path)),
23677
+ root: normalizePath3(dirname8(file.path)),
23390
23678
  entrypointIds: [entryId],
23391
23679
  channelAdapterIds: channelIds,
23392
23680
  artifactIds,
@@ -24285,7 +24573,7 @@ function contentHashForAnnotatedSource(sourcePath, annotation) {
24285
24573
  function readSmallTextFileForHash(absPath, rootDir) {
24286
24574
  if (!existsSync8(absPath))
24287
24575
  return;
24288
- const rel2 = normalizePath2(relative9(rootDir, absPath));
24576
+ const rel2 = normalizePath3(relative9(rootDir, absPath));
24289
24577
  if (isSecretishPath(rel2))
24290
24578
  return;
24291
24579
  let stat;
@@ -24386,7 +24674,7 @@ function titleFromId(id) {
24386
24674
  function promptNameFromPath(path) {
24387
24675
  return titleFromId(basename6(path).replace(/\.(prompt\.)?(md|json|ya?ml)$/i, ""));
24388
24676
  }
24389
- function normalizePath2(path) {
24677
+ function normalizePath3(path) {
24390
24678
  return path.split(sep5).join("/");
24391
24679
  }
24392
24680
  function hashText(text) {
@@ -27112,8 +27400,8 @@ function collectModels(result, ctx) {
27112
27400
  const context = modelPathContext(result.rootDir);
27113
27401
  const harnessPath = (path) => isHarnessModelPath(path, context);
27114
27402
  for (const [id, entry] of byId) {
27115
- const paths = [...entry.definitions.map((at) => at.path), ...entry.sites.map((site) => site.path)];
27116
- if (!paths.some(harnessPath))
27403
+ const paths2 = [...entry.definitions.map((at) => at.path), ...entry.sites.map((site) => site.path)];
27404
+ if (!paths2.some(harnessPath))
27117
27405
  byId.delete(id);
27118
27406
  }
27119
27407
  const kept = unresolved.filter((entry) => harnessPath(entry.path));
@@ -27430,7 +27718,7 @@ function enumerationRepository(ctx) {
27430
27718
  };
27431
27719
  walk(ctx.rootDir);
27432
27720
  const workers = [];
27433
- const paths = new Set(files.map((file) => file.path));
27721
+ const paths2 = new Set(files.map((file) => file.path));
27434
27722
  const closure = (main) => {
27435
27723
  const found = new Set, pending = [main];
27436
27724
  for (let index = 0;index < pending.length; index++) {
@@ -27445,7 +27733,7 @@ function enumerationRepository(ctx) {
27445
27733
  if (!ref.fileName.startsWith("."))
27446
27734
  continue;
27447
27735
  const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
27448
- const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
27736
+ const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths2.has(candidate));
27449
27737
  if (target)
27450
27738
  pending.push(target);
27451
27739
  }
@@ -29046,7 +29334,7 @@ function runExtract(rootDir, options) {
29046
29334
  return /\.svelte$/i.test(abs) ? svelteVirtualName(abs) : abs;
29047
29335
  };
29048
29336
  const lookup = (path) => repo?.owner.get(fileKey(path));
29049
- const sourceFile = (path) => lookup(path)?.program.getSourceFile(fileKey(path));
29337
+ const sourceFile2 = (path) => lookup(path)?.program.getSourceFile(fileKey(path));
29050
29338
  let files;
29051
29339
  const ctx = {
29052
29340
  rootDir,
@@ -29055,7 +29343,7 @@ function runExtract(rootDir, options) {
29055
29343
  checkerFor: (path) => lookup(path)?.checker(),
29056
29344
  sourceFiles: () => files ??= [...repo?.owner.entries() ?? []].filter(([file]) => !isTestPath(relPath(rootDir, file))).map(([file, entry]) => entry.program.getSourceFile(file)).filter((file) => Boolean(file)),
29057
29345
  nodeAt: (ref) => {
29058
- const source = sourceFile(ref.path);
29346
+ const source = sourceFile2(ref.path);
29059
29347
  return source ? nodeSpanning(source, ref.start, ref.end) : undefined;
29060
29348
  }
29061
29349
  };
@@ -30009,8 +30297,8 @@ function mergeEnumeratedComponents(artifacts, components) {
30009
30297
  const candidates = extractedByName.get(item.name) ?? [];
30010
30298
  if (candidates.length === 0)
30011
30299
  return item.id.startsWith("tool:catalog:") ? `tool:${item.id}` : `tool:${item.name}`;
30012
- const paths = new Set([item.sourcePath, ...item.evidence.map((entry) => entry.path)].filter(Boolean));
30013
- const target = candidates.find((candidate) => candidate.sourcePath && paths.has(candidate.sourcePath) || candidate.definitionVariants?.some((variant) => variant.sourcePath && paths.has(variant.sourcePath))) ?? candidates.find((candidate) => !candidate.id.includes("@")) ?? candidates[0];
30300
+ const paths2 = new Set([item.sourcePath, ...item.evidence.map((entry) => entry.path)].filter(Boolean));
30301
+ const target = candidates.find((candidate) => candidate.sourcePath && paths2.has(candidate.sourcePath) || candidate.definitionVariants?.some((variant) => variant.sourcePath && paths2.has(variant.sourcePath))) ?? candidates.find((candidate) => !candidate.id.includes("@")) ?? candidates[0];
30014
30302
  return `tool:${target.id}`;
30015
30303
  };
30016
30304
  for (const item of [...registry, ...artifacts, ...components.artifacts.filter((item2) => !registry.includes(item2))]) {