@moda-ai/cli 1.55.84 → 1.55.86

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?)\//;
@@ -17955,6 +18072,8 @@ class PromptResolver {
17955
18072
  callersByName = new Map;
17956
18073
  aliasesByName = new Map;
17957
18074
  callersIndexed = false;
18075
+ resolvedCallers = new WeakMap;
18076
+ locallyWrittenParameters = new WeakMap;
17958
18077
  methodIndex;
17959
18078
  constructor(context, options) {
17960
18079
  this.context = context;
@@ -18072,6 +18191,9 @@ class PromptResolver {
18072
18191
  return;
18073
18192
  }
18074
18193
  const expr = unwrap2(node);
18194
+ 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))) {
18195
+ walk = { ...walk, project: walk.project.slice(1) };
18196
+ }
18075
18197
  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
18198
  return;
18077
18199
  }
@@ -18106,6 +18228,16 @@ class PromptResolver {
18106
18228
  return;
18107
18229
  }
18108
18230
  if (import_typescript8.default.isArrayLiteralExpression(expr)) {
18231
+ if (walk.project[0] === ARRAY_ELEMENT || walk.project[0] === FLATMAP_ELEMENT) {
18232
+ const inner = { ...walk, project: walk.project.slice(1) };
18233
+ for (const element of expr.elements) {
18234
+ if (import_typescript8.default.isSpreadElement(element))
18235
+ this.value(element.expression, owner, walk);
18236
+ else
18237
+ this.value(element, owner, inner);
18238
+ }
18239
+ return;
18240
+ }
18109
18241
  if (/^\d+$/.test(walk.project[0] ?? "")) {
18110
18242
  const [index, ...rest] = walk.project;
18111
18243
  const selected = Number(index);
@@ -18300,7 +18432,7 @@ class PromptResolver {
18300
18432
  }
18301
18433
  const table = this.objectLiteralOf(access.expression);
18302
18434
  if (!table) {
18303
- this.value(access.expression, owner, walk);
18435
+ this.value(access.expression, owner, literalKey === undefined ? walk : { ...flag(walk, "projected"), project: [literalKey, ...walk.project] });
18304
18436
  return;
18305
18437
  }
18306
18438
  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 +18464,89 @@ class PromptResolver {
18332
18464
  this.value(callee.expression, owner, walk);
18333
18465
  return;
18334
18466
  }
18467
+ const checker = this.context.checkerFor(this.relative(callee.expression.getSourceFile().fileName));
18468
+ const arrayType = (type, awaited = false) => {
18469
+ if (!type)
18470
+ return false;
18471
+ if (import_typescript8.default.isArrayTypeNode(type) || import_typescript8.default.isTupleTypeNode(type))
18472
+ return true;
18473
+ if (import_typescript8.default.isTypeOperatorNode(type))
18474
+ return arrayType(type.type, awaited);
18475
+ if (!import_typescript8.default.isTypeReferenceNode(type))
18476
+ return false;
18477
+ const name = type.typeName.getText();
18478
+ return /^(?:Readonly)?Array$/.test(name) || awaited && name === "Promise" && arrayType(type.typeArguments?.[0]);
18479
+ };
18480
+ const arraySeen = new Set;
18481
+ const isArrayReceiver = (expression, awaited = false) => {
18482
+ const raw = unwrapNode(expression);
18483
+ if (import_typescript8.default.isAwaitExpression(raw))
18484
+ return isArrayReceiver(raw.expression, true);
18485
+ const receiver = unwrap2(expression);
18486
+ if (arraySeen.has(receiver))
18487
+ return false;
18488
+ arraySeen.add(receiver);
18489
+ if (import_typescript8.default.isAwaitExpression(receiver))
18490
+ return isArrayReceiver(receiver.expression, true);
18491
+ if (import_typescript8.default.isIdentifier(receiver)) {
18492
+ for (const declaration of this.declarationsOf(receiver)) {
18493
+ if ((import_typescript8.default.isVariableDeclaration(declaration) || import_typescript8.default.isParameter(declaration)) && (arrayType(declaration.type) || declaration.initializer && isArrayReceiver(declaration.initializer)))
18494
+ return true;
18495
+ }
18496
+ }
18497
+ if (import_typescript8.default.isCallExpression(receiver)) {
18498
+ for (const declaration of this.declarationsOf(import_typescript8.default.isPropertyAccessExpression(receiver.expression) ? receiver.expression.name : receiver.expression)) {
18499
+ const fn = functionOf(declaration);
18500
+ if (fn && arrayType(fn.type, awaited))
18501
+ return true;
18502
+ }
18503
+ }
18504
+ const type = checker?.getTypeAtLocation(receiver);
18505
+ if (import_typescript8.default.isArrayLiteralExpression(this.objectLiteralOf(receiver) ?? receiver) || !!checker && !!type && (type.isUnion() ? type.types : [type]).every((item) => checker.isArrayType(item) || checker.isTupleType(item)))
18506
+ return true;
18507
+ return import_typescript8.default.isCallExpression(receiver) && import_typescript8.default.isPropertyAccessExpression(receiver.expression) && ARRAY_ASSEMBLY_METHODS.has(receiver.expression.name.text) && receiver.expression.name.text !== "join" && isArrayReceiver(receiver.expression.expression);
18508
+ };
18509
+ const arrayReceiver = isArrayReceiver(callee.expression);
18510
+ if ((method === "find" || method === "findLast") && arrayReceiver) {
18511
+ this.value(callee.expression, owner, { ...flag(walk, "dynamic-key"), project: [ARRAY_ELEMENT, ...walk.project] });
18512
+ return;
18513
+ }
18514
+ if ((method === "map" || method === "flatMap") && arrayReceiver && call.arguments[0]) {
18515
+ const callback = unwrap2(call.arguments[0]);
18516
+ const functions2 = import_typescript8.default.isArrowFunction(callback) || import_typescript8.default.isFunctionExpression(callback) ? [callback] : this.declarationsOf(callback).map(functionOf).filter((fn) => !!fn?.body);
18517
+ const output = walk.project[0];
18518
+ const indexed = /^\d+$/.test(output ?? "");
18519
+ if (method === "flatMap" && indexed) {
18520
+ this.markUnresolved(call, "dynamic-key", walk);
18521
+ return;
18522
+ }
18523
+ const eachOutput = output === ARRAY_ELEMENT || output === FLATMAP_ELEMENT;
18524
+ const callbackProject = eachOutput ? method === "flatMap" ? [FLATMAP_ELEMENT, ...walk.project.slice(1)] : walk.project.slice(1) : indexed ? walk.project.slice(1) : walk.project;
18525
+ const sourceProject = method === "map" && indexed ? output : ARRAY_ELEMENT;
18526
+ for (const fn of functions2) {
18527
+ const next = this.step({ ...walk, project: callbackProject }, fn, `array callback at ${this.where(call)}`);
18528
+ if (!next || walk.seen.has(fn))
18529
+ continue;
18530
+ next.bindings = new Map(next.bindings);
18531
+ bindParameters(fn, [callee.expression], walk.bindings, next.bindings);
18532
+ const first2 = fn.parameters[0];
18533
+ if (first2 && import_typescript8.default.isArrayBindingPattern(first2.name)) {
18534
+ first2.name.elements.forEach((element, index) => {
18535
+ if (import_typescript8.default.isBindingElement(element) && !element.dotDotDotToken && !element.initializer) {
18536
+ next.bindings.set(element, { expr: callee.expression, bindings: walk.bindings, project: [String(index)] });
18537
+ }
18538
+ });
18539
+ }
18540
+ for (const [declaration, binding] of next.bindings) {
18541
+ if (declaration === first2 || import_typescript8.default.isBindingElement(declaration) && parameterOf(declaration) === first2) {
18542
+ next.bindings.set(declaration, { ...binding, project: [sourceProject, ...binding.project ?? []] });
18543
+ }
18544
+ }
18545
+ this.builderBody(fn, owner ?? { node: fn, kind: "builder" }, next);
18546
+ }
18547
+ if (functions2.length)
18548
+ return;
18549
+ }
18335
18550
  if (CALLBACK_METHODS.has(method)) {
18336
18551
  const callbacks = call.arguments.map(unwrap2).filter((a) => import_typescript8.default.isArrowFunction(a) || import_typescript8.default.isFunctionExpression(a));
18337
18552
  for (const callback of callbacks)
@@ -18343,6 +18558,10 @@ class PromptResolver {
18343
18558
  this.value(callee.expression, owner, walk);
18344
18559
  return;
18345
18560
  }
18561
+ if (ARRAY_ASSEMBLY_METHODS.has(method) && /^\d+$/.test(walk.project[0] ?? "")) {
18562
+ this.markUnresolved(call, "dynamic-key", walk);
18563
+ return;
18564
+ }
18346
18565
  if (TEXT_PRESERVING_METHODS.has(method) || ARRAY_ASSEMBLY_METHODS.has(method)) {
18347
18566
  this.value(callee.expression, owner, walk);
18348
18567
  if (method === "concat")
@@ -18393,6 +18612,10 @@ class PromptResolver {
18393
18612
  if (walk.seen.has(fn))
18394
18613
  continue;
18395
18614
  const name = functionName2(fn);
18615
+ if (walk.depth + 1 > this.maxDepth) {
18616
+ this.markUnresolved(call, "depth-limit", walk);
18617
+ continue;
18618
+ }
18396
18619
  const next = this.step(walk, fn, `builder ${name ?? "function"} called at ${this.where(call)}`);
18397
18620
  if (!next)
18398
18621
  continue;
@@ -18499,6 +18722,8 @@ class PromptResolver {
18499
18722
  return;
18500
18723
  }
18501
18724
  if (import_typescript8.default.isVariableDeclaration(declaration)) {
18725
+ if (/^\d+$/.test(next.project[0] ?? "") && this.assembly(declaration, ownerFor(declaration, name, owner), next, at, true))
18726
+ return;
18502
18727
  if (!owner && next.flags.includes("interpolated") && declaration.initializer) {
18503
18728
  let scope = declaration.parent;
18504
18729
  while (scope && !import_typescript8.default.isFunctionLike(scope))
@@ -18572,12 +18797,12 @@ class PromptResolver {
18572
18797
  if (fn)
18573
18798
  this.builderBody(fn, { node: declaration, name, kind: "builder" }, next);
18574
18799
  }
18575
- assembly(declaration, owner, walk, at) {
18800
+ assembly(declaration, owner, walk, at, probe = false) {
18576
18801
  if (!import_typescript8.default.isIdentifier(declaration.name))
18577
- return;
18802
+ return false;
18578
18803
  const scope = enclosingScope2(declaration);
18579
18804
  if (!scope)
18580
- return;
18805
+ return false;
18581
18806
  const assignments = [];
18582
18807
  const findRebinding = (node) => {
18583
18808
  if (import_typescript8.default.isFunctionLike(node))
@@ -18623,7 +18848,7 @@ class PromptResolver {
18623
18848
  return new Set;
18624
18849
  const next = new Set(seen).add(value);
18625
18850
  if (import_typescript8.default.isIdentifier(value)) {
18626
- const entry = this.declarationsOf(value).find((item) => import_typescript8.default.isVariableDeclaration(item));
18851
+ const entry = this.declarationsOf(value).find((item) => import_typescript8.default.isVariableDeclaration(item) || import_typescript8.default.isParameter(item));
18627
18852
  if (entry === declaration)
18628
18853
  return versionsAt(value);
18629
18854
  if (entry && import_typescript8.default.isVariableDeclaration(entry) && entry.initializer && entry.parent.flags & import_typescript8.default.NodeFlags.Const)
@@ -18734,15 +18959,24 @@ class PromptResolver {
18734
18959
  });
18735
18960
  };
18736
18961
  const isThis = (identifier) => references(identifier);
18962
+ let indexedMutation = false;
18737
18963
  const visit = (node) => {
18738
18964
  if (import_typescript8.default.isFunctionLike(node) && !invoked(node))
18739
18965
  return;
18740
18966
  if (import_typescript8.default.isCallExpression(node) && import_typescript8.default.isPropertyAccessExpression(node.expression) && references(node.expression.expression) && /^(?:push|unshift|splice)$/.test(node.expression.name.text)) {
18967
+ if (/^\d+$/.test(walk.project[0] ?? "")) {
18968
+ indexedMutation = true;
18969
+ this.markUnresolved(node, "dynamic-key", walk);
18970
+ return;
18971
+ }
18972
+ if (probe)
18973
+ return;
18741
18974
  const args = node.expression.name.text === "splice" ? node.arguments.slice(2) : node.arguments;
18975
+ const elementWalk = walk.project[0] === ARRAY_ELEMENT || walk.project[0] === FLATMAP_ELEMENT ? { ...walk, project: walk.project.slice(1) } : walk;
18742
18976
  for (const argument of args)
18743
- this.value(argument, owner, walk);
18977
+ this.value(argument, owner, elementWalk);
18744
18978
  }
18745
- if (import_typescript8.default.isBinaryExpression(node) && import_typescript8.default.isIdentifier(node.left) && (isThis(node.left) || readVersions.has(node))) {
18979
+ if (!probe && import_typescript8.default.isBinaryExpression(node) && import_typescript8.default.isIdentifier(node.left) && (isThis(node.left) || readVersions.has(node))) {
18746
18980
  if (node.operatorToken.kind === import_typescript8.default.SyntaxKind.PlusEqualsToken)
18747
18981
  this.value(node.right, owner, walk);
18748
18982
  if (node.operatorToken.kind === import_typescript8.default.SyntaxKind.EqualsToken && node.right !== declaration.initializer)
@@ -18751,11 +18985,52 @@ class PromptResolver {
18751
18985
  import_typescript8.default.forEachChild(node, visit);
18752
18986
  };
18753
18987
  visit(scope);
18988
+ return indexedMutation;
18989
+ }
18990
+ parameterHasLocalWrites(parameter) {
18991
+ const cached = this.locallyWrittenParameters.get(parameter);
18992
+ if (cached !== undefined)
18993
+ return cached;
18994
+ let written = false;
18995
+ const name = import_typescript8.default.isIdentifier(parameter.name) ? parameter.name.text : undefined;
18996
+ const scope = enclosingScope2(parameter);
18997
+ const isParameter = (expression) => import_typescript8.default.isIdentifier(expression) && expression.text === name && this.declarationsOf(expression).includes(parameter);
18998
+ const visit = (node) => {
18999
+ if (written)
19000
+ return;
19001
+ if (import_typescript8.default.isBinaryExpression(node) && [import_typescript8.default.SyntaxKind.EqualsToken, import_typescript8.default.SyntaxKind.PlusEqualsToken].includes(node.operatorToken.kind)) {
19002
+ written = isParameter(node.left) || import_typescript8.default.isElementAccessExpression(node.left) && isParameter(node.left.expression);
19003
+ } else if (import_typescript8.default.isCallExpression(node) && import_typescript8.default.isPropertyAccessExpression(node.expression) && /^(?:push|unshift|splice)$/.test(node.expression.name.text)) {
19004
+ written = isParameter(node.expression.expression);
19005
+ }
19006
+ if (!written)
19007
+ import_typescript8.default.forEachChild(node, visit);
19008
+ };
19009
+ if (scope)
19010
+ visit(scope);
19011
+ this.locallyWrittenParameters.set(parameter, written);
19012
+ return written;
18754
19013
  }
18755
19014
  parameter(declaration, at, owner, walk) {
19015
+ if (import_typescript8.default.isParameter(declaration) && import_typescript8.default.isIdentifier(declaration.name) && !walk.seen.has(declaration) && this.parameterHasLocalWrites(declaration)) {
19016
+ const local = { ...walk, seen: new Set(walk.seen).add(declaration) };
19017
+ this.assembly(declaration, owner, local, at);
19018
+ }
18756
19019
  const bound = walk.bindings.get(declaration);
18757
19020
  if (bound) {
18758
- this.value(bound.expr, undefined, { ...walk, bindings: bound.bindings, project: [...bound.project ?? [], ...walk.project] });
19021
+ const project = [...bound.project ?? [], ...walk.project];
19022
+ if (bound.rest) {
19023
+ const each = project[0] === ARRAY_ELEMENT;
19024
+ const index2 = /^\d+$/.test(project[0] ?? "") ? Number(project[0]) : undefined;
19025
+ const values = index2 === undefined ? bound.rest : bound.rest.slice(index2, index2 + 1);
19026
+ for (const value of values)
19027
+ this.value(value, undefined, {
19028
+ ...walk,
19029
+ bindings: bound.bindings,
19030
+ project: each || index2 !== undefined ? project.slice(1) : project
19031
+ });
19032
+ } else
19033
+ this.value(bound.expr, undefined, { ...walk, bindings: bound.bindings, project });
18759
19034
  return;
18760
19035
  }
18761
19036
  const parameter = import_typescript8.default.isParameter(declaration) ? declaration : parameterOf(declaration);
@@ -18802,6 +19077,9 @@ class PromptResolver {
18802
19077
  }
18803
19078
  }
18804
19079
  callersOf(fn) {
19080
+ const cached = this.resolvedCallers.get(fn);
19081
+ if (cached)
19082
+ return cached;
18805
19083
  const name = functionName2(fn);
18806
19084
  if (!name)
18807
19085
  return [];
@@ -18809,12 +19087,14 @@ class PromptResolver {
18809
19087
  const names = [name, ...this.aliasesByName.get(name) ?? []];
18810
19088
  const candidates = names.flatMap((alias) => this.callersByName.get(alias) ?? []);
18811
19089
  const signatures = this.implementedSignatures(fn, name);
18812
- return candidates.filter((call) => {
19090
+ const callers = candidates.filter((call) => {
18813
19091
  const callee = import_typescript8.default.isPropertyAccessExpression(call.expression) ? call.expression.name : call.expression;
18814
19092
  const checker = this.context.checkerFor(this.relative(call.getSourceFile().fileName));
18815
19093
  const members = checker && import_typescript8.default.isPropertyAccessExpression(call.expression) ? receiverClasses(call.expression.expression, checker).flatMap((cls) => cls.members.filter((member) => member.name?.getText() === name)) : [];
18816
19094
  return [...this.declarationsOf(callee), ...members].some((declaration) => functionOf(declaration) === fn || declaration === fn || signatures.has(declaration) && !!checker && contextualReceiverMatches(call, fn, checker));
18817
19095
  });
19096
+ this.resolvedCallers.set(fn, callers);
19097
+ return callers;
18818
19098
  }
18819
19099
  implementedSignatures(fn, name) {
18820
19100
  const checker = this.context.checkerFor(this.relative(fn.getSourceFile().fileName));
@@ -19116,6 +19396,8 @@ function contains(outer, inner) {
19116
19396
  return inner.getStart() >= outer.getStart() && inner.getEnd() <= outer.getEnd();
19117
19397
  }
19118
19398
  function enclosingScope2(declaration) {
19399
+ if (import_typescript8.default.isParameter(declaration) && import_typescript8.default.isFunctionLike(declaration.parent) && "body" in declaration.parent)
19400
+ return declaration.parent.body;
19119
19401
  for (let node = declaration.parent;node; node = node.parent) {
19120
19402
  if (import_typescript8.default.isBlock(node) || import_typescript8.default.isSourceFile(node) || import_typescript8.default.isModuleBlock(node))
19121
19403
  return node;
@@ -19141,6 +19423,10 @@ function bindingField(element) {
19141
19423
  function bindParameters(fn, args, outer, into) {
19142
19424
  fn.parameters.forEach((parameter, index) => {
19143
19425
  const argument = args[index];
19426
+ if (parameter.dotDotDotToken && import_typescript8.default.isIdentifier(parameter.name)) {
19427
+ into.set(parameter, { expr: argument ?? parameter.name, bindings: outer, rest: args.slice(index) });
19428
+ return;
19429
+ }
19144
19430
  if (!argument)
19145
19431
  return;
19146
19432
  if (import_typescript8.default.isIdentifier(parameter.name)) {
@@ -19279,7 +19565,7 @@ function unresolvedReports(resolution, sites) {
19279
19565
  const resolvedSites = new Set(resolution.refs.flatMap((ref) => ref.callSiteIds.map((id) => `${id}|${ref.role}`)));
19280
19566
  const reports = new Map;
19281
19567
  for (const value of resolution.unresolved) {
19282
- if (resolvedSites.has(`${value.callSiteId}|${value.role}`))
19568
+ if (value.reason !== "depth-limit" && resolvedSites.has(`${value.callSiteId}|${value.role}`))
19283
19569
  continue;
19284
19570
  const site = sites.get(value.callSiteId);
19285
19571
  if (!site)
@@ -19484,7 +19770,7 @@ async function runHarnessCommand(context) {
19484
19770
  report: {
19485
19771
  reportId: report.reportId,
19486
19772
  reportHash,
19487
- path: normalizePath2(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19773
+ path: normalizePath3(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19488
19774
  },
19489
19775
  validation,
19490
19776
  approval: {
@@ -19630,7 +19916,7 @@ async function runHarnessCommand(context) {
19630
19916
  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
19917
  }
19632
19918
  if (context.flags["github-actions"] === "true") {
19633
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-gt4qawvp.js");
19919
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-x2jgh0e8.js");
19634
19920
  const result = await runGithubActionsAnalyze(rootDir, {
19635
19921
  writeReport: (report2) => {
19636
19922
  const normalized = normalizeHarnessReport(report2);
@@ -19757,7 +20043,7 @@ async function runHarnessCommand(context) {
19757
20043
  report: {
19758
20044
  reportId: approval.report.reportId,
19759
20045
  reportHash: hashHarnessReport(approval.report),
19760
- path: normalizePath2(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
20046
+ path: normalizePath3(relative9(rootDir, reportPath)) || ".moda/harness-report.json"
19761
20047
  },
19762
20048
  validation: approval.validation,
19763
20049
  approval: approval.approval
@@ -19779,17 +20065,17 @@ async function runHarnessCommand(context) {
19779
20065
  if (promoteOut === "true") {
19780
20066
  throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
19781
20067
  }
19782
- const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
20068
+ const { artifacts, unknowns, canonicalAgentIdentities } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19783
20069
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19784
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-xhcqg43k.js");
19785
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-n43wbr24.js");
20070
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-h9r08433.js");
20071
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-69xwrmrh.js");
19786
20072
  let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19787
20073
  if (promote === "all" || promote === "topology" || promote === "tools") {
19788
20074
  const { result, ctx } = extractHarnessWithContext2(rootDir);
19789
20075
  const found = enumerateHarnessComponents(result, ctx);
19790
20076
  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
20077
  }
19792
- const promoted = { concern: promote, unknowns, ...mergeEnumeratedComponents(artifacts, components) };
20078
+ const promoted = { concern: promote, unknowns, canonicalAgentIdentities, ...mergeEnumeratedComponents(artifacts, components) };
19793
20079
  const promoteWritten = [];
19794
20080
  if (promoteOut && !context.dryRun) {
19795
20081
  const target = resolve9(context.cwd, promoteOut);
@@ -19816,12 +20102,16 @@ async function runHarnessCommand(context) {
19816
20102
  }
19817
20103
  case "extract": {
19818
20104
  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");
20105
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-h9r08433.js");
20106
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-69xwrmrh.js");
19821
20107
  const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19822
- const artifacts = deterministicArtifacts(rootDir);
20108
+ const items = deterministicGraphItems(rootDir);
20109
+ const artifacts = items.artifacts;
19823
20110
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19824
- const graph = mergeEnumeratedComponents(artifacts, enumerateHarnessComponents(result, ctx));
20111
+ const graph = {
20112
+ ...mergeEnumeratedComponents(artifacts, enumerateHarnessComponents(result, ctx)),
20113
+ unknowns: items.unknowns.filter((item) => item.id.startsWith("unresolved_prompt_depth_"))
20114
+ };
19825
20115
  writeHumanProgress(context, `Harness extract: ${result.callSites.length} call sites, ${result.roles.length} traced roles across ${result.files} files (${result.programs} programs, ${result.durationMs.toLocaleString()} ms).`);
19826
20116
  context.output.writeData({ ...serializeExtractResult(result), graph }, {
19827
20117
  status: result.warnings.length > 0 ? "degraded" : "success",
@@ -20379,7 +20669,7 @@ function modelIdsUsedInSource(rootDir, ids) {
20379
20669
  const walk = (current) => {
20380
20670
  if (pending.size === 0)
20381
20671
  return false;
20382
- const rel2 = normalizePath2(relative9(rootReal, current)) || ".";
20672
+ const rel2 = normalizePath3(relative9(rootReal, current)) || ".";
20383
20673
  let stat;
20384
20674
  try {
20385
20675
  stat = lstatSync7(current);
@@ -20463,9 +20753,9 @@ function mergeDeterministicReplacement(report, rootDir, options) {
20463
20753
  mergeDeterministicArtifacts(report.graph, rootDir, options);
20464
20754
  const replacements = new Map;
20465
20755
  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))));
20756
+ const paths2 = artifactPaths(artifact);
20757
+ const exact = report.graph.artifacts.filter((candidate) => candidate.type === artifact.type && artifactPaths(candidate).some((path) => paths2.includes(path)));
20758
+ 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
20759
  replacements.set(artifact.id, matches);
20470
20760
  const owners = new Set([...artifact.usedByAgentIds ?? [], ...artifact.ownedByAgentId ? [artifact.ownedByAgentId] : []]);
20471
20761
  for (const link of agentLinks)
@@ -20537,6 +20827,7 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20537
20827
  mergeDeterministicReplacement(normalized, rootDir, options);
20538
20828
  if (!options.concern || options.concern === "topology")
20539
20829
  mergeBoundRuntimeClasses(normalized.graph, rootDir);
20830
+ remapCanonicalArtifactAgents(normalized.graph, normalized.graph.artifacts, !options.concern);
20540
20831
  tagComponentStatus(normalized.graph, rootDir);
20541
20832
  hydratePromptAndToolBodies(normalized.graph, rootDir);
20542
20833
  const unverified = new Set;
@@ -20570,8 +20861,8 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20570
20861
  const testOnlyModels = normalized.graph.artifacts.filter((artifact) => {
20571
20862
  if (artifact.type !== "model_config" || unverified.has(artifact.id))
20572
20863
  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));
20864
+ const paths2 = artifact.evidence.map((entry) => entry.path).filter((path) => typeof path === "string" && path.length > 0);
20865
+ return paths2.length > 0 && paths2.every((path) => TEST_PATH3.test(path));
20575
20866
  });
20576
20867
  const usedInSource = testOnlyModels.length > 0 ? modelIdsUsedInSource(rootDir, testOnlyModels.map((artifact) => (artifact.name ?? "").trim())) : new Set;
20577
20868
  for (const artifact of testOnlyModels) {
@@ -20601,6 +20892,29 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
20601
20892
  if (unverified.size > 0)
20602
20893
  removeArtifacts(normalized, unverified);
20603
20894
  deriveRelationshipsFromGraph(normalized.graph);
20895
+ if (!options.concern) {
20896
+ const knownAgents = new Set(normalized.graph.runtimeAgents.map((agent) => agent.id));
20897
+ for (const artifact of normalized.graph.artifacts) {
20898
+ if (artifact.type !== "tool" || !["in_prod", "reachable"].includes(artifact.status ?? ""))
20899
+ continue;
20900
+ const owners = [
20901
+ ...artifact.usedByAgentIds ?? [],
20902
+ ...artifact.ownedByAgentId ? [artifact.ownedByAgentId] : [],
20903
+ ...normalized.graph.runtimeAgents.filter((agent) => agent.artifactIds?.includes(artifact.id)).map((agent) => agent.id),
20904
+ ...normalized.graph.relationships.filter((edge) => edge.to === artifact.id && ["uses_artifact", "owns_artifact"].includes(edge.type)).map((edge) => edge.from)
20905
+ ];
20906
+ if (owners.some((owner) => knownAgents.has(owner)))
20907
+ continue;
20908
+ const id = `unresolved_tool_owner_${createHash7("sha256").update(artifact.id).digest("hex").slice(0, 16)}`;
20909
+ if (!normalized.graph.unknowns.some((unknown) => unknown.id === id))
20910
+ normalized.graph.unknowns.push({
20911
+ id,
20912
+ 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.`,
20913
+ candidateIds: [artifact.id],
20914
+ evidence: artifact.evidence
20915
+ });
20916
+ }
20917
+ }
20604
20918
  dropUnlocatedAgentCitations(normalized);
20605
20919
  if ((normalized.claims?.length ?? 0) === 0 && deterministicOnlyArtifactTypes().has("eval")) {
20606
20920
  const grounded = createHarnessReport({ graph: {
@@ -20696,8 +21010,8 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
20696
21010
  evals: new Set(["model_config", "eval"])
20697
21011
  };
20698
21012
  async function deterministicFloorGraph(rootDir, options = {}) {
20699
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-xhcqg43k.js");
20700
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-n43wbr24.js");
21013
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-h9r08433.js");
21014
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-69xwrmrh.js");
20701
21015
  const { result, ctx } = extractHarnessWithContext2(rootDir);
20702
21016
  const items = deterministicGraphItems(rootDir);
20703
21017
  const components = mergeEnumeratedComponents(items.artifacts, enumerateHarnessComponents(result, ctx));
@@ -20726,7 +21040,7 @@ function deterministicGraphItems(rootDir, concern) {
20726
21040
  const graph = { artifacts: [], unknowns: [] };
20727
21041
  mergeDeterministicArtifacts(graph, rootDir, { concern });
20728
21042
  hydratePromptAndToolBodies(graph, rootDir);
20729
- return { artifacts: graph.artifacts, unknowns: graph.unknowns };
21043
+ return { artifacts: graph.artifacts, unknowns: graph.unknowns, canonicalAgentIdentities: graph.scan?.canonicalAgentIdentities ?? [] };
20730
21044
  }
20731
21045
  var extractedModelsCache = new WeakMap;
20732
21046
  function extractedModelItems(rootDir) {
@@ -20845,7 +21159,7 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20845
21159
  try {
20846
21160
  promoted = promoteHarnessCandidates(detectHarnessCandidates(rootDir), rootDir, { fullEvidence: true });
20847
21161
  if (!allowedTypes || allowedTypes.has("prompt"))
20848
- promoted = withCallSitePrompts(rootDir, promoted);
21162
+ promoted = withCallSitePrompts(rootDir, promoted, graph.unknowns ??= []);
20849
21163
  } catch {
20850
21164
  promoted = [];
20851
21165
  }
@@ -20861,9 +21175,16 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20861
21175
  } catch {}
20862
21176
  }
20863
21177
  const extractedIds = new Set(extracted.artifacts.map((artifact) => artifact.id));
21178
+ try {
21179
+ const { result, ctx } = extractHarnessWithContext(rootDir);
21180
+ const identities = harnessAgentIdentities(enumerateAgents(result, ctx).runtimeAgents);
21181
+ graph.scan ??= {};
21182
+ graph.scan.canonicalAgentIdentities = identities;
21183
+ remapCanonicalArtifactAgents(graph, promoted);
21184
+ } catch {}
20864
21185
  backfillRefutationEvidenceReasons(graph);
20865
21186
  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)));
21187
+ const candidatePaths = new Set(promoted.flatMap((artifact) => artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath3(entry.path) : "").filter(Boolean)));
20867
21188
  const modelLineCounts = new Map;
20868
21189
  for (const artifact of promoted) {
20869
21190
  if (artifact.type !== "model_config")
@@ -20888,6 +21209,26 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20888
21209
  added += 1;
20889
21210
  continue;
20890
21211
  }
21212
+ if (artifact.type === "prompt" && artifact.usedByAgentIds.length > 0) {
21213
+ const existing = graph.artifacts.find((candidate) => candidate.type === "prompt" && candidate.id === artifact.id);
21214
+ if (existing && !isRefutedByAnalyst(artifact, refuted, candidatePaths)) {
21215
+ const definition = artifact.evidence[0];
21216
+ const stored = existing.evidence?.[0];
21217
+ if (definition && (!stored || stored.path === definition.path && stored.line === definition.line)) {
21218
+ existing.usedByAgentIds = [...new Set([...existing.usedByAgentIds ?? [], ...artifact.usedByAgentIds])];
21219
+ if (Array.isArray(existing.staticUsedByAgentIds))
21220
+ existing.staticUsedByAgentIds = [...new Set([...existing.staticUsedByAgentIds, ...artifact.usedByAgentIds])];
21221
+ if (existing.usedByAgentIds.length > 1)
21222
+ existing.scope = "shared";
21223
+ existing.evidence ??= [];
21224
+ for (const entry of artifact.evidence) {
21225
+ if (!existing.evidence.some((known) => known.path === entry.path && known.line === entry.line && known.reason === entry.reason))
21226
+ existing.evidence.push(entry);
21227
+ }
21228
+ continue;
21229
+ }
21230
+ }
21231
+ }
20891
21232
  if (graphCoversPromotedArtifact(graph, artifact, sharedModelLines))
20892
21233
  continue;
20893
21234
  if ((artifact.type === "model_config" || artifact.type === "eval") && artifact.evidence.length > 1 && !refuted.candidateIds.has(artifact.id)) {
@@ -20915,14 +21256,76 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
20915
21256
  }
20916
21257
  return { added };
20917
21258
  }
20918
- function withCallSitePrompts(rootDir, promoted) {
21259
+ function remapCanonicalArtifactAgents(graph, artifacts = graph.artifacts, dropUnmapped = false) {
21260
+ const identities = harnessAgentIdentities(graph.scan?.canonicalAgentIdentities);
21261
+ const mapping = matchHarnessAgentIds(identities, graph.runtimeAgents ?? []);
21262
+ const canonical = new Map(identities.map((identity2) => [identity2.id, identity2]));
21263
+ const unresolved = new Map;
21264
+ const translate = (id, artifactId) => {
21265
+ const mapped = mapping.get(id);
21266
+ if (mapped || !dropUnmapped || !canonical.has(id))
21267
+ return mapped ?? id;
21268
+ const affected = unresolved.get(id) ?? [];
21269
+ if (!affected.includes(artifactId))
21270
+ affected.push(artifactId);
21271
+ unresolved.set(id, affected);
21272
+ return;
21273
+ };
21274
+ for (const artifact of artifacts) {
21275
+ artifact.usedByAgentIds = [...new Set((artifact.usedByAgentIds ?? []).flatMap((id) => translate(id, artifact.id) ?? []))];
21276
+ for (const field of ["staticUsedByAgentIds", "traceUsedByAgentIds"]) {
21277
+ if (Array.isArray(artifact[field]))
21278
+ artifact[field] = [...new Set(artifact[field].flatMap((id) => translate(id, artifact.id) ?? []))];
21279
+ }
21280
+ if (artifact.ownedByAgentId) {
21281
+ const owner = translate(artifact.ownedByAgentId, artifact.id);
21282
+ if (owner)
21283
+ artifact.ownedByAgentId = owner;
21284
+ else {
21285
+ delete artifact.ownedByAgentId;
21286
+ artifact.scope = "shared";
21287
+ }
21288
+ }
21289
+ }
21290
+ for (const [agentId, artifactIds] of unresolved) {
21291
+ const identity2 = canonical.get(agentId);
21292
+ const id = `unresolved_agent_links_${createHash7("sha256").update(agentId).digest("hex").slice(0, 16)}`;
21293
+ if (graph.unknowns.some((unknown) => unknown.id === id))
21294
+ continue;
21295
+ graph.unknowns.push({
21296
+ id,
21297
+ question: `Ownership for ${identity2.name} could not be matched uniquely to the hosted topology; its unresolved artifact links were omitted.`,
21298
+ candidateIds: artifactIds,
21299
+ evidence: (identity2.evidence ?? []).flatMap((entry) => entry.path ? [{ path: entry.path, ...entry.line !== undefined ? { line: entry.line } : {}, reason: entry.reason ?? "Extractor agent identity" }] : [])
21300
+ });
21301
+ }
21302
+ }
21303
+ function withCallSitePrompts(rootDir, promoted, unknowns = []) {
20919
21304
  if (process.env.MODA_HARNESS_CALLSITE_PROMPTS === "0")
20920
21305
  return promoted;
20921
21306
  try {
20922
21307
  const { result, ctx } = extractHarnessWithContext(rootDir);
20923
21308
  const sites = result.callSites.filter((site) => !site.isTest);
20924
21309
  const toolDefinitions = result.toolDefinitions ?? [];
20925
- return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions, agentForScope: createAgentScopeResolver(result, ctx) }).artifacts;
21310
+ const assembled = promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions, agentForScope: createAgentScopeResolver(result, ctx) });
21311
+ for (const report of assembled.unresolved) {
21312
+ const limited = report.values.filter((value) => value.reason === "depth-limit");
21313
+ if (!limited.length)
21314
+ continue;
21315
+ const id = stableId("unresolved_prompt_depth", `${report.callSiteId}:${report.role}`);
21316
+ if (unknowns.some((unknown) => unknown.id === id))
21317
+ continue;
21318
+ unknowns.push({
21319
+ id,
21320
+ question: `trace depth limit: ${report.role} prompt at ${report.path}:${report.line} has unresolved source paths.`,
21321
+ candidateIds: [],
21322
+ evidence: [
21323
+ { path: report.path, line: report.line, reason: "trace depth limit at model call site" },
21324
+ ...limited.map((value) => ({ path: value.path, line: value.line, reason: `trace depth limit: ${value.expression}` }))
21325
+ ]
21326
+ });
21327
+ }
21328
+ return assembled.artifacts;
20926
21329
  } catch {
20927
21330
  return promoted;
20928
21331
  }
@@ -20985,11 +21388,11 @@ function analystRefutations(graph) {
20985
21388
  if (typeof entry?.path !== "string" || !entry.path)
20986
21389
  continue;
20987
21390
  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) });
21391
+ result.locations.push({ path: normalizePath3(entry.path), start: line, end: line, types: refutedTypes(entry.reason, question) });
20989
21392
  }
20990
21393
  for (const match of question.matchAll(/([\w./-]+\.[a-z0-9]{1,5})(?::|\s+(?:lines?\s+)?)(\d+)(?:\s*[-\u2013]\s*(\d+))?/gi)) {
20991
21394
  const start = Number(match[2]);
20992
- result.locations.push({ path: normalizePath2(match[1]), start, end: match[3] ? Number(match[3]) : start, types: refutedTypes(question) });
21395
+ result.locations.push({ path: normalizePath3(match[1]), start, end: match[3] ? Number(match[3]) : start, types: refutedTypes(question) });
20993
21396
  }
20994
21397
  }
20995
21398
  return result;
@@ -21008,7 +21411,7 @@ function isRefutedByAnalyst(artifact, refuted, candidatePaths) {
21008
21411
  return artifact.evidence.some((entry) => {
21009
21412
  if (typeof entry.path !== "string")
21010
21413
  return false;
21011
- const path = normalizePath2(entry.path);
21414
+ const path = normalizePath3(entry.path);
21012
21415
  return refuted.locations.some((location) => {
21013
21416
  if (location.types && !location.types.has(artifact.type))
21014
21417
  return false;
@@ -21024,9 +21427,9 @@ function isRefutedByAnalyst(artifact, refuted, candidatePaths) {
21024
21427
  }
21025
21428
  function artifactSourceKey(artifact) {
21026
21429
  if (artifact.sourcePath)
21027
- return normalizePath2(artifact.sourcePath);
21430
+ return normalizePath3(artifact.sourcePath);
21028
21431
  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;
21432
+ return pinned ? normalizePath3(pinned.path) : undefined;
21030
21433
  }
21031
21434
  function mentionsModelId(text, id) {
21032
21435
  if (!id)
@@ -21035,8 +21438,8 @@ function mentionsModelId(text, id) {
21035
21438
  return new RegExp(`(?<![\\w./@-])${escaped}(?![\\w/-]|\\.\\w)`, "i").test(text);
21036
21439
  }
21037
21440
  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;
21441
+ const paths2 = Array.isArray(artifact.evidence) ? artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath3(entry.path) : "").filter(Boolean) : [];
21442
+ return artifact.sourcePath ? [normalizePath3(artifact.sourcePath), ...paths2] : paths2;
21040
21443
  }
21041
21444
  function graphCoversPromotedArtifact(graph, promoted, sharedModelLines = new Set) {
21042
21445
  if (promoted.type === "model_config" && graph.artifacts.some((existing) => existing.type === "model_config" && mentionsModelId(`${existing.name ?? ""}
@@ -21044,7 +21447,7 @@ ${existing.body ?? ""}`, promoted.name)))
21044
21447
  return true;
21045
21448
  if (promoted.type === "eval") {
21046
21449
  const suite = new Set(artifactPaths(promoted));
21047
- const suiteKey = promoted.sourcePath ? evalSuiteKey(normalizePath2(promoted.sourcePath)) : undefined;
21450
+ const suiteKey = promoted.sourcePath ? evalSuiteKey(normalizePath3(promoted.sourcePath)) : undefined;
21048
21451
  if (graph.artifacts.some((existing) => existing.type === "eval" && artifactPaths(existing).some((path) => suite.has(path) || suiteKey !== undefined && evalSuiteKey(path.replace(/\/+$/, "")) === suiteKey)))
21049
21452
  return true;
21050
21453
  }
@@ -22042,15 +22445,15 @@ function renderExternalAnalystProtocol(concern) {
22042
22445
  function renderAnalystPreflightSection(rootDir) {
22043
22446
  if (process.env.MODA_HARNESS_ANALYST_PREFLIGHT === "0")
22044
22447
  return "";
22045
- const paths = listAnalystPreflightPaths(rootDir);
22046
- if (paths.length === 0)
22448
+ const paths2 = listAnalystPreflightPaths(rootDir);
22449
+ if (paths2.length === 0)
22047
22450
  return "";
22048
22451
  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)
22452
+ manifests: paths2.filter((path) => isManifestLikePath(path)).slice(0, 60),
22453
+ docs: paths2.filter((path) => isDocLikePath(path)).slice(0, 40),
22454
+ source: paths2.filter((path) => isAgentNavigationPath(path)).slice(0, 160),
22455
+ deploy: paths2.filter((path) => isPreflightDeployLikePath(path)).slice(0, 50),
22456
+ evals: paths2.filter((path) => isPreflightEvalLikePath(path)).slice(0, 50)
22054
22457
  };
22055
22458
  const lines = [
22056
22459
  "",
@@ -22065,10 +22468,10 @@ function renderAnalystPreflightSection(rootDir) {
22065
22468
  return lines.join(`
22066
22469
  `);
22067
22470
  }
22068
- function renderPreflightGroup(label, paths) {
22069
- if (paths.length === 0)
22471
+ function renderPreflightGroup(label, paths2) {
22472
+ if (paths2.length === 0)
22070
22473
  return [];
22071
- return [`${label}:`, ...paths.map((path) => `- ${path}`)];
22474
+ return [`${label}:`, ...paths2.map((path) => `- ${path}`)];
22072
22475
  }
22073
22476
  var MAX_SEED_ARTIFACT_LINES = 150;
22074
22477
  function renderAnalystSeedSection(rootDir, concern) {
@@ -22172,8 +22575,8 @@ function renderAnalystSeedLines(graph) {
22172
22575
  }
22173
22576
  function listAnalystPreflightPaths(rootDir) {
22174
22577
  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();
22578
+ const paths2 = gitPaths.length > 0 ? gitPaths : readDirectoryPreflightPaths(rootDir);
22579
+ return [...new Set(paths2.map(normalizePath3))].filter((path) => path && !shouldSkipPreflightPath(path)).sort();
22177
22580
  }
22178
22581
  function readGitTrackedPaths(rootDir) {
22179
22582
  try {
@@ -22187,9 +22590,9 @@ function readGitTrackedPaths(rootDir) {
22187
22590
  }
22188
22591
  }
22189
22592
  function readDirectoryPreflightPaths(rootDir) {
22190
- const paths = [];
22593
+ const paths2 = [];
22191
22594
  const stack = ["."];
22192
- while (stack.length > 0 && paths.length < 2000) {
22595
+ while (stack.length > 0 && paths2.length < 2000) {
22193
22596
  const current = stack.pop() ?? ".";
22194
22597
  const absolute = current === "." ? rootDir : join11(rootDir, current);
22195
22598
  let entries;
@@ -22214,14 +22617,14 @@ function readDirectoryPreflightPaths(rootDir) {
22214
22617
  if (stat.isDirectory()) {
22215
22618
  stack.push(child);
22216
22619
  } else {
22217
- paths.push(child);
22620
+ paths2.push(child);
22218
22621
  }
22219
22622
  }
22220
22623
  }
22221
- return paths;
22624
+ return paths2;
22222
22625
  }
22223
22626
  function shouldSkipPreflightPath(path) {
22224
- const normalized = normalizePath2(path);
22627
+ const normalized = normalizePath3(path);
22225
22628
  if (!normalized || normalized.startsWith(".moda/"))
22226
22629
  return true;
22227
22630
  const parts = normalized.split("/");
@@ -22346,7 +22749,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
22346
22749
  let inventoryFileCount = 0;
22347
22750
  let inventoryTextBytes = 0;
22348
22751
  function walk(current) {
22349
- const path = normalizePath2(relative9(rootDir, current)) || ".";
22752
+ const path = normalizePath3(relative9(rootDir, current)) || ".";
22350
22753
  let stat;
22351
22754
  try {
22352
22755
  stat = lstatSync7(current);
@@ -22417,7 +22820,7 @@ function buildSourceSnapshot(rootDir) {
22417
22820
  }
22418
22821
  function buildCommandScanPlan(context, rootDir) {
22419
22822
  const explicitPath = context.flags.path !== undefined;
22420
- const rel2 = normalizePath2(relative9(context.cwd, rootDir)) || ".";
22823
+ const rel2 = normalizePath3(relative9(context.cwd, rootDir)) || ".";
22421
22824
  const scope = explicitPath && rel2 !== "." ? "narrow" : "broad";
22422
22825
  const machineReadable = context.outputMode !== "human";
22423
22826
  const approvalRequired = context.positional === "analyze" && scope === "broad" && !context.yes;
@@ -22502,7 +22905,7 @@ function writeHumanBlock(context, message) {
22502
22905
  function buildHarnessReadPlan(rootDir, pathWasExplicit) {
22503
22906
  return {
22504
22907
  scope: pathWasExplicit ? "narrow" : "broad",
22505
- rootPaths: [normalizePath2(relative9(rootDir, rootDir)) || "."],
22908
+ rootPaths: [normalizePath3(relative9(rootDir, rootDir)) || "."],
22506
22909
  willRead: [
22507
22910
  "package manifests",
22508
22911
  "source files under the selected path",
@@ -22715,7 +23118,7 @@ function findFresherHarnessReports(rootDir) {
22715
23118
  const candidate = lstatSync7(join11(child, HARNESS_REPORT_PATH));
22716
23119
  if (candidate.isFile() && candidate.mtimeMs > rootMtimeMs) {
22717
23120
  fresher.push({
22718
- path: normalizePath2(relative9(rootDir, join11(child, HARNESS_REPORT_PATH))),
23121
+ path: normalizePath3(relative9(rootDir, join11(child, HARNESS_REPORT_PATH))),
22719
23122
  mtimeMs: candidate.mtimeMs
22720
23123
  });
22721
23124
  }
@@ -22727,8 +23130,8 @@ function findFresherHarnessReports(rootDir) {
22727
23130
  return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
22728
23131
  }
22729
23132
  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))
23133
+ const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative9(rootDir, resolve9(rootDir, explicitReport))) : undefined;
23134
+ if (explicitReportPath && explicitReportPath !== normalizePath3(HARNESS_REPORT_PATH))
22732
23135
  return;
22733
23136
  let fresher;
22734
23137
  try {
@@ -22739,7 +23142,7 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
22739
23142
  if (fresher.length === 0)
22740
23143
  return;
22741
23144
  const newest = fresher[0];
22742
- const subdir = normalizePath2(dirname8(dirname8(newest.path)));
23145
+ const subdir = normalizePath3(dirname8(dirname8(newest.path)));
22743
23146
  const rootState = existsSync8(join11(rootDir, HARNESS_REPORT_PATH)) ? `older ${HARNESS_REPORT_PATH}` : `no ${HARNESS_REPORT_PATH}`;
22744
23147
  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
23148
  }
@@ -22934,7 +23337,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
22934
23337
  const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
22935
23338
  let textBytes = 0;
22936
23339
  function walk(current) {
22937
- const rel2 = normalizePath2(relative9(rootReal, current)) || ".";
23340
+ const rel2 = normalizePath3(relative9(rootReal, current)) || ".";
22938
23341
  let stat;
22939
23342
  try {
22940
23343
  stat = lstatSync7(current);
@@ -23150,7 +23553,7 @@ function runtimeAgentFromAnnotation(annotation) {
23150
23553
  kind: "runtime_agent",
23151
23554
  purpose: first2(values.purpose) ?? first2(values.description),
23152
23555
  familyId: first2(values.family),
23153
- root: normalizePath2(first2(values.root) ?? dirname8(annotation.evidence.path)),
23556
+ root: normalizePath3(first2(values.root) ?? dirname8(annotation.evidence.path)),
23154
23557
  entrypointIds: values.entrypoint ?? [stableId("entry", annotation.evidence.path)],
23155
23558
  channelAdapterIds: values.channel ?? [],
23156
23559
  artifactIds: [...values.artifact ?? [], ...values.prompt ?? [], ...values.tool ?? []],
@@ -23386,7 +23789,7 @@ function inferRuntimeAgent(file, graph) {
23386
23789
  name: titleFromId(file.path.replace(/\.(ts|tsx|js|mjs|py)$/i, "")),
23387
23790
  kind: "runtime_agent",
23388
23791
  purpose: inferAgentPurpose(file),
23389
- root: normalizePath2(dirname8(file.path)),
23792
+ root: normalizePath3(dirname8(file.path)),
23390
23793
  entrypointIds: [entryId],
23391
23794
  channelAdapterIds: channelIds,
23392
23795
  artifactIds,
@@ -24285,7 +24688,7 @@ function contentHashForAnnotatedSource(sourcePath, annotation) {
24285
24688
  function readSmallTextFileForHash(absPath, rootDir) {
24286
24689
  if (!existsSync8(absPath))
24287
24690
  return;
24288
- const rel2 = normalizePath2(relative9(rootDir, absPath));
24691
+ const rel2 = normalizePath3(relative9(rootDir, absPath));
24289
24692
  if (isSecretishPath(rel2))
24290
24693
  return;
24291
24694
  let stat;
@@ -24386,7 +24789,7 @@ function titleFromId(id) {
24386
24789
  function promptNameFromPath(path) {
24387
24790
  return titleFromId(basename6(path).replace(/\.(prompt\.)?(md|json|ya?ml)$/i, ""));
24388
24791
  }
24389
- function normalizePath2(path) {
24792
+ function normalizePath3(path) {
24390
24793
  return path.split(sep5).join("/");
24391
24794
  }
24392
24795
  function hashText(text) {
@@ -27112,8 +27515,8 @@ function collectModels(result, ctx) {
27112
27515
  const context = modelPathContext(result.rootDir);
27113
27516
  const harnessPath = (path) => isHarnessModelPath(path, context);
27114
27517
  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))
27518
+ const paths2 = [...entry.definitions.map((at) => at.path), ...entry.sites.map((site) => site.path)];
27519
+ if (!paths2.some(harnessPath))
27117
27520
  byId.delete(id);
27118
27521
  }
27119
27522
  const kept = unresolved.filter((entry) => harnessPath(entry.path));
@@ -27430,7 +27833,7 @@ function enumerationRepository(ctx) {
27430
27833
  };
27431
27834
  walk(ctx.rootDir);
27432
27835
  const workers = [];
27433
- const paths = new Set(files.map((file) => file.path));
27836
+ const paths2 = new Set(files.map((file) => file.path));
27434
27837
  const closure = (main) => {
27435
27838
  const found = new Set, pending = [main];
27436
27839
  for (let index = 0;index < pending.length; index++) {
@@ -27445,7 +27848,7 @@ function enumerationRepository(ctx) {
27445
27848
  if (!ref.fileName.startsWith("."))
27446
27849
  continue;
27447
27850
  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));
27851
+ const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths2.has(candidate));
27449
27852
  if (target)
27450
27853
  pending.push(target);
27451
27854
  }
@@ -29046,7 +29449,7 @@ function runExtract(rootDir, options) {
29046
29449
  return /\.svelte$/i.test(abs) ? svelteVirtualName(abs) : abs;
29047
29450
  };
29048
29451
  const lookup = (path) => repo?.owner.get(fileKey(path));
29049
- const sourceFile = (path) => lookup(path)?.program.getSourceFile(fileKey(path));
29452
+ const sourceFile2 = (path) => lookup(path)?.program.getSourceFile(fileKey(path));
29050
29453
  let files;
29051
29454
  const ctx = {
29052
29455
  rootDir,
@@ -29055,7 +29458,7 @@ function runExtract(rootDir, options) {
29055
29458
  checkerFor: (path) => lookup(path)?.checker(),
29056
29459
  sourceFiles: () => files ??= [...repo?.owner.entries() ?? []].filter(([file]) => !isTestPath(relPath(rootDir, file))).map(([file, entry]) => entry.program.getSourceFile(file)).filter((file) => Boolean(file)),
29057
29460
  nodeAt: (ref) => {
29058
- const source = sourceFile(ref.path);
29461
+ const source = sourceFile2(ref.path);
29059
29462
  return source ? nodeSpanning(source, ref.start, ref.end) : undefined;
29060
29463
  }
29061
29464
  };
@@ -30009,8 +30412,8 @@ function mergeEnumeratedComponents(artifacts, components) {
30009
30412
  const candidates = extractedByName.get(item.name) ?? [];
30010
30413
  if (candidates.length === 0)
30011
30414
  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];
30415
+ const paths2 = new Set([item.sourcePath, ...item.evidence.map((entry) => entry.path)].filter(Boolean));
30416
+ 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
30417
  return `tool:${target.id}`;
30015
30418
  };
30016
30419
  for (const item of [...registry, ...artifacts, ...components.artifacts.filter((item2) => !registry.includes(item2))]) {