@moda-ai/cli 1.55.72 → 1.55.73

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.
@@ -18,10 +18,12 @@ import {
18
18
  artifactHasBody,
19
19
  buildImportGraphReachability,
20
20
  createHarnessReport,
21
+ detectBoundRuntimeClasses,
21
22
  firstEvidencePath,
22
23
  graphForReport,
23
24
  hashHarnessReport,
24
25
  hashStableJson,
26
+ isTestWorkerConfig,
25
27
  loadHarnessReportForSync,
26
28
  mergeBoundRuntimeClasses,
27
29
  normalizeHarnessReport,
@@ -29,14 +31,11 @@ import {
29
31
  requiresArtifactBody,
30
32
  resolveHarnessReportPath,
31
33
  stampRemoteSnapshotTruncation,
34
+ stripJsonc,
32
35
  tagComponentStatus,
33
36
  validateHarnessReport,
34
37
  writeHarnessReportArtifacts
35
- } from "./cli-9ww72mrd.js";
36
- import {
37
- createCommandContext,
38
- stringOption
39
- } from "./cli-5ms8rw8x.js";
38
+ } from "./cli-y333w08f.js";
40
39
  import {
41
40
  assertFlags,
42
41
  assertPositionals,
@@ -46,6 +45,10 @@ import {
46
45
  ApiError,
47
46
  callControlAPI
48
47
  } from "./cli-87xy1evx.js";
48
+ import {
49
+ createCommandContext,
50
+ stringOption
51
+ } from "./cli-5ms8rw8x.js";
49
52
  import {
50
53
  EXIT_DEGRADED,
51
54
  embeddedTenantIdFromApiKey,
@@ -105,6 +108,9 @@ import {
105
108
  __toESM
106
109
  } from "./cli-0v6na3yp.js";
107
110
 
111
+ // src/harness-extract/enumerators/agents.ts
112
+ var import_typescript12 = __toESM(require_typescript(), 1);
113
+
108
114
  // src/harness-extract/index.ts
109
115
  var import_typescript10 = __toESM(require_typescript(), 1);
110
116
  import { resolve as resolve13 } from "node:path";
@@ -9140,7 +9146,7 @@ function isUnder2(path, root) {
9140
9146
  return true;
9141
9147
  return path === root || path.startsWith(`${root}/`);
9142
9148
  }
9143
- function stripJsonc(text) {
9149
+ function stripJsonc2(text) {
9144
9150
  let out = "";
9145
9151
  let i = 0;
9146
9152
  let inString = false;
@@ -9184,7 +9190,7 @@ function stripJsonc(text) {
9184
9190
  }
9185
9191
  function parseJsonLoose(text) {
9186
9192
  try {
9187
- return JSON.parse(stripJsonc(text));
9193
+ return JSON.parse(stripJsonc2(text));
9188
9194
  } catch {
9189
9195
  return;
9190
9196
  }
@@ -19031,7 +19037,7 @@ async function runHarnessCommand(context) {
19031
19037
  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.");
19032
19038
  }
19033
19039
  if (context.flags["github-actions"] === "true") {
19034
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-awcd5ns1.js");
19040
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-p4011crc.js");
19035
19041
  const result = await runGithubActionsAnalyze(rootDir, {
19036
19042
  writeReport: (report2) => {
19037
19043
  const normalized = normalizeHarnessReport(report2);
@@ -19177,7 +19183,15 @@ async function runHarnessCommand(context) {
19177
19183
  }
19178
19184
  const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19179
19185
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19180
- const promoted = { concern: promote, artifacts, unknowns };
19186
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-4z7h9mam.js");
19187
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-femt9s00.js");
19188
+ let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19189
+ if (promote === "all" || promote === "topology" || promote === "tools") {
19190
+ const { result, ctx } = extractHarnessWithContext2(rootDir);
19191
+ const found = enumerateHarnessComponents(result, ctx);
19192
+ components = promote === "tools" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type === "tool") } : promote === "topology" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type !== "tool") } : found;
19193
+ }
19194
+ const promoted = { concern: promote, unknowns, ...mergeEnumeratedComponents(artifacts, components) };
19181
19195
  const promoteWritten = [];
19182
19196
  if (promoteOut && !context.dryRun) {
19183
19197
  const target = resolve9(context.cwd, promoteOut);
@@ -19204,10 +19218,14 @@ async function runHarnessCommand(context) {
19204
19218
  }
19205
19219
  case "extract": {
19206
19220
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
19207
- const { extractHarness: extractHarness2, serializeExtractResult } = await import("./index-tpwztst3.js");
19208
- const result = extractHarness2(rootDir, { fresh: true });
19221
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-4z7h9mam.js");
19222
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-femt9s00.js");
19223
+ const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19224
+ const artifacts = deterministicArtifacts(rootDir);
19225
+ tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19226
+ const graph = mergeEnumeratedComponents(artifacts, enumerateHarnessComponents(result, ctx));
19209
19227
  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).`);
19210
- context.output.writeData(serializeExtractResult(result), {
19228
+ context.output.writeData({ ...serializeExtractResult(result), graph }, {
19211
19229
  status: result.warnings.length > 0 ? "degraded" : "success",
19212
19230
  ...result.warnings.length > 0 ? { warnings: result.warnings } : {}
19213
19231
  });
@@ -19987,18 +20005,19 @@ function deterministicGraphItems(rootDir, concern) {
19987
20005
  hydratePromptAndToolBodies(graph, rootDir);
19988
20006
  return { artifacts: graph.artifacts, unknowns: graph.unknowns };
19989
20007
  }
19990
- var extractedModelsCache = new Map;
20008
+ var extractedModelsCache = new WeakMap;
19991
20009
  function extractedModelItems(rootDir) {
19992
20010
  const empty = { artifacts: [], unknowns: [], rewritten: new Set, enabled: false };
19993
20011
  if (process.env.MODA_HARNESS_EXTRACT === "0")
19994
20012
  return empty;
19995
20013
  const key = resolve9(rootDir);
19996
- const cached = extractedModelsCache.get(key);
19997
- if (cached)
19998
- return cached;
19999
20014
  let items = { ...empty, enabled: true };
20000
20015
  try {
20001
- const result = extractHarness(key);
20016
+ const { result, ctx } = extractHarnessWithContext(key);
20017
+ createAgentScopeResolver(result, ctx);
20018
+ const cached = extractedModelsCache.get(result);
20019
+ if (cached)
20020
+ return cached;
20002
20021
  for (const warning of result.warnings)
20003
20022
  process.stderr.write(`warning: harness extraction incomplete; ${warning}
20004
20023
  `);
@@ -20008,11 +20027,11 @@ function extractedModelItems(rootDir) {
20008
20027
  rewritten: new Set((result.rewrittenModels ?? []).map((entry) => normalizedModelId(entry.id))),
20009
20028
  enabled: true
20010
20029
  };
20030
+ extractedModelsCache.set(result, items);
20011
20031
  } catch (error) {
20012
20032
  process.stderr.write(`warning: harness extraction failed; model artifacts come from the candidate pre-pass only (${error instanceof Error ? error.message : String(error)})
20013
20033
  `);
20014
20034
  }
20015
- extractedModelsCache.set(key, items);
20016
20035
  return items;
20017
20036
  }
20018
20037
  var normalizedModelId = (name) => String(name ?? "").trim().toLowerCase();
@@ -20180,7 +20199,7 @@ function withCallSitePrompts(rootDir, promoted) {
20180
20199
  const { result, ctx } = extractHarnessWithContext(rootDir);
20181
20200
  const sites = result.callSites.filter((site) => !site.isTest);
20182
20201
  const toolDefinitions = result.toolDefinitions ?? [];
20183
- return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions }).artifacts;
20202
+ return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions, agentForScope: createAgentScopeResolver(result, ctx) }).artifacts;
20184
20203
  } catch {
20185
20204
  return promoted;
20186
20205
  }
@@ -26390,25 +26409,29 @@ var REASON = {
26390
26409
  config: "model id in model configuration next to a model call"
26391
26410
  };
26392
26411
  function modelArtifacts(result) {
26393
- return (result.models ?? []).map((model) => ({
26394
- id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26395
- type: "model_config",
26396
- name: model.id,
26397
- scope: "shared",
26398
- usedByAgentIds: [],
26399
- confidence: CONFIDENCE[model.resolution],
26400
- confidenceReason: model.resolution === "config" ? "Read from a model-named setting in source; no call site passes it directly." : "Traced from a model call site's model argument to this literal.",
26401
- evidence: [
26402
- { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26403
- ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26404
- path: site.path,
26405
- line: site.line,
26406
- reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26407
- }))
26408
- ],
26409
- calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26410
- resolution: model.resolution
26411
- }));
26412
+ const owners = new Map(result.callSites.map((site) => [site.id, site.agentIds ?? []]));
26413
+ return (result.models ?? []).map((model) => {
26414
+ const agentIds = [...new Set(model.calledFrom.flatMap((site) => owners.get(site.callSite) ?? []))].sort();
26415
+ return {
26416
+ id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26417
+ type: "model_config",
26418
+ name: model.id,
26419
+ scope: agentIds.length === 1 ? "agent" : "shared",
26420
+ usedByAgentIds: agentIds,
26421
+ confidence: CONFIDENCE[model.resolution],
26422
+ confidenceReason: model.resolution === "config" ? "Read from a model-named setting in source; no call site passes it directly." : "Traced from a model call site's model argument to this literal.",
26423
+ evidence: [
26424
+ { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26425
+ ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26426
+ path: site.path,
26427
+ line: site.line,
26428
+ reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26429
+ }))
26430
+ ],
26431
+ calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26432
+ resolution: model.resolution
26433
+ };
26434
+ });
26412
26435
  }
26413
26436
  function describeSource(source) {
26414
26437
  const [kind, ...rest] = source.split(":");
@@ -26621,8 +26644,6 @@ function collectModelLiterals(rootDir) {
26621
26644
 
26622
26645
  // src/harness-extract/types.ts
26623
26646
  var EXTRACT_SCHEMA_VERSION = 1;
26624
- // src/harness-extract/enumerators/index.ts
26625
- var ENUMERATORS = [];
26626
26647
  // src/harness-extract/tools.ts
26627
26648
  var PASS_THROUGH2 = new Set(["ref", "call", "param", "oneOf", "lookup"]);
26628
26649
  var DEFINITION_KEYS = new Set(["description", "input_schema", "inputSchema", "parameters", "schema", "execute", "type", "strict"]);
@@ -27242,4 +27263,954 @@ function assignAgentIds(result, agentForScope) {
27242
27263
  }
27243
27264
  }
27244
27265
 
27245
- export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals, EXTRACT_SCHEMA_VERSION, ENUMERATORS, toolNamesOf, clearExtractCache, extractHarness, extractHarnessWithContext, serializeExtractResult, runEnumerators, assignAgentIds, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, deterministicGraphItems, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, resolveExternalHarnessAnalystInvocation, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, readOnlyClaudeExtraArgs, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };
27266
+ // src/harness-extract/enumerators/common.ts
27267
+ var import_typescript11 = __toESM(require_typescript(), 1);
27268
+ import { readdirSync as readdirSync8, readFileSync as readFileSync15 } from "node:fs";
27269
+ import { dirname as dirname10, join as join13, posix as posix2, relative as relative10 } from "node:path";
27270
+ var cache2 = new WeakMap;
27271
+ var SKIP = new Set(["node_modules", "dist", "build", "out", "vendor", "coverage", "__pycache__"]);
27272
+ var TEST_PATH4 = /(?:^|\/)(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|__mocks__|e2e)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
27273
+ var EVAL_PATH2 = /(?:^|\/)evals?\/|\.evals?\.[cm]?[jt]sx?$/i;
27274
+ function enumerationRepository(ctx) {
27275
+ const existing = cache2.get(ctx);
27276
+ if (existing)
27277
+ return existing;
27278
+ const files = [];
27279
+ const walk = (dir) => {
27280
+ for (const entry of readdirSync8(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
27281
+ const abs = join13(dir, entry.name);
27282
+ if (entry.isDirectory()) {
27283
+ if (!entry.name.startsWith(".") && !SKIP.has(entry.name))
27284
+ walk(abs);
27285
+ } else if (entry.isFile() && /\.(?:[cm]?[jt]sx?|py|jsonc?|toml)$/.test(entry.name) && !/\.d\.[cm]?ts$/.test(entry.name)) {
27286
+ const path = relative10(ctx.rootDir, abs).split("\\").join("/");
27287
+ try {
27288
+ const text = readFileSync15(abs, "utf8");
27289
+ if (text.length > 1024 * 1024)
27290
+ continue;
27291
+ const source = ctx.programFor(path)?.getSourceFile(abs) ?? import_typescript11.default.createSourceFile(abs, text, import_typescript11.default.ScriptTarget.Latest, true, path.endsWith("tsx") ? import_typescript11.default.ScriptKind.TSX : import_typescript11.default.ScriptKind.TS);
27292
+ files.push({ path, text, source });
27293
+ } catch {}
27294
+ }
27295
+ }
27296
+ };
27297
+ walk(ctx.rootDir);
27298
+ const workers = [];
27299
+ const paths = new Set(files.map((file) => file.path));
27300
+ const closure = (main) => {
27301
+ const found = new Set, pending = [main];
27302
+ for (let index = 0;index < pending.length; index++) {
27303
+ const path = pending[index];
27304
+ if (found.has(path))
27305
+ continue;
27306
+ found.add(path);
27307
+ const file = files.find((entry) => entry.path === path);
27308
+ if (!file)
27309
+ continue;
27310
+ for (const ref of import_typescript11.default.preProcessFile(file.text, true, true).importedFiles) {
27311
+ if (!ref.fileName.startsWith("."))
27312
+ continue;
27313
+ const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
27314
+ const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
27315
+ if (target)
27316
+ pending.push(target);
27317
+ }
27318
+ }
27319
+ return found;
27320
+ };
27321
+ for (const file of files)
27322
+ if (/(?:^|\/)wrangler(?:\.[\w.-]+)?\.(?:jsonc?|toml)$/.test(file.path)) {
27323
+ try {
27324
+ const config2 = file.path.endsWith(".toml") ? parse(file.text) : JSON.parse(stripJsonc(file.text));
27325
+ const variants = [["default", config2], ...Object.entries(config2.env ?? {}).map(([name, section]) => [name, { ...config2, ...section, queues: section.queues, workflows: section.workflows }])];
27326
+ for (const [environment, section] of variants) {
27327
+ if (typeof section.main !== "string" || isTestWorkerConfig({ path: file.path, name: section.name, mains: [section.main] }))
27328
+ continue;
27329
+ const main = posix2.normalize(posix2.join(dirname10(file.path), section.main));
27330
+ workers.push({ id: `${file.path}#${environment}`, main, cron: Boolean(section.triggers?.crons?.length), queueBindings: new Set((section.queues?.producers ?? []).flatMap((producer) => typeof producer.binding === "string" ? [producer.binding] : [])), workflowClasses: (section.workflows ?? []).flatMap((binding) => typeof binding.class_name === "string" && !binding.script_name ? [binding.class_name] : []), files: closure(main) });
27331
+ }
27332
+ } catch {}
27333
+ }
27334
+ const queueBindingsFor = (path) => {
27335
+ const owners = workers.filter((worker) => worker.files.has(path));
27336
+ return new Set(owners[0] ? [...owners[0].queueBindings].filter((binding) => owners.every((worker) => worker.queueBindings.has(binding))) : []);
27337
+ };
27338
+ const reach = buildImportGraphReachability(ctx.rootDir);
27339
+ const repo = { files, workers, queueBindingsFor, cronEntrypoints: new Set(workers.filter((worker) => worker.cron).map((worker) => worker.main)), deployedFiles: reach.inProd, status: (path) => reach.inProd.has(path) || reach.reachable.has(path) ? "reachable" : "defined_only" };
27340
+ cache2.set(ctx, repo);
27341
+ return repo;
27342
+ }
27343
+ function lineOf5(node) {
27344
+ return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1;
27345
+ }
27346
+ function nameOf(node) {
27347
+ if (!node)
27348
+ return;
27349
+ if (import_typescript11.default.isComputedPropertyName(node) && import_typescript11.default.isStringLiteralLike(node.expression))
27350
+ return node.expression.text;
27351
+ return import_typescript11.default.isIdentifier(node) || import_typescript11.default.isStringLiteralLike(node) || import_typescript11.default.isNumericLiteral(node) ? node.text : undefined;
27352
+ }
27353
+ function visit(node, fn) {
27354
+ fn(node);
27355
+ import_typescript11.default.forEachChild(node, (child) => visit(child, fn));
27356
+ }
27357
+ function componentId(kind, path, name) {
27358
+ return `${kind}:${path}:${name}`;
27359
+ }
27360
+ function artifact(type, name, file, node, reason, status) {
27361
+ return { id: componentId(type, file.path, name), type, name, scope: "shared", sourcePath: file.path, usedByAgentIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
27362
+ }
27363
+ function agent(name, file, node, reason, status) {
27364
+ return { id: componentId("agent", file.path, name), name, kind: "runtime_agent", root: ".", entrypointIds: [], channelAdapterIds: [], artifactIds: [], identityNamespaceIds: [], deploymentIds: [], frameworkIds: [], modelProviderIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
27365
+ }
27366
+ function emptyResult() {
27367
+ return { runtimeAgents: [], artifacts: [], warnings: [] };
27368
+ }
27369
+ function stableResult(result) {
27370
+ const unique2 = (values) => [...new Map(values.map((x) => [x.id, x])).values()].sort((a, b) => a.id.localeCompare(b.id));
27371
+ return { runtimeAgents: unique2(result.runtimeAgents), artifacts: unique2(result.artifacts), warnings: [...new Set(result.warnings)].sort() };
27372
+ }
27373
+
27374
+ // src/harness-extract/enumerators/agents.ts
27375
+ function agentForScope(scope, enumeration) {
27376
+ return enumeration.agentForScope(scope);
27377
+ }
27378
+ function createAgentScopeResolver(result, ctx) {
27379
+ return enumerateAgents(result, ctx).agentForScope;
27380
+ }
27381
+ var enumerations = new WeakMap;
27382
+ var AGENT_BASES3 = new Set(["Think", "Agent", "AIChatAgent", "McpAgent"]);
27383
+ var HTTP_METHODS2 = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]);
27384
+ function routeOf(fn, file) {
27385
+ const name = functionName(fn);
27386
+ if (name && HTTP_METHODS2.has(name) && /(?:^|\/)(?:route|\+server)\.[cm]?[jt]sx?$/.test(file.path))
27387
+ return `${name} ${file.path}`;
27388
+ const parent = fn.parent;
27389
+ if (parent && import_typescript12.default.isCallExpression(parent) && import_typescript12.default.isPropertyAccessExpression(parent.expression) && /^(get|post|put|patch|delete|all|on)$/.test(parent.expression.name.text)) {
27390
+ const path = parent.arguments.find(import_typescript12.default.isStringLiteralLike);
27391
+ if (path)
27392
+ return `${parent.expression.name.text.toUpperCase()} ${path.text} (${file.path})`;
27393
+ }
27394
+ return;
27395
+ }
27396
+ function enumerateAgents(result, ctx) {
27397
+ const cached = enumerations.get(ctx);
27398
+ if (cached)
27399
+ return cached;
27400
+ const repo = enumerationRepository(ctx);
27401
+ const scopes = new Map;
27402
+ const byNode = new Map;
27403
+ const classes = [];
27404
+ const bound = new Set(detectBoundRuntimeClasses(ctx.rootDir).filter((x) => x.kind === "durable_object").map((x) => x.className));
27405
+ const memo = createFrameworkMemo();
27406
+ const keyOf = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
27407
+ for (const file of repo.files) {
27408
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path) || /^scripts\//.test(file.path) && !repo.deployedFiles.has(file.path))
27409
+ continue;
27410
+ const checker = ctx.checkerFor(file.path);
27411
+ visit(file.source, (node) => {
27412
+ if ((import_typescript12.default.isClassDeclaration(node) || import_typescript12.default.isClassExpression(node)) && node.name) {
27413
+ const name2 = node.name.text;
27414
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
27415
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
27416
+ const protocolEvents = new Set;
27417
+ visit(node, (member2) => {
27418
+ if (import_typescript12.default.isStringLiteralLike(member2))
27419
+ protocolEvents.add(member2.text);
27420
+ });
27421
+ const realtime = protocolEvents.has("session.update") && protocolEvents.has("response.create") && [...protocolEvents].some((event) => event.includes("function_call"));
27422
+ const exported = import_typescript12.default.getCombinedModifierFlags(node) & import_typescript12.default.ModifierFlags.Export;
27423
+ const abstract = import_typescript12.default.getCombinedModifierFlags(node) & import_typescript12.default.ModifierFlags.Abstract;
27424
+ if (!abstract && (exported || bound.has(name2)) && (info?.base && AGENT_BASES3.has(info.base) || directBase.some((x) => AGENT_BASES3.has(x)) || exported && realtime)) {
27425
+ classes.push({ file, node, name: name2, chain: info?.chain ?? [name2, ...directBase] });
27426
+ }
27427
+ }
27428
+ if (!isFunctionLike(node) || !node.body)
27429
+ return;
27430
+ const name = functionName(node);
27431
+ const cls = enclosingClass(node)?.name?.text;
27432
+ const route = routeOf(node, file);
27433
+ const label = cls && name ? `${cls}.${name}` : name ?? route ?? `${file.path}:${lineOf5(node)}`;
27434
+ const scope = {
27435
+ key: keyOf(node),
27436
+ label,
27437
+ aliases: [label, ...name ? [name] : [], ...route ? [route] : [], `${file.path}::${label}`, `${file.path}#${label}`],
27438
+ file,
27439
+ node,
27440
+ className: cls,
27441
+ route,
27442
+ calls: new Set,
27443
+ virtualCalls: new Map,
27444
+ deployedCalls: new Set,
27445
+ callsByWorker: new Map(repo.workers.map((worker) => [worker.id, new Set])),
27446
+ callers: new Set,
27447
+ hasModel: false,
27448
+ modelWorkers: new Set,
27449
+ hasTools: false,
27450
+ toolFeedback: false,
27451
+ configuredSteps: false,
27452
+ hasLoop: false,
27453
+ forcedOutput: false
27454
+ };
27455
+ const qualified = (fn, fnName) => {
27456
+ const owner = enclosingClass(fn);
27457
+ return owner?.name && (fn.parent === owner || fn.parent?.parent === owner) ? `${owner.name.text}.${fnName}` : fnName;
27458
+ };
27459
+ if (name) {
27460
+ const parts = [qualified(node, name)];
27461
+ const member2 = import_typescript12.default.isMethodDeclaration(node) || import_typescript12.default.isGetAccessorDeclaration(node) || import_typescript12.default.isSetAccessorDeclaration(node) ? node : import_typescript12.default.isPropertyAssignment(node.parent) ? node.parent : undefined;
27462
+ const object = member2 && import_typescript12.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
27463
+ if (object)
27464
+ parts.unshift(import_typescript12.default.isVariableDeclaration(object.parent) && import_typescript12.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf5(object)}`);
27465
+ for (let outer = (object ?? node).parent;outer; outer = outer.parent) {
27466
+ if (isFunctionLike(outer)) {
27467
+ const outerName = functionName(outer);
27468
+ if (outerName)
27469
+ parts.unshift(qualified(outer, outerName));
27470
+ }
27471
+ }
27472
+ scope.aliases.push(`${file.path}#${parts.join(".")}`);
27473
+ }
27474
+ scope.aliases.push(scope.key);
27475
+ scopes.set(scope.key, scope);
27476
+ byNode.set(node, scope);
27477
+ });
27478
+ }
27479
+ const classChain = (node, seen = new Set) => {
27480
+ if (seen.has(keyOf(node)))
27481
+ return [];
27482
+ seen.add(keyOf(node));
27483
+ const checker = ctx.checkerFor(node.getSourceFile().fileName.slice(ctx.rootDir.length + 1));
27484
+ const bases = node.heritageClauses?.flatMap((clause) => clause.types).flatMap((base) => {
27485
+ const declaration = checker && valueDeclaration(resolvedSymbol(base.expression, checker));
27486
+ return declaration && import_typescript12.default.isClassLike(declaration) ? classChain(declaration, seen) : [];
27487
+ }) ?? [];
27488
+ return [node, ...bases];
27489
+ };
27490
+ for (const cls of classes)
27491
+ cls.nodes = classChain(cls.node);
27492
+ const virtualEdges = new Map;
27493
+ const nearest = (node) => {
27494
+ for (let current = node;current; current = current.parent) {
27495
+ const scope = byNode.get(current);
27496
+ if (scope)
27497
+ return scope;
27498
+ }
27499
+ return;
27500
+ };
27501
+ const bindingTruth = (condition, worker) => {
27502
+ if (condition.kind === import_typescript12.default.SyntaxKind.TrueKeyword)
27503
+ return true;
27504
+ if (condition.kind === import_typescript12.default.SyntaxKind.FalseKeyword)
27505
+ return false;
27506
+ if (import_typescript12.default.isPrefixUnaryExpression(condition) && condition.operator === import_typescript12.default.SyntaxKind.ExclamationToken) {
27507
+ const value = bindingTruth(condition.operand, worker);
27508
+ return value === undefined ? undefined : !value;
27509
+ }
27510
+ if (import_typescript12.default.isPropertyAccessExpression(condition) && /^(?:this\.)?env$/.test(condition.expression.getText()) && (worker ? repo.workers.find((entry) => entry.id === worker)?.queueBindings : repo.queueBindingsFor(condition.getSourceFile().fileName.slice(ctx.rootDir.length + 1)))?.has(condition.name.text))
27511
+ return true;
27512
+ return;
27513
+ };
27514
+ const returns = (node) => Boolean(node && (import_typescript12.default.isReturnStatement(node) || import_typescript12.default.isBlock(node) && node.statements.length && import_typescript12.default.isReturnStatement(node.statements[node.statements.length - 1])));
27515
+ const deployed = (node, worker) => {
27516
+ for (let current = node;current.parent; current = current.parent) {
27517
+ const parent = current.parent;
27518
+ if (import_typescript12.default.isIfStatement(parent)) {
27519
+ const truth = bindingTruth(parent.expression, worker);
27520
+ if (truth !== undefined && (current === parent.thenStatement ? !truth : current === parent.elseStatement ? truth : false))
27521
+ return false;
27522
+ }
27523
+ if (import_typescript12.default.isBlock(parent))
27524
+ for (const prior of parent.statements) {
27525
+ if (prior.getStart() >= current.getStart())
27526
+ break;
27527
+ if (import_typescript12.default.isIfStatement(prior)) {
27528
+ const truth = bindingTruth(prior.expression, worker);
27529
+ if (truth !== undefined && returns(truth ? prior.thenStatement : prior.elseStatement))
27530
+ return false;
27531
+ }
27532
+ }
27533
+ }
27534
+ return true;
27535
+ };
27536
+ const markModel = (scope, node) => {
27537
+ scope.hasModel = true;
27538
+ for (const worker of repo.workers)
27539
+ if (deployed(node, worker.id))
27540
+ scope.modelWorkers.add(worker.id);
27541
+ };
27542
+ for (const site of result.callSites) {
27543
+ if (site.isTest || site.isEval)
27544
+ continue;
27545
+ const file = repo.files.find((x) => x.path === site.path);
27546
+ if (!file)
27547
+ continue;
27548
+ const offset = file.source.getPositionOfLineAndCharacter(Math.max(0, site.line - 1), Math.max(0, site.col - 1));
27549
+ let anchor = file.source;
27550
+ const descend = (node) => {
27551
+ if (node.getStart() <= offset && node.getEnd() >= offset) {
27552
+ anchor = node;
27553
+ import_typescript12.default.forEachChild(node, descend);
27554
+ }
27555
+ };
27556
+ descend(file.source);
27557
+ const scope = nearest(anchor);
27558
+ if (!scope)
27559
+ continue;
27560
+ markModel(scope, anchor);
27561
+ const tools = site.toolsArg ? ctx.nodeAt(site.toolsArg) : undefined;
27562
+ scope.hasTools ||= Boolean(tools && !(import_typescript12.default.isObjectLiteralExpression(tools) && tools.properties.length === 0) && !(import_typescript12.default.isArrayLiteralExpression(tools) && tools.elements.length === 0));
27563
+ scope.aliases.push(site.scope);
27564
+ }
27565
+ const targetsOf = (node, file) => {
27566
+ const checker = ctx.checkerFor(file.path);
27567
+ if (!checker)
27568
+ return [];
27569
+ const at = import_typescript12.default.isPropertyAccessExpression(node) ? node.name : node;
27570
+ const declaration = valueDeclaration(resolvedSymbol(at, checker));
27571
+ if (!declaration)
27572
+ return [];
27573
+ const direct = byNode.get(declaration) ?? scopes.get(keyOf(declaration));
27574
+ if (direct)
27575
+ return [direct];
27576
+ if (import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer) {
27577
+ const fn = byNode.get(declaration.initializer) ?? scopes.get(keyOf(declaration.initializer));
27578
+ if (fn)
27579
+ return [fn];
27580
+ }
27581
+ return [];
27582
+ };
27583
+ for (const scope of scopes.values()) {
27584
+ const inspect = (node) => {
27585
+ if (node !== scope.node && isFunctionLike(node)) {
27586
+ return;
27587
+ }
27588
+ if (import_typescript12.default.isWhileStatement(node) || import_typescript12.default.isDoStatement(node) || import_typescript12.default.isForStatement(node) || import_typescript12.default.isForOfStatement(node))
27589
+ scope.hasLoop = true;
27590
+ if ((import_typescript12.default.isIdentifier(node) || import_typescript12.default.isStringLiteralLike(node)) && /^(?:tool_calls|toolCalls|tool_use|tool_result|tool_results|toolResults)$/.test(node.text)) {
27591
+ scope.hasTools = true;
27592
+ scope.toolFeedback = true;
27593
+ }
27594
+ if (import_typescript12.default.isObjectLiteralExpression(node)) {
27595
+ const fields = new Map(node.properties.filter(import_typescript12.default.isPropertyAssignment).map((p2) => [nameOf(p2.name), p2.initializer]));
27596
+ const type = fields.get("type");
27597
+ if (type && import_typescript12.default.isStringLiteralLike(type) && type.text === "tool" && fields.has("name"))
27598
+ scope.forcedOutput = true;
27599
+ }
27600
+ if (import_typescript12.default.isCallExpression(node) || import_typescript12.default.isNewExpression(node)) {
27601
+ const callee = node.expression.getText();
27602
+ if (/(?:chat\.)?completions\.create$|messages\.(?:create|stream)$|responses\.(?:create|stream)$/.test(callee))
27603
+ markModel(scope, node);
27604
+ if (/\.runTurn$/.test(callee) && scope.node.parameters.some((param) => /tools/i.test(param.name.getText())))
27605
+ markModel(scope, node);
27606
+ const connect = (at) => {
27607
+ for (const target of byNode.has(at) ? [byNode.get(at)] : targetsOf(at, scope.file)) {
27608
+ if (import_typescript12.default.isPropertyAccessExpression(at) && at.expression.kind === import_typescript12.default.SyntaxKind.ThisKeyword) {
27609
+ virtualEdges.set(`${scope.key}|${target.key}`, at.name.text);
27610
+ scope.virtualCalls.set(target.key, at.name.text);
27611
+ }
27612
+ scope.calls.add(target.key);
27613
+ if (deployed(at))
27614
+ scope.deployedCalls.add(target.key);
27615
+ for (const [worker, calls] of scope.callsByWorker)
27616
+ if (deployed(at, worker))
27617
+ calls.add(target.key);
27618
+ target.callers.add(scope.key);
27619
+ }
27620
+ };
27621
+ connect(node.expression);
27622
+ const connectArgument = (at) => {
27623
+ if (isFunctionLike(at)) {
27624
+ connect(at);
27625
+ return;
27626
+ }
27627
+ if (import_typescript12.default.isIdentifier(at) || import_typescript12.default.isPropertyAccessExpression(at))
27628
+ connect(at);
27629
+ import_typescript12.default.forEachChild(at, connectArgument);
27630
+ };
27631
+ for (const argument of node.arguments ?? [])
27632
+ connectArgument(argument);
27633
+ for (const argument of node.arguments ?? [])
27634
+ if (import_typescript12.default.isObjectLiteralExpression(argument)) {
27635
+ const fields = new Set(argument.properties.map((p2) => nameOf(p2.name)));
27636
+ if (fields.has("model") && fields.has("messages") && fields.has("tools")) {
27637
+ markModel(scope, node);
27638
+ scope.hasTools = true;
27639
+ }
27640
+ }
27641
+ if (/(?:^|\.)(?:stepCountIs|isStepCount)$/.test(node.expression.getText()) && node.arguments?.[0] && import_typescript12.default.isNumericLiteral(node.arguments?.[0]) && Number(node.arguments?.[0].text) > 1) {
27642
+ scope.hasLoop = true;
27643
+ scope.configuredSteps = true;
27644
+ }
27645
+ }
27646
+ if (import_typescript12.default.isPropertyAssignment(node) && nameOf(node.name) === "maxSteps" && import_typescript12.default.isNumericLiteral(node.initializer) && Number(node.initializer.text) > 1) {
27647
+ scope.hasLoop = true;
27648
+ scope.configuredSteps = true;
27649
+ }
27650
+ import_typescript12.default.forEachChild(node, inspect);
27651
+ };
27652
+ inspect(scope.node);
27653
+ }
27654
+ const modelQueue = [...scopes.values()].filter((scope) => scope.hasModel);
27655
+ for (let index = 0;index < modelQueue.length; index++) {
27656
+ const scope = modelQueue[index];
27657
+ if (scope.reachesModel)
27658
+ continue;
27659
+ scope.reachesModel = true;
27660
+ for (const caller of scope.callers) {
27661
+ const parent = scopes.get(caller);
27662
+ if (parent && !parent.reachesModel)
27663
+ modelQueue.push(parent);
27664
+ }
27665
+ }
27666
+ const agents = new Map;
27667
+ const owners = new Map;
27668
+ const assign = (key, id) => {
27669
+ let values = owners.get(key);
27670
+ if (!values)
27671
+ owners.set(key, values = new Set);
27672
+ values.add(id);
27673
+ };
27674
+ for (const cls of classes) {
27675
+ const emitted = agent(cls.name, cls.file, cls.node, "Concrete agent/framework class or realtime model/tool bridge", repo.status(cls.file.path));
27676
+ agents.set(emitted.id, emitted);
27677
+ }
27678
+ for (const scope of scopes.values()) {
27679
+ let nestedInFunction = false;
27680
+ for (let parent = scope.node.parent;parent && !import_typescript12.default.isClassLike(parent); parent = parent.parent)
27681
+ if (isFunctionLike(parent)) {
27682
+ nestedInFunction = true;
27683
+ break;
27684
+ }
27685
+ if (scope.className && !nestedInFunction) {
27686
+ let member2 = scope.node;
27687
+ while (member2.parent && !import_typescript12.default.isClassLike(member2.parent))
27688
+ member2 = member2.parent;
27689
+ const memberName = "name" in member2 ? nameOf(member2.name) : undefined;
27690
+ for (const cls of classes) {
27691
+ const ownerClass = enclosingClass(scope.node);
27692
+ const baseIndex = cls.nodes.findIndex((node) => ownerClass && keyOf(node) === keyOf(ownerClass));
27693
+ if (baseIndex < 0)
27694
+ continue;
27695
+ const overridden = memberName && cls.nodes.slice(0, baseIndex).some((node) => node.members.some((candidate) => nameOf(candidate.name) === memberName));
27696
+ if (!overridden)
27697
+ assign(scope.key, componentId("agent", cls.file.path, cls.name));
27698
+ }
27699
+ }
27700
+ if (!scope.className && !scope.forcedOutput && scope.hasLoop && scope.hasTools && (scope.toolFeedback || scope.configuredSteps) && scope.reachesModel) {
27701
+ let boundary = scope;
27702
+ for (let parent = scope.node.parent;parent; parent = parent.parent) {
27703
+ const outer = byNode.get(parent);
27704
+ if (outer?.route) {
27705
+ boundary = outer;
27706
+ break;
27707
+ }
27708
+ }
27709
+ const name = boundary.route ?? functionName(boundary.node);
27710
+ if (!name)
27711
+ continue;
27712
+ const emitted = agent(name, boundary.file, scope.node, "Function or route owns a multi-step model/tool feedback loop", repo.status(boundary.file.path));
27713
+ agents.set(emitted.id, emitted);
27714
+ assign(boundary.key, emitted.id);
27715
+ }
27716
+ }
27717
+ let changed = true;
27718
+ while (changed) {
27719
+ changed = false;
27720
+ for (const scope of scopes.values())
27721
+ for (const callee of scope.calls)
27722
+ for (const id of owners.get(scope.key) ?? []) {
27723
+ let targetKey = callee;
27724
+ const virtual = virtualEdges.get(`${scope.key}|${callee}`), concrete = classes.find((cls) => componentId("agent", cls.file.path, cls.name) === id);
27725
+ if (virtual && concrete) {
27726
+ const implementation = concrete.nodes.flatMap((node) => node.members.filter((member2) => nameOf(member2.name) === virtual))[0];
27727
+ if (implementation && scopes.has(keyOf(implementation)))
27728
+ targetKey = keyOf(implementation);
27729
+ }
27730
+ const before = owners.get(targetKey)?.size ?? 0;
27731
+ assign(targetKey, id);
27732
+ changed ||= (owners.get(targetKey)?.size ?? 0) !== before;
27733
+ }
27734
+ }
27735
+ const scopeOwners = new Map;
27736
+ const mergeAlias = (label, ids) => {
27737
+ let values = scopeOwners.get(label);
27738
+ if (!values)
27739
+ scopeOwners.set(label, values = new Set);
27740
+ for (const id of ids)
27741
+ values.add(id);
27742
+ };
27743
+ const classAliases = new Map;
27744
+ for (const cls of classes)
27745
+ for (const base of cls.nodes) {
27746
+ if (!base.name)
27747
+ continue;
27748
+ const qualified = `${base.getSourceFile().fileName.slice(ctx.rootDir.length + 1)}#${base.name.text}`;
27749
+ mergeAlias(qualified, [componentId("agent", cls.file.path, cls.name)]);
27750
+ let variants = classAliases.get(base.name.text);
27751
+ if (!variants)
27752
+ classAliases.set(base.name.text, variants = new Set);
27753
+ variants.add(qualified);
27754
+ }
27755
+ for (const [name, variants] of classAliases)
27756
+ if (variants.size === 1)
27757
+ mergeAlias(name, scopeOwners.get([...variants][0]) ?? []);
27758
+ const aliases = new Map;
27759
+ for (const scope of scopes.values())
27760
+ for (const alias of scope.aliases) {
27761
+ const matches = aliases.get(alias) ?? [];
27762
+ matches.push(scope);
27763
+ aliases.set(alias, matches);
27764
+ }
27765
+ for (const [alias, matches] of aliases) {
27766
+ const candidates = matches.map((scope) => [...owners.get(scope.key) ?? []].sort());
27767
+ if (candidates.every((ids) => JSON.stringify(ids) === JSON.stringify(candidates[0])))
27768
+ mergeAlias(alias, candidates[0]);
27769
+ }
27770
+ const output = {
27771
+ runtimeAgents: [...agents.values()].sort((a, b) => a.id.localeCompare(b.id)),
27772
+ agentForScope: (scope) => scope ? [...scopeOwners.get(scope) ?? []].sort() : [],
27773
+ scopes: [...scopes.values()]
27774
+ };
27775
+ enumerations.set(ctx, output);
27776
+ assignAgentIds(result, output.agentForScope);
27777
+ return output;
27778
+ }
27779
+
27780
+ // src/harness-extract/enumerators/workflows.ts
27781
+ var import_typescript13 = __toESM(require_typescript(), 1);
27782
+ function enumerateWorkflows(result, ctx) {
27783
+ const output = emptyResult();
27784
+ const repo = enumerationRepository(ctx);
27785
+ const nodeKey = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
27786
+ const bindings = new Set;
27787
+ for (const worker of repo.workers) {
27788
+ const file = repo.files.find((entry) => entry.path === worker.main), checker = file && ctx.checkerFor(file.path);
27789
+ const module = file && checker?.getSymbolAtLocation(file.source);
27790
+ if (!module || !checker)
27791
+ continue;
27792
+ for (const name of worker.workflowClasses) {
27793
+ let exported = checker.getExportsOfModule(module).find((symbol) => symbol.name === name);
27794
+ if (exported && exported.flags & import_typescript13.default.SymbolFlags.Alias)
27795
+ exported = checker.getAliasedSymbol(exported);
27796
+ const declaration = exported && valueDeclaration(exported);
27797
+ if (declaration && import_typescript13.default.isClassDeclaration(declaration))
27798
+ bindings.add(nodeKey(declaration));
27799
+ }
27800
+ }
27801
+ const memo = createFrameworkMemo();
27802
+ for (const file of repo.files) {
27803
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path))
27804
+ continue;
27805
+ visit(file.source, (node) => {
27806
+ if (!import_typescript13.default.isClassDeclaration(node) || !node.name || import_typescript13.default.getCombinedModifierFlags(node) & import_typescript13.default.ModifierFlags.Abstract)
27807
+ return;
27808
+ const checker = ctx.checkerFor(file.path);
27809
+ const base = checker ? frameworkBaseOf(node, checker, memo)?.base : undefined;
27810
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
27811
+ if (!bindings.has(nodeKey(node)) && base !== "WorkflowEntrypoint" && base !== "AgentWorkflow" && !directBase.some((x) => /^(?:WorkflowEntrypoint|AgentWorkflow)$/.test(x)))
27812
+ return;
27813
+ const entry = artifact("entrypoint", node.name.text, file, node, "Concrete Workflow class or Wrangler workflow binding", repo.status(file.path));
27814
+ entry.id = componentId("workflow", file.path, node.name.text);
27815
+ if (bindings.has(nodeKey(node))) {
27816
+ Object.assign(entry, { componentKind: "workflow", trigger: "workflow_binding" });
27817
+ }
27818
+ output.artifacts.push(entry);
27819
+ });
27820
+ }
27821
+ for (const worker of repo.workers.filter((entry) => entry.cron)) {
27822
+ const scopes = enumerateAgents(result, ctx).scopes;
27823
+ const byKey = new Map(scopes.map((scope) => [scope.key, scope]));
27824
+ const implementations = new Map, workerClasses = new Set;
27825
+ const deployedCalls = (scope) => {
27826
+ const calls = scope.callsByWorker.get(worker.id) ?? scope.deployedCalls;
27827
+ const cls = enclosingClass(scope.node);
27828
+ if (!cls || !workerClasses.has(nodeKey(cls)))
27829
+ return calls;
27830
+ const member2 = scope.node.parent === cls ? scope.node : scope.node.parent;
27831
+ if (import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static)
27832
+ return calls;
27833
+ return new Set([...calls].map((key) => {
27834
+ const method = scope.virtualCalls.get(key);
27835
+ return method && implementations.has(method) ? implementations.get(method) : key;
27836
+ }));
27837
+ };
27838
+ const modelScopes = new Set(scopes.filter((scope) => scope.modelWorkers.has(worker.id)).map((scope) => scope.key));
27839
+ const mainFile = repo.files.find((file) => file.path === worker.main), checker = mainFile && ctx.checkerFor(mainFile.path);
27840
+ const exportedNodes = new Set, visited = new Set;
27841
+ const resolveWorker = (node) => {
27842
+ if (!node || visited.has(node))
27843
+ return;
27844
+ visited.add(node);
27845
+ if (import_typescript13.default.isParenthesizedExpression(node) || import_typescript13.default.isAsExpression(node) || import_typescript13.default.isSatisfiesExpression(node) || import_typescript13.default.isNonNullExpression(node)) {
27846
+ resolveWorker(node.expression);
27847
+ return;
27848
+ }
27849
+ if (import_typescript13.default.isCallExpression(node) && /(?:^|\.)withSentry$/.test(node.expression.getText())) {
27850
+ for (const argument of node.arguments)
27851
+ resolveWorker(argument);
27852
+ return;
27853
+ }
27854
+ if (import_typescript13.default.isExportAssignment(node)) {
27855
+ resolveWorker(node.expression);
27856
+ return;
27857
+ }
27858
+ if (import_typescript13.default.isVariableDeclaration(node)) {
27859
+ resolveWorker(node.initializer);
27860
+ return;
27861
+ }
27862
+ if (import_typescript13.default.isIdentifier(node) && checker) {
27863
+ resolveWorker(valueDeclaration(resolvedSymbol(node, checker)));
27864
+ return;
27865
+ }
27866
+ exportedNodes.add(node);
27867
+ };
27868
+ const module = mainFile && checker?.getSymbolAtLocation(mainFile.source);
27869
+ const exported = module && checker?.getExportsOfModule(module).find((symbol2) => symbol2.name === "default");
27870
+ const symbol = exported && checker && (exported.flags & import_typescript13.default.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported);
27871
+ resolveWorker(symbol && valueDeclaration(symbol));
27872
+ const collectImplementations = (node) => {
27873
+ if (!import_typescript13.default.isClassLike(node) || workerClasses.has(nodeKey(node)))
27874
+ return;
27875
+ workerClasses.add(nodeKey(node));
27876
+ for (const member2 of node.members) {
27877
+ if (import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static)
27878
+ continue;
27879
+ const name = nameOf(member2.name);
27880
+ const implementation = byKey.get(nodeKey(member2)) ?? (import_typescript13.default.isPropertyDeclaration(member2) && member2.initializer ? byKey.get(nodeKey(member2.initializer)) : undefined);
27881
+ if (name && !implementations.has(name))
27882
+ implementations.set(name, implementation?.key ?? "(non-callable override)");
27883
+ }
27884
+ if (checker)
27885
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
27886
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
27887
+ if (declaration)
27888
+ collectImplementations(declaration);
27889
+ }
27890
+ };
27891
+ for (const node of exportedNodes)
27892
+ collectImplementations(node);
27893
+ let changed = true;
27894
+ while (changed) {
27895
+ changed = false;
27896
+ for (const scope of scopes)
27897
+ if (!modelScopes.has(scope.key) && [...deployedCalls(scope)].some((key) => modelScopes.has(key))) {
27898
+ modelScopes.add(scope.key);
27899
+ changed = true;
27900
+ }
27901
+ }
27902
+ const scheduledNodes = new Set;
27903
+ const resolveScheduled = (node, seen2 = new Set) => {
27904
+ if (!node || seen2.has(node))
27905
+ return;
27906
+ seen2.add(node);
27907
+ if (import_typescript13.default.isIdentifier(node) && checker) {
27908
+ resolveScheduled(valueDeclaration(resolvedSymbol(node, checker)), seen2);
27909
+ return;
27910
+ }
27911
+ if (import_typescript13.default.isVariableDeclaration(node) || import_typescript13.default.isPropertyAssignment(node) || import_typescript13.default.isPropertyDeclaration(node)) {
27912
+ resolveScheduled(node.initializer, seen2);
27913
+ return;
27914
+ }
27915
+ if (import_typescript13.default.isShorthandPropertyAssignment(node)) {
27916
+ resolveScheduled(checker && valueDeclaration(checker.getShorthandAssignmentValueSymbol(node)), seen2);
27917
+ return;
27918
+ }
27919
+ if (import_typescript13.default.isParenthesizedExpression(node) || import_typescript13.default.isAsExpression(node) || import_typescript13.default.isSatisfiesExpression(node) || import_typescript13.default.isNonNullExpression(node)) {
27920
+ resolveScheduled(node.expression, seen2);
27921
+ return;
27922
+ }
27923
+ scheduledNodes.add(node);
27924
+ };
27925
+ const collectScheduled = (node, seen2 = new Set) => {
27926
+ if (seen2.has(node))
27927
+ return;
27928
+ seen2.add(node);
27929
+ const members = import_typescript13.default.isObjectLiteralExpression(node) ? node.properties : import_typescript13.default.isClassLike(node) ? node.members : [];
27930
+ const handlers = members.filter((member2) => nameOf(member2.name) === "scheduled" && !(import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static));
27931
+ for (const member2 of handlers)
27932
+ resolveScheduled(member2);
27933
+ if (!handlers.length && import_typescript13.default.isClassLike(node) && checker)
27934
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
27935
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
27936
+ if (declaration)
27937
+ collectScheduled(declaration, seen2);
27938
+ }
27939
+ };
27940
+ for (const node of exportedNodes)
27941
+ collectScheduled(node);
27942
+ const roots = scopes.filter((scope) => [...scheduledNodes].some((node) => node.getSourceFile().fileName === scope.node.getSourceFile().fileName && node.getStart() === scope.node.getStart()));
27943
+ const seen = new Set;
27944
+ const queue = roots.flatMap((scope) => scope.modelWorkers.has(worker.id) ? [scope.key] : [...deployedCalls(scope)]);
27945
+ for (let i = 0;i < queue.length; i++) {
27946
+ const key = queue[i];
27947
+ if (seen.has(key))
27948
+ continue;
27949
+ seen.add(key);
27950
+ const scope = byKey.get(key);
27951
+ if (!scope)
27952
+ continue;
27953
+ if (!modelScopes.has(scope.key)) {
27954
+ if (/(?:Cron|Pipeline)$/.test(scope.label)) {
27955
+ const entry = artifact("entrypoint", scope.label, scope.file, scope.node, "Scheduled entrypoint has no deployed model step on its own pipeline", repo.status(scope.file.path));
27956
+ const proof = [...scope.calls].map((callee) => byKey.get(callee)).filter((callee) => callee?.reachesModel).map((callee) => `${callee.file.path}#${callee.label}`);
27957
+ Object.assign(entry, { exclusionReason: scope.reachesModel ? "Model reachable only through a queue consumer or statically excluded fallback" : "No model reachable from scheduled pipeline", proofPath: [`${scope.file.path}#${scope.label}`, ...proof] });
27958
+ output.artifacts.push(entry);
27959
+ } else
27960
+ queue.push(...deployedCalls(scope));
27961
+ continue;
27962
+ }
27963
+ if (/(?:Cron|Pipeline)$/.test(scope.label) || scope.modelWorkers.has(worker.id)) {
27964
+ const entry = artifact("entrypoint", scope.label, scope.file, scope.node, "Cron dispatch reaches this model-backed pipeline", repo.status(scope.file.path));
27965
+ entry.id = componentId("workflow", scope.file.path, scope.label);
27966
+ entry.componentKind = "workflow";
27967
+ entry.trigger = "cron";
27968
+ output.artifacts.push(entry);
27969
+ if (roots.includes(scope))
27970
+ queue.push(...deployedCalls(scope));
27971
+ } else
27972
+ queue.push(...deployedCalls(scope));
27973
+ }
27974
+ }
27975
+ return stableResult(output);
27976
+ }
27977
+
27978
+ // src/harness-extract/enumerators/catalog.ts
27979
+ var import_typescript14 = __toESM(require_typescript(), 1);
27980
+ var THINK_WORKSPACE_TOOLS = ["read", "write", "edit", "list", "find", "grep", "delete"];
27981
+ function strings(expression, checker, seen = new Set) {
27982
+ if (!expression)
27983
+ return [];
27984
+ const node = unwrap(expression);
27985
+ if (seen.has(node))
27986
+ return [];
27987
+ seen.add(node);
27988
+ if (import_typescript14.default.isIdentifier(node)) {
27989
+ const declaration = checker && valueDeclaration(resolvedSymbol(node, checker));
27990
+ if (!declaration || !import_typescript14.default.isVariableDeclaration(declaration))
27991
+ return [];
27992
+ return strings(declaration.initializer, checker, seen);
27993
+ }
27994
+ if (import_typescript14.default.isArrayLiteralExpression(node))
27995
+ return node.elements.flatMap((entry) => import_typescript14.default.isSpreadElement(entry) ? strings(entry.expression, checker, seen) : strings(entry, checker, seen));
27996
+ if (import_typescript14.default.isStringLiteralLike(node))
27997
+ return [{ name: node.text, node }];
27998
+ if (import_typescript14.default.isNewExpression(node) && node.expression.getText() === "Set")
27999
+ return strings(node.arguments?.[0], checker, seen);
28000
+ return [];
28001
+ }
28002
+ function property(object, name) {
28003
+ const entry = object.properties.find((item) => item.name && nameOf(item.name) === name);
28004
+ return entry && import_typescript14.default.isPropertyAssignment(entry) ? entry.initializer : entry && import_typescript14.default.isShorthandPropertyAssignment(entry) ? entry.name : undefined;
28005
+ }
28006
+ function inheritedTrue(node, propertyName2, checker, seen = new Set) {
28007
+ if (seen.has(node))
28008
+ return false;
28009
+ seen.add(node);
28010
+ const own = node.members.find((member2) => nameOf(member2.name) === propertyName2);
28011
+ if (own && import_typescript14.default.isPropertyDeclaration(own) && own.initializer)
28012
+ return unwrap(own.initializer).kind === import_typescript14.default.SyntaxKind.TrueKeyword;
28013
+ if (checker)
28014
+ for (const base of node.heritageClauses?.flatMap((h) => h.types) ?? []) {
28015
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
28016
+ if (declaration && (import_typescript14.default.isClassDeclaration(declaration) || import_typescript14.default.isClassExpression(declaration)))
28017
+ return inheritedTrue(declaration, propertyName2, checker, seen);
28018
+ }
28019
+ return false;
28020
+ }
28021
+ function enumerateToolCatalog(result, ctx) {
28022
+ const output = emptyResult(), repo = enumerationRepository(ctx), agents = enumerateAgents(result, ctx);
28023
+ const agentByName = new Map(agents.runtimeAgents.map((entry) => [entry.name, entry.id]));
28024
+ const symbolOwners = new Map;
28025
+ for (const scope of agents.scopes) {
28026
+ const owners = agents.agentForScope(scope.key);
28027
+ const checker = ctx.checkerFor(scope.file.path);
28028
+ if (!owners.length || !checker)
28029
+ continue;
28030
+ visit(scope.node, (node) => {
28031
+ if (!import_typescript14.default.isIdentifier(node) || !/ALLOW|MCP_NAME/.test(node.text))
28032
+ return;
28033
+ const declaration = valueDeclaration(resolvedSymbol(node, checker));
28034
+ if (!declaration || !import_typescript14.default.isVariableDeclaration(declaration) || !import_typescript14.default.isIdentifier(declaration.name))
28035
+ return;
28036
+ const key = `${declaration.getSourceFile().fileName}:${declaration.name.text}`;
28037
+ let existing = symbolOwners.get(key);
28038
+ if (!existing)
28039
+ symbolOwners.set(key, existing = new Set);
28040
+ for (const id of owners)
28041
+ existing.add(id);
28042
+ });
28043
+ }
28044
+ const ownersAt = (node, path) => {
28045
+ const scope = agents.scopes.filter((s) => s.file.path === path && s.node.getStart() <= node.getStart() && s.node.getEnd() >= node.getEnd()).sort((a, b) => a.node.getWidth() - b.node.getWidth())[0];
28046
+ return scope ? agents.agentForScope(scope.key) : [];
28047
+ };
28048
+ const memo = createFrameworkMemo();
28049
+ const thinkIds = new Set;
28050
+ for (const runtime of agents.runtimeAgents) {
28051
+ const file = repo.files.find((entry) => entry.path === runtime.evidence[0]?.path), checker = file && ctx.checkerFor(file.path);
28052
+ if (!file || !checker)
28053
+ continue;
28054
+ visit(file.source, (node) => {
28055
+ if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name?.text === runtime.name && frameworkBaseOf(node, checker, memo)?.base === "Think")
28056
+ thinkIds.add(runtime.id);
28057
+ });
28058
+ }
28059
+ const add = (name, file, node, source, reason, owners = []) => {
28060
+ const evidenceFile = repo.files.find((entry2) => entry2.source.fileName === node.getSourceFile().fileName) ?? file;
28061
+ const entry = artifact("tool", name, evidenceFile, node, reason, repo.status(file.path));
28062
+ entry.catalogSource = source;
28063
+ entry.usedByAgentIds = owners;
28064
+ output.artifacts.push(entry);
28065
+ return entry;
28066
+ };
28067
+ for (const file of repo.files) {
28068
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path) || /^scripts\//.test(file.path) && !repo.deployedFiles.has(file.path))
28069
+ continue;
28070
+ const checker = ctx.checkerFor(file.path), declarations = new Map;
28071
+ visit(file.source, (node) => {
28072
+ if (import_typescript14.default.isVariableDeclaration(node) && import_typescript14.default.isIdentifier(node.name) && node.initializer)
28073
+ declarations.set(node.name.text, node.initializer);
28074
+ });
28075
+ visit(file.source, (node) => {
28076
+ if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name && agentByName.has(node.name.text)) {
28077
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
28078
+ const directThink = node.heritageClauses?.some((h) => h.types.some((t) => t.expression.getText() === "Think"));
28079
+ if (info?.base === "Think" || directThink) {
28080
+ const owners2 = agents.agentForScope(`${file.path}#${node.name.text}`);
28081
+ const names = [...THINK_WORKSPACE_TOOLS];
28082
+ if (inheritedTrue(node, "workspaceBash", checker))
28083
+ names.push("bash");
28084
+ for (const name of names)
28085
+ add(name, file, node, "think", "Think workspace tool inherited by this concrete agent", owners2);
28086
+ }
28087
+ }
28088
+ if (import_typescript14.default.isPropertyAccessExpression(node) && node.name.text === "activate_skill" || import_typescript14.default.isPropertyAssignment(node) && nameOf(node.name) === "activate_skill") {
28089
+ const owner = ownersAt(node, file.path);
28090
+ add("activate_skill", file, node, "think", "Source explicitly exposes Think skill activation", owner);
28091
+ }
28092
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isPropertyAccessExpression(node.expression) && /^(?:registerTool|tool)$/.test(node.expression.name.text) && checker) {
28093
+ const receiver = valueDeclaration(resolvedSymbol(node.expression.expression, checker));
28094
+ const init = receiver && import_typescript14.default.isVariableDeclaration(receiver) && receiver.initializer ? unwrap(receiver.initializer) : undefined;
28095
+ const origin = init && import_typescript14.default.isNewExpression(init) && import_typescript14.default.isIdentifier(init.expression) ? importOrigin(init.expression, checker) : undefined;
28096
+ const name = node.arguments[0];
28097
+ if (origin?.module.startsWith("@modelcontextprotocol/sdk/") && origin.imported === "McpServer" && name && import_typescript14.default.isStringLiteralLike(name)) {
28098
+ add(name.text, file, name, "mcp_server", "MCP SDK server explicitly registers this model-facing tool name", ownersAt(node, file.path));
28099
+ }
28100
+ }
28101
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isPropertyAccessExpression(node.expression) && node.expression.expression.getText() === "Output" && node.expression.name.text === "object") {
28102
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
28103
+ if (owners2.length && checker && import_typescript14.default.isIdentifier(node.expression.expression) && ["ai", "@cloudflare/think"].includes(importOrigin(node.expression.expression, checker)?.module ?? ""))
28104
+ add("think_final_answer", file, node, "think", "Think structured output is offered as the framework final-answer tool", owners2);
28105
+ }
28106
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isIdentifier(node.expression) && node.expression.text === "createExecuteRuntime") {
28107
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
28108
+ if (owners2.length && checker && importOrigin(node.expression, checker)?.module.startsWith("@cloudflare/think"))
28109
+ add("execute", file, node, "think", "Think Code Mode runtime explicitly enabled for this agent", owners2);
28110
+ }
28111
+ if (!import_typescript14.default.isObjectLiteralExpression(node))
28112
+ return;
28113
+ const serverNames = strings(property(node, "name"), checker), allow = property(node, "allow");
28114
+ if (serverNames.length !== 1 || !allow || !property(node, "url"))
28115
+ return;
28116
+ const server = serverNames[0].name;
28117
+ const owners = ownersAt(node, file.path);
28118
+ if (import_typescript14.default.isStringLiteralLike(unwrap(allow)) && unwrap(allow).text === "all") {
28119
+ const entry = add(`${server} dynamic MCP tools`, file, allow, "mcp_dynamic_group", "Server schemas are admitted dynamically as one bounded catalog group", owners);
28120
+ entry.serverName = server;
28121
+ entry.dynamicGroup = true;
28122
+ entry.namePattern = `tool_<${server}ServerId>_*`;
28123
+ return;
28124
+ }
28125
+ for (const tool of strings(allow, checker)) {
28126
+ const name = `tool_<${server}ServerIdNoDashes>_${tool.name}`;
28127
+ const entry = add(name, file, tool.node, "mcp_allowlist", "Literal MCP allowlist converted by the Agents SDK tool_<serverId>_<name> contract", owners);
28128
+ entry.id = componentId("tool", file.path, `${server}:${name}`);
28129
+ entry.serverName = server;
28130
+ entry.namePattern = name;
28131
+ }
28132
+ });
28133
+ for (const [name, initializer] of declarations) {
28134
+ const match = name.match(/^(.*)_ALLOWED_TOOLS$/);
28135
+ if (!match)
28136
+ continue;
28137
+ const serverName = strings(declarations.get(`${match[1]}_MCP_NAME`), checker)[0]?.name;
28138
+ if (!serverName)
28139
+ continue;
28140
+ for (const tool of strings(initializer, checker)) {
28141
+ const entry = add(`${serverName}_${tool.name}`, file, tool.node, "mcp_allowlist", "Explicit named MCP allowlist with server-prefixed model name");
28142
+ entry.serverName = serverName;
28143
+ entry.usedByAgentIds = [...symbolOwners.get(`${file.source.fileName}:${name}`) ?? []].sort();
28144
+ }
28145
+ }
28146
+ }
28147
+ const merged = new Map;
28148
+ for (const item of output.artifacts) {
28149
+ const previous = merged.get(item.name);
28150
+ if (previous) {
28151
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
28152
+ const seen = new Set(previous.evidence.map((e) => `${e.path}:${e.line}`));
28153
+ previous.evidence.push(...item.evidence.filter((e) => !seen.has(`${e.path}:${e.line}`)));
28154
+ if (item.status === "in_prod" || item.status === "reachable" && previous.status === "defined_only")
28155
+ previous.status = item.status;
28156
+ } else {
28157
+ item.id = `tool:catalog:${item.name}`;
28158
+ merged.set(item.name, item);
28159
+ }
28160
+ }
28161
+ output.artifacts = [...merged.values()];
28162
+ return stableResult(output);
28163
+ }
28164
+
28165
+ // src/harness-extract/enumerators/index.ts
28166
+ var ENUMERATORS = [
28167
+ { id: "agents", enumerate: ({ result }, ctx) => ({ runtimeAgents: enumerateAgents(result, ctx).runtimeAgents }) },
28168
+ { id: "workflows", enumerate: ({ result }, ctx) => enumerateWorkflows(result, ctx) },
28169
+ { id: "framework-mcp-catalog", enumerate: ({ result }, ctx) => enumerateToolCatalog(result, ctx) }
28170
+ ];
28171
+ function enumerateHarnessComponents(result, ctx) {
28172
+ const agents = enumerateAgents(result, ctx), workflows = enumerateWorkflows(result, ctx), catalog = enumerateToolCatalog(result, ctx);
28173
+ return stableResult({ runtimeAgents: agents.runtimeAgents, artifacts: [...workflows.artifacts, ...catalog.artifacts], warnings: [...workflows.warnings, ...catalog.warnings] });
28174
+ }
28175
+ function mergeEnumeratedComponents(artifacts, components) {
28176
+ const merged = new Map;
28177
+ const definitions = new Map;
28178
+ for (const item of [...artifacts, ...components.artifacts]) {
28179
+ const key = item.type === "tool" ? `tool:${item.name}` : item.id;
28180
+ if (item.type === "tool" && item.body) {
28181
+ let variants = definitions.get(key);
28182
+ if (!variants)
28183
+ definitions.set(key, variants = []);
28184
+ if (!variants.some((entry) => entry.id === item.id && entry.body === item.body))
28185
+ variants.push({ id: item.id, sourcePath: item.sourcePath, body: item.body, evidence: [...item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
28186
+ }
28187
+ const previous = merged.get(key);
28188
+ if (!previous) {
28189
+ merged.set(key, { ...item, evidence: [...item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
28190
+ continue;
28191
+ }
28192
+ const rank = { defined_only: 0, reachable: 1, in_prod: 2 };
28193
+ if (item.status && (!previous.status || rank[item.status] > rank[previous.status]))
28194
+ previous.status = item.status;
28195
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
28196
+ const evidence = new Set(previous.evidence.map((entry) => `${entry.path}:${entry.line}`));
28197
+ previous.evidence.push(...item.evidence.filter((entry) => !evidence.has(`${entry.path}:${entry.line}`)));
28198
+ if (!previous.body && item.body && !previous.definitionVariants)
28199
+ previous.body = item.body;
28200
+ }
28201
+ for (const [key, variants] of definitions) {
28202
+ const item = merged.get(key);
28203
+ if (variants.length > 1 || item.id !== variants[0].id)
28204
+ item.definitionVariants = variants;
28205
+ if (new Set(variants.map((entry) => entry.body)).size > 1)
28206
+ delete item.body;
28207
+ }
28208
+ const output = [...merged.values()].sort((a, b) => a.id.localeCompare(b.id));
28209
+ const runtimeAgents = components.runtimeAgents.map((entry) => ({
28210
+ ...entry,
28211
+ artifactIds: [...new Set([...entry.artifactIds, ...output.filter((item) => item.usedByAgentIds.includes(entry.id)).map((item) => item.id)])].sort()
28212
+ }));
28213
+ return { runtimeAgents, artifacts: output };
28214
+ }
28215
+
28216
+ export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals, EXTRACT_SCHEMA_VERSION, agentForScope, createAgentScopeResolver, enumerateAgents, enumerateWorkflows, enumerateToolCatalog, ENUMERATORS, enumerateHarnessComponents, mergeEnumeratedComponents, toolNamesOf, clearExtractCache, extractHarness, extractHarnessWithContext, serializeExtractResult, runEnumerators, assignAgentIds, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, deterministicGraphItems, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, resolveExternalHarnessAnalystInvocation, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, readOnlyClaudeExtraArgs, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };