@moda-ai/cli 1.55.89 → 1.55.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{agent-svqnv0b8.js → agent-a6hz6vfr.js} +9 -9
  2. package/dist/{cli-p5grm12t.js → cli-0semcakc.js} +184 -5
  3. package/dist/{cli-5ms8rw8x.js → cli-13zdcv4w.js} +1 -1
  4. package/dist/{cli-z1t3sf7b.js → cli-1nd4339b.js} +1 -1
  5. package/dist/{cli-n1406hqg.js → cli-62e1vy8f.js} +3 -3
  6. package/dist/{cli-22yvg5kh.js → cli-6ga6kmdp.js} +2 -2
  7. package/dist/{cli-6hveza1a.js → cli-8v6v3ket.js} +7 -7
  8. package/dist/{cli-snswkrxd.js → cli-998n4kz9.js} +1 -1
  9. package/dist/{cli-9p2cdy58.js → cli-aqk56bkg.js} +320 -221
  10. package/dist/{cli-cqmntvnv.js → cli-c9v875xv.js} +5 -5
  11. package/dist/{cli-87xy1evx.js → cli-dxajrq9h.js} +1 -1
  12. package/dist/{cli-rrggdmf8.js → cli-qwnkv4jy.js} +1 -1
  13. package/dist/{cli-p1rrq2sq.js → cli-t29r8b6f.js} +1 -1
  14. package/dist/{cli-1smcq5pf.js → cli-t8vmcbe0.js} +4 -4
  15. package/dist/{cli-6hpfw3vf.js → cli-wm0p9kn2.js} +2 -2
  16. package/dist/cli.js +22 -21
  17. package/dist/{doctor-xcx7nc0v.js → doctor-72qrmfe7.js} +8 -8
  18. package/dist/{harness-github-actions-18v41647.js → harness-github-actions-9a48sd2r.js} +7 -7
  19. package/dist/{harness-a55w36em.js → harness-kr06zrhh.js} +7 -7
  20. package/dist/{index-g3zsqcjg.js → index-5q79y09b.js} +7 -7
  21. package/dist/{index-rdzd700n.js → index-t4fncjwa.js} +7 -7
  22. package/dist/{index-zg3g49f4.js → index-vx6eysne.js} +13 -13
  23. package/dist/{production-intelligence-f9sd68te.js → production-intelligence-1y884f69.js} +4 -4
  24. package/dist/{profile-commands-1fdvrs5y.js → profile-commands-tav5q639.js} +5 -5
  25. package/dist/{prompt-attribution-fyas5gnw.js → prompt-attribution-1cwnp7fb.js} +7 -7
  26. package/dist/prompt-source-mcp.js +7 -7
  27. package/dist/{prompt-sources-87qsxhdt.js → prompt-sources-x5z4p7n5.js} +2 -2
  28. package/dist/{prompts-qzbj61ca.js → prompts-hczy41m5.js} +6 -6
  29. package/dist/{provision-ya3vebee.js → provision-d0sxcka1.js} +6 -6
  30. package/dist/{registry-c64qr7ta.js → registry-4mhr7xsd.js} +4 -4
  31. package/dist/{skills-knpeqryb.js → skills-hf8fa7w7.js} +6 -6
  32. package/dist/{sync-t8psyfc9.js → sync-e2aydwa0.js} +9 -9
  33. package/package.json +1 -1
  34. package/skills/integration/index.json +2 -2
@@ -40,15 +40,15 @@ import {
40
40
  assertFlags,
41
41
  assertPositionals,
42
42
  requireTenant
43
- } from "./cli-22yvg5kh.js";
43
+ } from "./cli-6ga6kmdp.js";
44
44
  import {
45
45
  ApiError,
46
46
  callControlAPI
47
- } from "./cli-87xy1evx.js";
47
+ } from "./cli-dxajrq9h.js";
48
48
  import {
49
49
  createCommandContext,
50
50
  stringOption
51
- } from "./cli-5ms8rw8x.js";
51
+ } from "./cli-13zdcv4w.js";
52
52
  import {
53
53
  EXIT_DEGRADED,
54
54
  embeddedTenantIdFromApiKey,
@@ -59,7 +59,7 @@ import {
59
59
  resolveModaBaseUrl,
60
60
  resolveTenantId,
61
61
  shellArg
62
- } from "./cli-z1t3sf7b.js";
62
+ } from "./cli-1nd4339b.js";
63
63
  import {
64
64
  CliInputError,
65
65
  CliInputRequiredError
@@ -74,7 +74,7 @@ import {
74
74
  extractPythonSource,
75
75
  resolvePromptSource,
76
76
  validatePromptSource
77
- } from "./cli-p1rrq2sq.js";
77
+ } from "./cli-t29r8b6f.js";
78
78
  import {
79
79
  $isMap,
80
80
  $isNode,
@@ -91,17 +91,21 @@ import {
91
91
  DEFAULT_MAX_INVENTORY_TEXT_BYTES,
92
92
  MAX_RECORDED_SKIPS,
93
93
  MAX_SCANNED_FILE_BYTES,
94
+ MAX_STORED_ARTIFACT_BODY_BYTES,
94
95
  SKIPPED_DIRS,
96
+ captureFullArtifactBodies,
97
+ fitGraphForSync,
95
98
  isEvalLikePath,
96
99
  isSecretishPath,
97
100
  isSkippedDir,
98
101
  isSkippedPathPrefix,
99
102
  isTextFile,
100
103
  packSnapshot,
104
+ redactArtifactBody,
101
105
  redactDeep,
102
- redactSnapshotText,
103
- shouldInventoryFile
104
- } from "./cli-p5grm12t.js";
106
+ shouldInventoryFile,
107
+ storeShortenedArtifactBodies
108
+ } from "./cli-0semcakc.js";
105
109
  import {
106
110
  CALL_SINKS,
107
111
  CallIndex,
@@ -487,12 +491,12 @@ function buildPrograms(rootDir, options = {}) {
487
491
 
488
492
  // src/harness-extract/emit-models.ts
489
493
  var import_typescript7 = __toESM(require_typescript(), 1);
490
- import { createHash as createHash9 } from "node:crypto";
494
+ import { createHash as createHash10 } from "node:crypto";
491
495
  import { readFileSync as readFileSync16, readdirSync as readdirSync8, statSync as statSync5 } from "node:fs";
492
496
  import { join as join13, resolve as resolve13 } from "node:path";
493
497
 
494
498
  // src/harness-candidate-promotion.ts
495
- import { createHash as createHash8 } from "node:crypto";
499
+ import { createHash as createHash9 } from "node:crypto";
496
500
  import { readdirSync as readdirSync7, readFileSync as readFileSync15, statSync as statSync4 } from "node:fs";
497
501
  import { extname as extname8, posix as posix2, resolve as resolve12 } from "node:path";
498
502
 
@@ -704,22 +708,6 @@ function readSourcePathRelativeToEvidence(artifact, rootDir) {
704
708
  }
705
709
  return;
706
710
  }
707
- var PRIVATE_KEY_BLOCK = /-----BEGIN ([A-Z ]*)PRIVATE KEY-----(?:[\s\S]*?-----END \1PRIVATE KEY-----|(?:(?:\r\n|\r|\n)[ \t]*[A-Za-z0-9+/=]+[ \t]*(?=[\r\n]|$))*)/g;
708
- function maskPrivateKeyBlock(block) {
709
- return block.split(/(\r\n|\r|\n)/).map((part, index) => index === 0 ? "[REDACTED PRIVATE KEY]" : index % 2 === 1 ? part : "").join("");
710
- }
711
- var CREDENTIAL_FIELD = /(\b(?:[A-Za-z0-9]+[_-])*(?:api[_-]?key|apikey|secret(?:[_-]?key)?|password|passwd|access[_-]?token|auth[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\b["']?\s*[:=]\s*["']?)(?![<${]|process\.env|os\.environ)([^\s"'`,;]{8,})/gi;
712
- var CALL_OR_INDEX = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*[([]/;
713
- var DOTTED_REFERENCE = /^[A-Za-z_$][\w$]{0,39}(?:\.[A-Za-z_$][\w$]{0,39})+$/;
714
- function isCredentialReference(field, value) {
715
- if (/["']$/.test(field))
716
- return false;
717
- return CALL_OR_INDEX.test(value) || DOTTED_REFERENCE.test(value);
718
- }
719
- function redactArtifactBody(body) {
720
- const masked = body.replace(PRIVATE_KEY_BLOCK, maskPrivateKeyBlock).replace(CREDENTIAL_FIELD, (match, field, value) => isCredentialReference(field, value) ? match : `${field}[REDACTED]`);
721
- return redactSnapshotText(masked).text;
722
- }
723
711
  function hydratePromptAndToolBodies(graph, rootDir) {
724
712
  for (const artifact of graph.artifacts) {
725
713
  if (requiresArtifactBody(artifact.type) && !artifactHasBody(artifact)) {
@@ -1275,7 +1263,7 @@ function withTemplateOwners(templates, refs, agentsForCallSite, scopes = []) {
1275
1263
  }
1276
1264
 
1277
1265
  // src/harness.ts
1278
- import { createHash as createHash7 } from "node:crypto";
1266
+ import { createHash as createHash8 } from "node:crypto";
1279
1267
  import { execFileSync as execFileSync3, spawn } from "node:child_process";
1280
1268
  import { homedir, tmpdir as tmpdir2 } from "node:os";
1281
1269
  import { fileURLToPath } from "node:url";
@@ -1407,6 +1395,112 @@ function harnessAgentIdentities(value) {
1407
1395
  });
1408
1396
  }
1409
1397
 
1398
+ // src/harness-body-store.ts
1399
+ import { createHash as createHash2 } from "node:crypto";
1400
+
1401
+ // src/harness-sync-limits.ts
1402
+ var MAX_HARNESS_SYNC_GRAPH_BYTES = 2000000;
1403
+ var MAX_HARNESS_SYNC_REQUEST_BYTES = 2000000;
1404
+ function assertHarnessSyncRequestSize(body) {
1405
+ const requestBytes = Buffer.byteLength(JSON.stringify(body), "utf8");
1406
+ if (requestBytes > MAX_HARNESS_SYNC_REQUEST_BYTES) {
1407
+ throw new CliInputError(`Harness sync request is too large (${requestBytes.toLocaleString()} bytes; limit ${MAX_HARNESS_SYNC_REQUEST_BYTES.toLocaleString()}).`, "Run `moda harness analyze --path=<agent-dir>` to narrow the harness root.");
1408
+ }
1409
+ }
1410
+ function assertHarnessGraphSyncSize(graph) {
1411
+ if (!graph || typeof graph !== "object" || Array.isArray(graph)) {
1412
+ throw new CliInputError("Harness graph must be an object before sync.");
1413
+ }
1414
+ const graphBytes = Buffer.byteLength(JSON.stringify(graph), "utf8");
1415
+ if (graphBytes > MAX_HARNESS_SYNC_GRAPH_BYTES) {
1416
+ throw new CliInputError(`Harness graph is too large to sync (${graphBytes.toLocaleString()} bytes; limit ${MAX_HARNESS_SYNC_GRAPH_BYTES.toLocaleString()}).`, [
1417
+ "Run `moda harness analyze --path=<agent-dir>` to narrow the harness root.",
1418
+ "Reduce captured prompt/tool bodies if the graph grew too large.",
1419
+ "Split multiple agent roots into separate harness syncs per tenant."
1420
+ ].join(`
1421
+ `));
1422
+ }
1423
+ }
1424
+
1425
+ // src/harness-body-store.ts
1426
+ function sha256Hex(text) {
1427
+ return Promise.resolve(createHash2("sha256").update(text, "utf8").digest("hex"));
1428
+ }
1429
+ function graphBytes(graph) {
1430
+ return Buffer.byteLength(JSON.stringify(graph), "utf8");
1431
+ }
1432
+ async function prepareHarnessGraphForSync(graph, store, maxBytes = MAX_HARNESS_SYNC_GRAPH_BYTES, options = {}) {
1433
+ if (!graph || typeof graph !== "object" || graphBytes(graph) <= maxBytes) {
1434
+ return { graph, shortened: 0, uploaded: 0, storeFailed: false, storeFailedBodies: 0, unstorableBodies: 0 };
1435
+ }
1436
+ const copy = structuredClone(graph);
1437
+ const fullBodies = await captureFullArtifactBodies(copy, sha256Hex);
1438
+ const artifacts = Array.isArray(copy.artifacts) ? copy.artifacts.filter((artifact) => Boolean(artifact) && typeof artifact === "object") : [];
1439
+ const capturedBodies = new Map(artifacts.map((artifact) => [artifact, artifact.body]));
1440
+ const shortened = fitGraphForSync(copy, maxBytes, fullBodies);
1441
+ const unstorableBodies = artifacts.filter((artifact) => artifact.body !== capturedBodies.get(artifact) && typeof artifact.bodyHash !== "string").length;
1442
+ if (shortened === 0 || !store || options.requireStorable && unstorableBodies > 0) {
1443
+ return { graph: copy, shortened, uploaded: 0, storeFailed: false, storeFailedBodies: 0, unstorableBodies };
1444
+ }
1445
+ const stored = await storeShortenedArtifactBodies(copy, fullBodies, store, { keepHashesOnError: true });
1446
+ const storeFailed = stored.error !== undefined;
1447
+ return {
1448
+ graph: copy,
1449
+ shortened,
1450
+ uploaded: stored.uploaded,
1451
+ storeFailed,
1452
+ storeFailedBodies: storeFailed ? stored.referenced : 0,
1453
+ unstorableBodies
1454
+ };
1455
+ }
1456
+ function requestBytes(request) {
1457
+ return graphBytes({ ...request, dryRun: false });
1458
+ }
1459
+ function isRecord(value) {
1460
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1461
+ }
1462
+ function reportFieldsWithoutGraph(body) {
1463
+ const report = body.report;
1464
+ if (!isRecord(report) || !("graph" in report))
1465
+ return {};
1466
+ const { graph: _graph, ...reportWithoutGraph } = report;
1467
+ const fields = { report: reportWithoutGraph };
1468
+ if (body.reportHash === undefined)
1469
+ return fields;
1470
+ const reportHash = hashStableJson(reportWithoutGraph);
1471
+ fields.reportHash = reportHash;
1472
+ const approval = body.reportApproval;
1473
+ if (isRecord(approval) && approval.reportHash === body.reportHash) {
1474
+ fields.reportApproval = { ...approval, reportHash, approvedReportHash: body.reportHash };
1475
+ }
1476
+ return fields;
1477
+ }
1478
+ async function prepareHarnessSyncRequest(body, store, maxRequestBytes = MAX_HARNESS_SYNC_REQUEST_BYTES, maxGraphBytes = MAX_HARNESS_SYNC_GRAPH_BYTES, options = {}) {
1479
+ const { dryRun: _dryRun, ...rest } = body;
1480
+ if (requestBytes(rest) <= maxRequestBytes && graphBytes(rest.graph) <= maxGraphBytes) {
1481
+ return { request: rest, shortened: 0, uploaded: 0, storeFailed: false, storeFailedBodies: 0, unstorableBodies: 0 };
1482
+ }
1483
+ const request = { ...rest, ...reportFieldsWithoutGraph(rest) };
1484
+ const envelopeBytes = requestBytes({ ...request, graph: null });
1485
+ const budget = Math.min(maxGraphBytes, maxRequestBytes - envelopeBytes);
1486
+ const { graph, ...prepared } = await prepareHarnessGraphForSync(rest.graph, store, Math.max(0, budget), options);
1487
+ return { request: { ...request, graph }, ...prepared };
1488
+ }
1489
+ function controlApiArtifactBodyStore(call) {
1490
+ return {
1491
+ async missing(hashes) {
1492
+ const result = await call("/harnesses/bodies/missing", {
1493
+ method: "POST",
1494
+ body: JSON.stringify({ hashes })
1495
+ });
1496
+ return Array.isArray(result?.missing) ? result.missing.filter((hash) => typeof hash === "string") : [];
1497
+ },
1498
+ upload(bodies) {
1499
+ return call("/harnesses/bodies", { method: "POST", body: JSON.stringify({ bodies }) });
1500
+ }
1501
+ };
1502
+ }
1503
+
1410
1504
  // src/analyst-tui.ts
1411
1505
  class AnalystTui {
1412
1506
  state;
@@ -2102,13 +2196,13 @@ function entrypointOf(command, modelRouting) {
2102
2196
  return { entrypoint: { kind: "command", ...command ? { command } : {}, ...hasRouting ? { modelRouting } : {} } };
2103
2197
  }
2104
2198
  // ../../packages/harness-bundle/src/register/collect.ts
2105
- import { createHash as createHash5 } from "node:crypto";
2199
+ import { createHash as createHash6 } from "node:crypto";
2106
2200
  import { execFileSync } from "node:child_process";
2107
2201
  import { copyFileSync, createReadStream, existsSync as existsSync6, mkdirSync as mkdirSync3, realpathSync as realpathSync6, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
2108
2202
  import { dirname as dirname7, join as join8 } from "node:path";
2109
2203
 
2110
2204
  // ../../packages/harness-bundle/src/collect/collect.ts
2111
- import { createHash as createHash2 } from "node:crypto";
2205
+ import { createHash as createHash3 } from "node:crypto";
2112
2206
  import { closeSync, existsSync as existsSync3, lstatSync as lstatSync2, openSync, readdirSync as readdirSync2, readFileSync as readFileSync4, readlinkSync, readSync, realpathSync as realpathSync3 } from "node:fs";
2113
2207
  import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute4, join as join4, relative as relative3, resolve as resolve5, sep } from "node:path";
2114
2208
 
@@ -6247,7 +6341,7 @@ function detectEncoding(buf) {
6247
6341
  }
6248
6342
  }
6249
6343
  function sha256(buf) {
6250
- return createHash2("sha256").update(buf).digest("hex");
6344
+ return createHash3("sha256").update(buf).digest("hex");
6251
6345
  }
6252
6346
  var DROP_FIRST = ["data", "binary", "asset", "generated"];
6253
6347
  var KEEP = [
@@ -6316,7 +6410,7 @@ function rangeCovered(ranges, start, end) {
6316
6410
  }
6317
6411
 
6318
6412
  // ../../packages/harness-bundle/src/collect/write.ts
6319
- import { createHash as createHash3, randomUUID } from "node:crypto";
6413
+ import { createHash as createHash4, randomUUID } from "node:crypto";
6320
6414
  import { createWriteStream, existsSync as existsSync4, lstatSync as lstatSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync4, renameSync, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
6321
6415
  import { dirname as dirname5, isAbsolute as isAbsolute5, join as join5, relative as relative4, resolve as resolve6, sep as sep2 } from "node:path";
6322
6416
  import { Readable, Transform } from "node:stream";
@@ -6515,7 +6609,7 @@ function* tarChunks(files) {
6515
6609
  }
6516
6610
  async function writeTarGz(files, path) {
6517
6611
  mkdirSync2(dirname5(path), { recursive: true });
6518
- const tarHash = createHash3("sha256");
6612
+ const tarHash = createHash4("sha256");
6519
6613
  await pipeline(Readable.from(tarChunks(files)), new Transform({
6520
6614
  transform(chunk, _encoding, callback) {
6521
6615
  tarHash.update(chunk);
@@ -6743,7 +6837,7 @@ function parseJsonLoose(text) {
6743
6837
  return;
6744
6838
  }
6745
6839
  }
6746
- function isRecord(value) {
6840
+ function isRecord2(value) {
6747
6841
  return typeof value === "object" && value !== null && !Array.isArray(value);
6748
6842
  }
6749
6843
  function asString(value) {
@@ -7941,7 +8035,7 @@ function readManifest(dir) {
7941
8035
  return;
7942
8036
  try {
7943
8037
  const parsed = JSON.parse(readFileSync6(path, "utf8"));
7944
- if (isRecord(parsed) && parsed.schema === HARNESS_BUNDLE_SCHEMA && Array.isArray(parsed.files)) {
8038
+ if (isRecord2(parsed) && parsed.schema === HARNESS_BUNDLE_SCHEMA && Array.isArray(parsed.files)) {
7945
8039
  return parsed;
7946
8040
  }
7947
8041
  } catch {
@@ -7977,7 +8071,7 @@ function makeFile(path, text, categories) {
7977
8071
  };
7978
8072
  }
7979
8073
  function isValidEntry(value) {
7980
- return isRecord(value) && typeof value.path === "string" && typeof value.bytes === "number" && Array.isArray(value.categories) && value.categories.every((c) => typeof c === "string") && (value.encoding === "text" || value.encoding === "binary");
8074
+ return isRecord2(value) && typeof value.path === "string" && typeof value.bytes === "number" && Array.isArray(value.categories) && value.categories.every((c) => typeof c === "string") && (value.encoding === "text" || value.encoding === "binary");
7981
8075
  }
7982
8076
  function staysInside(root, abs) {
7983
8077
  try {
@@ -8013,7 +8107,7 @@ function loadFiles(dir, opts = {}) {
8013
8107
  if (isValidEntry(raw))
8014
8108
  entries.push(raw);
8015
8109
  else
8016
- skipped.push({ path: isRecord(raw) && typeof raw.path === "string" ? raw.path : "(unnamed)", reason: "invalid_entry" });
8110
+ skipped.push({ path: isRecord2(raw) && typeof raw.path === "string" ? raw.path : "(unnamed)", reason: "invalid_entry" });
8017
8111
  }
8018
8112
  const contentRoot = contentRootFor(dir, entries);
8019
8113
  entries.sort((a, b) => cmp(a.path, b.path));
@@ -8099,7 +8193,7 @@ function loadFiles(dir, opts = {}) {
8099
8193
  return { files, truncated, skipped };
8100
8194
  }
8101
8195
  function isValidEnv(value) {
8102
- return isRecord(value) && typeof value.name === "string" && Array.isArray(value.sources) && typeof value.classification === "string" && typeof value.hasExampleValue === "boolean";
8196
+ return isRecord2(value) && typeof value.name === "string" && Array.isArray(value.sources) && typeof value.classification === "string" && typeof value.hasExampleValue === "boolean";
8103
8197
  }
8104
8198
 
8105
8199
  // ../../packages/harness-bundle/src/detect/frameworks.ts
@@ -10254,7 +10348,7 @@ function parsePackageJsons(files) {
10254
10348
  continue;
10255
10349
  try {
10256
10350
  const json = JSON.parse(f.text);
10257
- if (isRecord(json))
10351
+ if (isRecord2(json))
10258
10352
  out.push({ path: f.path, root: dirname6(f.path), json });
10259
10353
  } catch {}
10260
10354
  }
@@ -10267,7 +10361,7 @@ function fromPackageJson(f, out) {
10267
10361
  } catch {
10268
10362
  return;
10269
10363
  }
10270
- if (!isRecord(json))
10364
+ if (!isRecord2(json))
10271
10365
  return;
10272
10366
  for (const [field, dev] of [
10273
10367
  ["dependencies", false],
@@ -10276,7 +10370,7 @@ function fromPackageJson(f, out) {
10276
10370
  ["devDependencies", true]
10277
10371
  ]) {
10278
10372
  const deps = json[field];
10279
- if (!isRecord(deps))
10373
+ if (!isRecord2(deps))
10280
10374
  continue;
10281
10375
  for (const name of Object.keys(deps).sort()) {
10282
10376
  out.push({ eco: "npm", name, path: f.path, line: lineOfToken(f.text, `"${name}"`), dev });
@@ -10307,49 +10401,49 @@ function fromPyproject(f, out) {
10307
10401
  if (name && name !== "python")
10308
10402
  out.push({ eco: "pypi", name, path: f.path, line: lineOfToken(f.text, name), dev });
10309
10403
  };
10310
- const project = isRecord(doc.project) ? doc.project : {};
10404
+ const project = isRecord2(doc.project) ? doc.project : {};
10311
10405
  for (const req of asArray(project.dependencies))
10312
10406
  if (typeof req === "string")
10313
10407
  add(req, false);
10314
- const optional = isRecord(project["optional-dependencies"]) ? project["optional-dependencies"] : {};
10408
+ const optional = isRecord2(project["optional-dependencies"]) ? project["optional-dependencies"] : {};
10315
10409
  for (const [group, reqs] of Object.entries(optional)) {
10316
10410
  for (const req of asArray(reqs))
10317
10411
  if (typeof req === "string")
10318
10412
  add(req, /dev|test|lint|doc/i.test(group));
10319
10413
  }
10320
- const groups = isRecord(doc["dependency-groups"]) ? doc["dependency-groups"] : {};
10414
+ const groups = isRecord2(doc["dependency-groups"]) ? doc["dependency-groups"] : {};
10321
10415
  for (const reqs of Object.values(groups))
10322
10416
  for (const req of asArray(reqs))
10323
10417
  if (typeof req === "string")
10324
10418
  add(req, true);
10325
- const tool = isRecord(doc.tool) ? doc.tool : {};
10326
- const poetry = isRecord(tool.poetry) ? tool.poetry : {};
10327
- if (isRecord(poetry.dependencies))
10419
+ const tool = isRecord2(doc.tool) ? doc.tool : {};
10420
+ const poetry = isRecord2(tool.poetry) ? tool.poetry : {};
10421
+ if (isRecord2(poetry.dependencies))
10328
10422
  for (const name of Object.keys(poetry.dependencies))
10329
10423
  add(name, false);
10330
- if (isRecord(poetry["dev-dependencies"]))
10424
+ if (isRecord2(poetry["dev-dependencies"]))
10331
10425
  for (const name of Object.keys(poetry["dev-dependencies"]))
10332
10426
  add(name, true);
10333
- if (isRecord(poetry.group)) {
10427
+ if (isRecord2(poetry.group)) {
10334
10428
  for (const [group, body] of Object.entries(poetry.group)) {
10335
- if (isRecord(body) && isRecord(body.dependencies)) {
10429
+ if (isRecord2(body) && isRecord2(body.dependencies)) {
10336
10430
  for (const name of Object.keys(body.dependencies))
10337
10431
  add(name, /dev|test|lint|doc/i.test(group));
10338
10432
  }
10339
10433
  }
10340
10434
  }
10341
- const uv = isRecord(tool.uv) ? tool.uv : {};
10435
+ const uv = isRecord2(tool.uv) ? tool.uv : {};
10342
10436
  for (const req of asArray(uv["dev-dependencies"]))
10343
10437
  if (typeof req === "string")
10344
10438
  add(req, true);
10345
- const hatch = isRecord(tool.hatch) && isRecord(tool.hatch.metadata) && isRecord(tool.hatch.metadata.hooks) ? tool.hatch.metadata.hooks : {};
10439
+ const hatch = isRecord2(tool.hatch) && isRecord2(tool.hatch.metadata) && isRecord2(tool.hatch.metadata.hooks) ? tool.hatch.metadata.hooks : {};
10346
10440
  for (const hook of Object.values(hatch)) {
10347
- if (!isRecord(hook))
10441
+ if (!isRecord2(hook))
10348
10442
  continue;
10349
10443
  for (const req of asArray(hook.dependencies))
10350
10444
  if (typeof req === "string")
10351
10445
  add(req, false);
10352
- const extra = isRecord(hook["optional-dependencies"]) ? hook["optional-dependencies"] : {};
10446
+ const extra = isRecord2(hook["optional-dependencies"]) ? hook["optional-dependencies"] : {};
10353
10447
  for (const [group, reqs] of Object.entries(extra))
10354
10448
  for (const req of asArray(reqs))
10355
10449
  if (typeof req === "string")
@@ -10368,7 +10462,7 @@ function fromPipfile(f, out) {
10368
10462
  ["dev-packages", true]
10369
10463
  ]) {
10370
10464
  const pkgs = doc[section];
10371
- if (isRecord(pkgs)) {
10465
+ if (isRecord2(pkgs)) {
10372
10466
  for (const name of Object.keys(pkgs)) {
10373
10467
  out.push({ eco: "pypi", name: name.toLowerCase(), path: f.path, line: lineOfToken(f.text, name), dev });
10374
10468
  }
@@ -10550,7 +10644,7 @@ var SLS_EVENT_TRIGGERS = {
10550
10644
  alexaSkill: "event"
10551
10645
  };
10552
10646
  function envFromVariables(ctx, vars, file, sourceLabel) {
10553
- if (!isRecord(vars))
10647
+ if (!isRecord2(vars))
10554
10648
  return;
10555
10649
  for (const name of Object.keys(vars).sort()) {
10556
10650
  const value = vars[name];
@@ -10561,10 +10655,10 @@ function envFromVariables(ctx, vars, file, sourceLabel) {
10561
10655
  function cfnResources(ctx, resources, file, runtime) {
10562
10656
  for (const logicalId of Object.keys(resources).sort()) {
10563
10657
  const res = resources[logicalId];
10564
- if (!isRecord(res))
10658
+ if (!isRecord2(res))
10565
10659
  continue;
10566
10660
  const type = asString(res.Type) ?? "";
10567
- const props = isRecord(res.Properties) ? res.Properties : {};
10661
+ const props = isRecord2(res.Properties) ? res.Properties : {};
10568
10662
  let spec = CFN_RESOURCES[type];
10569
10663
  if (!spec && (type === "AWS::RDS::DBInstance" || type === "AWS::RDS::DBCluster")) {
10570
10664
  spec = { capability: "database", provider: rdsEngineProvider(asString(props.Engine)), cls: "engine" };
@@ -10580,61 +10674,61 @@ function handlerPath(codeUri, handler, root) {
10580
10674
  return codeUri ? `${joinPath(root, codeUri)}/${handler}` : joinPath(root, handler);
10581
10675
  }
10582
10676
  function detectSam(ctx, file, doc) {
10583
- const resources = isRecord(doc.Resources) ? doc.Resources : undefined;
10677
+ const resources = isRecord2(doc.Resources) ? doc.Resources : undefined;
10584
10678
  if (!resources)
10585
10679
  return;
10586
10680
  const root = dirname6(file.path);
10587
- const globals = isRecord(doc.Globals) && isRecord(doc.Globals.Function) ? doc.Globals.Function : {};
10681
+ const globals = isRecord2(doc.Globals) && isRecord2(doc.Globals.Function) ? doc.Globals.Function : {};
10588
10682
  const runtime = newRuntime("aws_lambda", root, [file.path], [ev(file, /AWS::Serverless|AWSTemplateFormatVersion/)], 0.95);
10589
10683
  const g = languageFromRuntime(asString(globals.Runtime));
10590
- envFromVariables(ctx, isRecord(globals.Environment) ? globals.Environment.Variables : undefined, file, "Globals");
10684
+ envFromVariables(ctx, isRecord2(globals.Environment) ? globals.Environment.Variables : undefined, file, "Globals");
10591
10685
  for (const logicalId of Object.keys(resources).sort()) {
10592
10686
  const res = resources[logicalId];
10593
- if (!isRecord(res))
10687
+ if (!isRecord2(res))
10594
10688
  continue;
10595
10689
  const type = asString(res.Type);
10596
10690
  if (type !== "AWS::Serverless::Function" && type !== "AWS::Lambda::Function")
10597
10691
  continue;
10598
- const props = isRecord(res.Properties) ? res.Properties : {};
10692
+ const props = isRecord2(res.Properties) ? res.Properties : {};
10599
10693
  const lang = languageFromRuntime(asString(props.Runtime) ?? asString(globals.Runtime));
10600
10694
  runtime.language ??= lang.language ?? g.language;
10601
10695
  runtime.runtimeVersion ??= lang.version ?? g.version;
10602
10696
  const handler = asString(props.Handler) ?? asString(globals.Handler);
10603
- const codeUri = asString(props.CodeUri) ?? asString(globals.CodeUri) ?? (isRecord(props.Code) ? undefined : asString(props.Code));
10604
- const events = isRecord(props.Events) ? props.Events : {};
10697
+ const codeUri = asString(props.CodeUri) ?? asString(globals.CodeUri) ?? (isRecord2(props.Code) ? undefined : asString(props.Code));
10698
+ const events = isRecord2(props.Events) ? props.Events : {};
10605
10699
  const triggers = new Set;
10606
10700
  for (const evt of Object.values(events)) {
10607
- if (isRecord(evt))
10701
+ if (isRecord2(evt))
10608
10702
  triggers.add(SAM_EVENT_TRIGGERS[asString(evt.Type) ?? ""] ?? "event");
10609
10703
  }
10610
- if (isRecord(props.FunctionUrlConfig))
10704
+ if (isRecord2(props.FunctionUrlConfig))
10611
10705
  triggers.add("http");
10612
10706
  const trigger = triggers.has("http") ? "http" : [...triggers][0] ?? "event";
10613
10707
  const entry = { name: logicalId, trigger };
10614
10708
  if (handler)
10615
10709
  entry.handler = handlerPath(codeUri, handler, root);
10616
10710
  else if (asString(props.PackageType) === "Image") {
10617
- const meta = isRecord(res.Metadata) ? res.Metadata : {};
10711
+ const meta = isRecord2(res.Metadata) ? res.Metadata : {};
10618
10712
  const ctxDir = asString(meta.DockerContext);
10619
10713
  entry.handler = ctxDir ? `${joinPath(root, ctxDir)}/${asString(meta.Dockerfile) ?? "Dockerfile"}` : undefined;
10620
10714
  }
10621
10715
  runtime.entrypoints.push(entry);
10622
- envFromVariables(ctx, isRecord(props.Environment) ? props.Environment.Variables : undefined, file, logicalId);
10716
+ envFromVariables(ctx, isRecord2(props.Environment) ? props.Environment.Variables : undefined, file, logicalId);
10623
10717
  }
10624
10718
  cfnResources(ctx, resources, file, runtime);
10625
10719
  const ids = Object.keys(resources);
10626
10720
  const direct = (text, self) => ids.filter((id) => id !== self && new RegExp(`\\b${escapeRe(id)}\\b`).test(text));
10627
- const globalsText = JSON.stringify(isRecord(doc.Globals) && isRecord(doc.Globals.Function) ? doc.Globals.Function : {});
10721
+ const globalsText = JSON.stringify(isRecord2(doc.Globals) && isRecord2(doc.Globals.Function) ? doc.Globals.Function : {});
10628
10722
  const refs = new Map;
10629
10723
  for (const [fnId, res] of Object.entries(resources)) {
10630
- if (!isRecord(res) || !/^AWS::(?:Serverless|Lambda)::Function$/.test(asString(res.Type) ?? ""))
10724
+ if (!isRecord2(res) || !/^AWS::(?:Serverless|Lambda)::Function$/.test(asString(res.Type) ?? ""))
10631
10725
  continue;
10632
10726
  const seen = new Set(direct(`${JSON.stringify(res.Properties ?? {})} ${globalsText}`, fnId));
10633
10727
  const queue = [...seen];
10634
10728
  while (queue.length > 0) {
10635
10729
  const id = queue.shift();
10636
10730
  const other = resources[id];
10637
- if (!isRecord(other) || /^AWS::(?:Serverless|Lambda)::Function$/.test(asString(other.Type) ?? ""))
10731
+ if (!isRecord2(other) || /^AWS::(?:Serverless|Lambda)::Function$/.test(asString(other.Type) ?? ""))
10638
10732
  continue;
10639
10733
  for (const next of direct(JSON.stringify(other.Properties ?? {}), id)) {
10640
10734
  if (next !== fnId && !seen.has(next)) {
@@ -10651,7 +10745,7 @@ function detectSam(ctx, file, doc) {
10651
10745
  return runtime;
10652
10746
  }
10653
10747
  function detectServerless(ctx, file, doc) {
10654
- const provider = isRecord(doc.provider) ? doc.provider : {};
10748
+ const provider = isRecord2(doc.provider) ? doc.provider : {};
10655
10749
  const providerName = asString(provider.name) ?? "aws";
10656
10750
  const root = dirname6(file.path);
10657
10751
  const kind = providerName === "google" ? "gcp_cloud_functions" : providerName === "azure" ? "azure_functions" : "aws_lambda";
@@ -10660,14 +10754,14 @@ function detectServerless(ctx, file, doc) {
10660
10754
  runtime.language = lang.language;
10661
10755
  runtime.runtimeVersion = lang.version;
10662
10756
  envFromVariables(ctx, provider.environment, file, "provider.environment");
10663
- const functions = isRecord(doc.functions) ? doc.functions : {};
10757
+ const functions = isRecord2(doc.functions) ? doc.functions : {};
10664
10758
  for (const name of Object.keys(functions).sort()) {
10665
10759
  const fn = functions[name];
10666
- if (!isRecord(fn))
10760
+ if (!isRecord2(fn))
10667
10761
  continue;
10668
10762
  const triggers = new Set;
10669
10763
  for (const evt of asArray(fn.events)) {
10670
- if (isRecord(evt))
10764
+ if (isRecord2(evt))
10671
10765
  for (const key of Object.keys(evt))
10672
10766
  triggers.add(SLS_EVENT_TRIGGERS[key] ?? "event");
10673
10767
  }
@@ -10692,7 +10786,7 @@ function detectServerless(ctx, file, doc) {
10692
10786
  const line = at(m.index);
10693
10787
  ctx.env.push({ name: m[1], source: `${file.path}:${line}`, evidence: { path: file.path, line, excerpt: excerpt(splitLines(file.text)[line - 1]), detector: DETECTOR5 } });
10694
10788
  }
10695
- const resources = isRecord(doc.resources) && isRecord(doc.resources.Resources) ? doc.resources.Resources : undefined;
10789
+ const resources = isRecord2(doc.resources) && isRecord2(doc.resources.Resources) ? doc.resources.Resources : undefined;
10696
10790
  if (resources)
10697
10791
  cfnResources(ctx, resources, file, runtime);
10698
10792
  return runtime;
@@ -10786,7 +10880,7 @@ function detectAws(input) {
10786
10880
  const name = basename3(file.path);
10787
10881
  if (/^serverless\.ya?ml$/.test(name)) {
10788
10882
  const doc = loadYaml(file.text);
10789
- if (!isRecord(doc)) {
10883
+ if (!isRecord2(doc)) {
10790
10884
  ctx.gaps.push({ kind: "unparseable_config", message: `Could not parse ${file.path}`, evidence: [{ path: file.path, detector: DETECTOR5 }] });
10791
10885
  continue;
10792
10886
  }
@@ -10795,7 +10889,7 @@ function detectAws(input) {
10795
10889
  out.push(rt);
10796
10890
  } else if (isCfnTemplate(file)) {
10797
10891
  const doc = file.path.endsWith(".json") ? safeJson(file.text) : loadYaml(file.text);
10798
- if (!isRecord(doc)) {
10892
+ if (!isRecord2(doc)) {
10799
10893
  ctx.gaps.push({ kind: "unparseable_config", message: `Could not parse ${file.path}`, evidence: [{ path: file.path, detector: DETECTOR5 }] });
10800
10894
  continue;
10801
10895
  }
@@ -10830,7 +10924,7 @@ function parseWrangler(file) {
10830
10924
  }
10831
10925
  }
10832
10926
  const parsed = parseJsonLoose(file.text);
10833
- return isRecord(parsed) ? parsed : undefined;
10927
+ return isRecord2(parsed) ? parsed : undefined;
10834
10928
  }
10835
10929
  function ev2(file, token) {
10836
10930
  const re = typeof token === "string" ? new RegExp(escapeRe(token)) : token;
@@ -10838,10 +10932,10 @@ function ev2(file, token) {
10838
10932
  }
10839
10933
  function sections(config) {
10840
10934
  const out = [config];
10841
- if (isRecord(config.env))
10935
+ if (isRecord2(config.env))
10842
10936
  for (const key of Object.keys(config.env).sort()) {
10843
10937
  const env = config.env[key];
10844
- if (isRecord(env))
10938
+ if (isRecord2(env))
10845
10939
  out.push(env);
10846
10940
  }
10847
10941
  return out;
@@ -10877,7 +10971,7 @@ function detectCloudflare(input) {
10877
10971
  const hasFetch = !mainFile || /\bfetch\s*[(:]|\bexport\s+default\s+(?:app|router|server)\b|routeAgentRequest|new\s+Hono\b|\bon_fetch\b|WorkerEntrypoint/.test(text);
10878
10972
  if (hasFetch)
10879
10973
  runtime.entrypoints.push({ name: "fetch", handler: `${mainPath}#default.fetch`, trigger: "http" });
10880
- if (mainFile && /(?:^|[\s{,])(?:async\s+)?scheduled\s*\(\s*\w|\bscheduled\s*:\s*(?:async\s*)?(?:\(|function)|\bon_scheduled\b/m.test(text) && asArray(isRecord(config.triggers) ? config.triggers.crons : undefined).length === 0) {
10974
+ if (mainFile && /(?:^|[\s{,])(?:async\s+)?scheduled\s*\(\s*\w|\bscheduled\s*:\s*(?:async\s*)?(?:\(|function)|\bon_scheduled\b/m.test(text) && asArray(isRecord2(config.triggers) ? config.triggers.crons : undefined).length === 0) {
10881
10975
  runtime.entrypoints.push({ name: "scheduled", handler: `${mainPath}#default.scheduled`, trigger: "cron" });
10882
10976
  }
10883
10977
  if (!mainFile) {
@@ -10886,7 +10980,7 @@ function detectCloudflare(input) {
10886
10980
  } else if (pagesOut) {
10887
10981
  runtime.entrypoints.push({ name: "pages", handler: joinPath(root, "functions"), trigger: "http" });
10888
10982
  }
10889
- const triggers = isRecord(config.triggers) ? config.triggers : {};
10983
+ const triggers = isRecord2(config.triggers) ? config.triggers : {};
10890
10984
  for (const cron of asArray(triggers.crons)) {
10891
10985
  if (typeof cron === "string")
10892
10986
  runtime.entrypoints.push({ name: `cron ${cron}`, handler: main ? `${joinPath(root, main)}#default.scheduled` : undefined, trigger: "cron" });
@@ -10903,16 +10997,16 @@ function detectCloudflare(input) {
10903
10997
  runtime.bindings.push(resource ? { name, type: normalized, resource } : { name, type: normalized });
10904
10998
  return true;
10905
10999
  };
10906
- const produced = new Set(sections(config).flatMap((section) => asArray(isRecord(section.queues) ? section.queues.producers : undefined).map((p2) => isRecord(p2) ? asString(p2.queue) : undefined)));
11000
+ const produced = new Set(sections(config).flatMap((section) => asArray(isRecord2(section.queues) ? section.queues.producers : undefined).map((p2) => isRecord2(p2) ? asString(p2.queue) : undefined)));
10907
11001
  for (const section of sections(config)) {
10908
11002
  for (const [field, spec] of Object.entries(WORKERS_BINDINGS)) {
10909
11003
  const raw = section[field];
10910
11004
  if (raw === undefined)
10911
11005
  continue;
10912
11006
  if (field === "queues") {
10913
- const queues = isRecord(raw) ? raw : {};
11007
+ const queues = isRecord2(raw) ? raw : {};
10914
11008
  for (const producer of asArray(queues.producers)) {
10915
- if (!isRecord(producer))
11009
+ if (!isRecord2(producer))
10916
11010
  continue;
10917
11011
  const name = asString(producer.binding) ?? "QUEUE";
10918
11012
  const resource = asString(producer.queue);
@@ -10921,7 +11015,7 @@ function detectCloudflare(input) {
10921
11015
  }
10922
11016
  }
10923
11017
  for (const consumer of asArray(queues.consumers)) {
10924
- if (!isRecord(consumer))
11018
+ if (!isRecord2(consumer))
10925
11019
  continue;
10926
11020
  const queue = asString(consumer.queue) ?? "queue";
10927
11021
  if (addBinding(queue, "QueueConsumer", queue)) {
@@ -10934,7 +11028,7 @@ function detectCloudflare(input) {
10934
11028
  }
10935
11029
  const items = Array.isArray(raw) ? raw : [raw];
10936
11030
  for (const item of items) {
10937
- if (!isRecord(item))
11031
+ if (!isRecord2(item))
10938
11032
  continue;
10939
11033
  const name = asString(item.binding) ?? asString(item.name) ?? spec.type.toUpperCase();
10940
11034
  const resource = asString(item.database_name) ?? asString(item.bucket_name) ?? asString(item.index_name) ?? asString(item.service) ?? asString(item.dataset) ?? asString(item.namespace) ?? asString(item.id);
@@ -10964,9 +11058,9 @@ function detectCloudflare(input) {
10964
11058
  }
10965
11059
  }
10966
11060
  }
10967
- const durable = isRecord(section.durable_objects) ? section.durable_objects : {};
11061
+ const durable = isRecord2(section.durable_objects) ? section.durable_objects : {};
10968
11062
  for (const item of asArray(durable.bindings)) {
10969
- if (!isRecord(item))
11063
+ if (!isRecord2(item))
10970
11064
  continue;
10971
11065
  const name = asString(item.name) ?? "DO";
10972
11066
  const className2 = asString(item.class_name);
@@ -10981,19 +11075,19 @@ function detectCloudflare(input) {
10981
11075
  }
10982
11076
  }
10983
11077
  for (const item of asArray(section.workflows)) {
10984
- if (isRecord(item))
11078
+ if (isRecord2(item))
10985
11079
  addBinding(asString(item.binding) ?? "WORKFLOW", "Workflow", asString(item.class_name));
10986
11080
  }
10987
11081
  for (const item of asArray(section.containers)) {
10988
- if (isRecord(item))
11082
+ if (isRecord2(item))
10989
11083
  addBinding(asString(item.class_name) ?? "CONTAINER", "Container", asString(item.image));
10990
11084
  }
10991
- if (isRecord(section.assets)) {
11085
+ if (isRecord2(section.assets)) {
10992
11086
  const binding = asString(section.assets.binding);
10993
11087
  if (binding)
10994
11088
  addBinding(binding, "Assets", asString(section.assets.directory));
10995
11089
  }
10996
- if (isRecord(section.vars)) {
11090
+ if (isRecord2(section.vars)) {
10997
11091
  for (const key of Object.keys(section.vars).sort()) {
10998
11092
  const value = section.vars[key];
10999
11093
  ctx.env.push({
@@ -11005,7 +11099,7 @@ function detectCloudflare(input) {
11005
11099
  }
11006
11100
  }
11007
11101
  const secrets = section.secrets;
11008
- const required = isRecord(secrets) ? asArray(secrets.required) : asArray(secrets);
11102
+ const required = isRecord2(secrets) ? asArray(secrets.required) : asArray(secrets);
11009
11103
  for (const s of required)
11010
11104
  if (typeof s === "string")
11011
11105
  ctx.env.push({ name: s, source: `${file.path} secrets` });
@@ -11196,7 +11290,7 @@ function detachDockerfile(byRoot, contributions, c) {
11196
11290
  }
11197
11291
  function composeServices(ctx, file, byRoot, contributions, relocated) {
11198
11292
  const doc = loadYaml(file.text);
11199
- if (!isRecord(doc) || !isRecord(doc.services))
11293
+ if (!isRecord2(doc) || !isRecord2(doc.services))
11200
11294
  return;
11201
11295
  const base = dirname6(file.path);
11202
11296
  const at = lineIndex(file.text);
@@ -11207,7 +11301,7 @@ function composeServices(ctx, file, byRoot, contributions, relocated) {
11207
11301
  };
11208
11302
  for (const name of Object.keys(doc.services).sort()) {
11209
11303
  const svc = doc.services[name];
11210
- if (!isRecord(svc))
11304
+ if (!isRecord2(svc))
11211
11305
  continue;
11212
11306
  const line = lineOfService(name);
11213
11307
  const evidence = { path: file.path, line, excerpt: line ? excerpt(lines[line - 1]) : undefined, detector: `${DETECTOR7}.compose` };
@@ -11216,11 +11310,11 @@ function composeServices(ctx, file, byRoot, contributions, relocated) {
11216
11310
  const ports = asArray(svc.ports);
11217
11311
  const svcEntrypoint = composeArgs(svc.entrypoint);
11218
11312
  const svcCommand = composeArgs(svc.command);
11219
- let serviceRoot = build !== undefined ? joinPath(base, typeof build === "string" ? build : isRecord(build) ? asString(build.context) ?? "." : ".") : undefined;
11313
+ let serviceRoot = build !== undefined ? joinPath(base, typeof build === "string" ? build : isRecord2(build) ? asString(build.context) ?? "." : ".") : undefined;
11220
11314
  if (build !== undefined) {
11221
- const context = typeof build === "string" ? build : isRecord(build) ? asString(build.context) ?? "." : ".";
11315
+ const context = typeof build === "string" ? build : isRecord2(build) ? asString(build.context) ?? "." : ".";
11222
11316
  const contextRoot = joinPath(base, context);
11223
- const dockerfile = joinPath(contextRoot, (isRecord(build) ? asString(build.dockerfile) : undefined) ?? "Dockerfile");
11317
+ const dockerfile = joinPath(contextRoot, (isRecord2(build) ? asString(build.dockerfile) : undefined) ?? "Dockerfile");
11224
11318
  const dfDir = dirname6(dockerfile);
11225
11319
  const projectDir = dfDir !== contextRoot && isUnder2(dfDir, contextRoot) && ctx.files.some((f) => dirname6(f.path) === dfDir && PROJECT_MANIFEST.test(basename3(f.path)));
11226
11320
  const root = projectDir ? dfDir : contextRoot;
@@ -11240,7 +11334,7 @@ function composeServices(ctx, file, byRoot, contributions, relocated) {
11240
11334
  else if (contribution.entry)
11241
11335
  runtime.entrypoints = runtime.entrypoints.filter((e) => e !== contribution.entry);
11242
11336
  }
11243
- const target = isRecord(build) ? asString(build.target)?.toLowerCase() : undefined;
11337
+ const target = isRecord2(build) ? asString(build.target)?.toLowerCase() : undefined;
11244
11338
  const targetStage = target ? contribution?.df.stages[target] : undefined;
11245
11339
  if (targetStage) {
11246
11340
  const lang = languageFromImage(targetStage.base);
@@ -11277,7 +11371,7 @@ function composeServices(ctx, file, byRoot, contributions, relocated) {
11277
11371
  const [k, ...v] = item.split("=");
11278
11372
  pairs.push([k, v.length > 0 ? v.join("=") : undefined]);
11279
11373
  }
11280
- } else if (isRecord(env)) {
11374
+ } else if (isRecord2(env)) {
11281
11375
  for (const [k, v] of Object.entries(env))
11282
11376
  pairs.push([k, v === null || v === undefined ? undefined : String(v)]);
11283
11377
  }
@@ -11396,16 +11490,16 @@ function knativeServices(ctx, file, runtime) {
11396
11490
  }
11397
11491
  for (const doc of Array.isArray(docs) ? docs : [docs]) {
11398
11492
  const json = doc.toJS?.();
11399
- if (!isRecord(json) || json.kind !== "Service")
11493
+ if (!isRecord2(json) || json.kind !== "Service")
11400
11494
  continue;
11401
- const spec = isRecord(json.spec) && isRecord(json.spec.template) && isRecord(json.spec.template.spec) ? json.spec.template.spec : {};
11495
+ const spec = isRecord2(json.spec) && isRecord2(json.spec.template) && isRecord2(json.spec.template.spec) ? json.spec.template.spec : {};
11402
11496
  for (const container of asArray(spec.containers)) {
11403
- if (!isRecord(container))
11497
+ if (!isRecord2(container))
11404
11498
  continue;
11405
11499
  const strings = (v) => asArray(v).filter((c) => typeof c === "string");
11406
11500
  const cmd = strings(container.command);
11407
11501
  const args = strings(container.args);
11408
- const name = isRecord(json.metadata) ? asString(json.metadata.name) ?? "service" : "service";
11502
+ const name = isRecord2(json.metadata) ? asString(json.metadata.name) ?? "service" : "service";
11409
11503
  const entry = { name, trigger: "http" };
11410
11504
  const image = asString(container.image);
11411
11505
  if (image)
@@ -11421,7 +11515,7 @@ function knativeServices(ctx, file, runtime) {
11421
11515
  }
11422
11516
  runtime.entrypoints.push(entry);
11423
11517
  for (const env of asArray(container.env)) {
11424
- if (isRecord(env) && typeof env.name === "string") {
11518
+ if (isRecord2(env) && typeof env.name === "string") {
11425
11519
  ctx.env.push({ name: env.name, source: `${file.path} env`, value: asString(env.value), evidence: { path: file.path, line: findLine(file.text, new RegExp(`name:\\s*${escapeRe(env.name)}\\b`)), detector: DETECTOR8 } });
11426
11520
  }
11427
11521
  }
@@ -11498,18 +11592,18 @@ function detectGcp(input, roots) {
11498
11592
  if (basename3(file.path) !== "firebase.json")
11499
11593
  continue;
11500
11594
  const json = parseJsonLoose(file.text);
11501
- if (!isRecord(json) || json.functions === undefined)
11595
+ if (!isRecord2(json) || json.functions === undefined)
11502
11596
  continue;
11503
11597
  const entries = Array.isArray(json.functions) ? json.functions : [json.functions];
11504
11598
  for (const fn of entries) {
11505
- const source = isRecord(fn) ? asString(fn.source) ?? "functions" : "functions";
11599
+ const source = isRecord2(fn) ? asString(fn.source) ?? "functions" : "functions";
11506
11600
  const root = joinPath(dirname6(file.path), source);
11507
11601
  const rt = get(root, file.path, "gcp_cloud_functions");
11508
11602
  rt.evidence.unshift(evidenceAt(file.path, file.text, findLine(file.text, /"functions"/), `${DETECTOR8}.firebase`));
11509
11603
  }
11510
11604
  }
11511
11605
  for (const pkg of input.packageJsons) {
11512
- const scripts = isRecord(pkg.json.scripts) ? pkg.json.scripts : {};
11606
+ const scripts = isRecord2(pkg.json.scripts) ? pkg.json.scripts : {};
11513
11607
  for (const [script, cmd] of Object.entries(scripts)) {
11514
11608
  if (typeof cmd !== "string" || !/functions-framework/.test(cmd))
11515
11609
  continue;
@@ -11656,7 +11750,7 @@ function detectAzure(input) {
11656
11750
  if (basename3(hostFile.path) !== "host.json")
11657
11751
  continue;
11658
11752
  const host = parseJsonLoose(hostFile.text);
11659
- if (!isRecord(host) || host.version !== undefined && !String(host.version).startsWith("2"))
11753
+ if (!isRecord2(host) || host.version !== undefined && !String(host.version).startsWith("2"))
11660
11754
  continue;
11661
11755
  const root = dirname6(hostFile.path);
11662
11756
  const runtime = newRuntime("azure_functions", root, [hostFile.path], [evidenceAt(hostFile.path, hostFile.text, findLine(hostFile.text, /version/), DETECTOR9)], 0.9);
@@ -11678,7 +11772,7 @@ function detectAzure(input) {
11678
11772
  if (settings) {
11679
11773
  runtime.configFiles.push(settings.path);
11680
11774
  const json = parseJsonLoose(settings.text);
11681
- const values = isRecord(json) && isRecord(json.Values) ? json.Values : {};
11775
+ const values = isRecord2(json) && isRecord2(json.Values) ? json.Values : {};
11682
11776
  for (const name of Object.keys(values).sort()) {
11683
11777
  ctx.env.push({ name, source: `${settings.path} Values`, value: asString(values[name]), evidence: evidenceAt(settings.path, settings.text, findLine(settings.text, new RegExp(`"${escapeRe(name)}"`)), DETECTOR9) });
11684
11778
  }
@@ -11705,12 +11799,12 @@ function detectAzure(input) {
11705
11799
  }
11706
11800
  function handleFunctionJson(file, runtime, addDep) {
11707
11801
  const json = parseJsonLoose(file.text);
11708
- if (!isRecord(json))
11802
+ if (!isRecord2(json))
11709
11803
  return;
11710
11804
  const fnName = basename3(dirname6(file.path));
11711
11805
  let trigger = "unknown";
11712
11806
  for (const b of asArray(json.bindings)) {
11713
- if (!isRecord(b))
11807
+ if (!isRecord2(b))
11714
11808
  continue;
11715
11809
  const raw = asString(b.type) ?? "";
11716
11810
  const type = azureBindingType(raw);
@@ -11857,8 +11951,8 @@ function detectProcesses(input, roots) {
11857
11951
  const map = new Map;
11858
11952
  for (const pkg of packageJsons) {
11859
11953
  const json = pkg.json;
11860
- const deps = { ...isRecord(json.dependencies) ? json.dependencies : {} };
11861
- const scripts = isRecord(json.scripts) ? json.scripts : {};
11954
+ const deps = { ...isRecord2(json.dependencies) ? json.dependencies : {} };
11955
+ const scripts = isRecord2(json.scripts) ? json.scripts : {};
11862
11956
  const bin = json.bin;
11863
11957
  const server = Object.keys(deps).some((d) => SERVER_NPM.has(d));
11864
11958
  const agent = Object.keys(deps).some((d) => AGENT_NPM.has(d));
@@ -11878,7 +11972,7 @@ function detectProcesses(input, roots) {
11878
11972
  addEntry(rt, { name: "start", command: shellCommand(start), trigger });
11879
11973
  if (typeof bin === "string")
11880
11974
  addEntry(rt, { name: asString(json.name) ?? "bin", handler: joinPath(pkg.root, bin), command: ["node", joinPath(bin)], trigger: "cli" });
11881
- else if (isRecord(bin))
11975
+ else if (isRecord2(bin))
11882
11976
  for (const [name, target] of Object.entries(bin)) {
11883
11977
  if (typeof target === "string")
11884
11978
  addEntry(rt, { name, handler: joinPath(pkg.root, target), command: ["node", joinPath(target)], trigger: "cli" });
@@ -11976,10 +12070,10 @@ function pyprojectScripts(file, map) {
11976
12070
  } catch {
11977
12071
  return;
11978
12072
  }
11979
- const project = isRecord(doc.project) ? doc.project : {};
11980
- const tool = isRecord(doc.tool) ? doc.tool : {};
11981
- const poetry = isRecord(tool.poetry) ? tool.poetry : {};
11982
- const scripts = { ...isRecord(poetry.scripts) ? poetry.scripts : {}, ...isRecord(project.scripts) ? project.scripts : {} };
12073
+ const project = isRecord2(doc.project) ? doc.project : {};
12074
+ const tool = isRecord2(doc.tool) ? doc.tool : {};
12075
+ const poetry = isRecord2(tool.poetry) ? tool.poetry : {};
12076
+ const scripts = { ...isRecord2(poetry.scripts) ? poetry.scripts : {}, ...isRecord2(project.scripts) ? project.scripts : {} };
11983
12077
  const names = Object.keys(scripts).sort();
11984
12078
  if (names.length === 0)
11985
12079
  return;
@@ -11994,16 +12088,16 @@ function pyprojectScripts(file, map) {
11994
12088
  }
11995
12089
  function langgraph(file, map) {
11996
12090
  const json = parseJsonLoose(file.text);
11997
- if (!isRecord(json))
12091
+ if (!isRecord2(json))
11998
12092
  return;
11999
12093
  const root = dirname6(file.path);
12000
- const graphs = isRecord(json.graphs) ? json.graphs : {};
12094
+ const graphs = isRecord2(json.graphs) ? json.graphs : {};
12001
12095
  const isJs = Object.values(graphs).some((g) => typeof g === "string" && /\.[cm]?[jt]s:/.test(g));
12002
12096
  const rt = upsert(map, isJs ? "node_process" : "python_process", root, file.path);
12003
12097
  rt.frameworks = [...new Set([...rt.frameworks ?? [], "langgraph"])].sort();
12004
12098
  for (const name of Object.keys(graphs).sort()) {
12005
12099
  const ref = graphs[name];
12006
- const spec = typeof ref === "string" ? ref : isRecord(ref) ? asString(ref.path) : undefined;
12100
+ const spec = typeof ref === "string" ? ref : isRecord2(ref) ? asString(ref.path) : undefined;
12007
12101
  if (!spec)
12008
12102
  continue;
12009
12103
  const [p2, attr] = spec.split(":");
@@ -12149,10 +12243,10 @@ function detectVercel(input) {
12149
12243
  const { ctx, packageJsons } = input;
12150
12244
  const roots = new Map;
12151
12245
  for (const pkg of packageJsons) {
12152
- const deps = { ...isRecord(pkg.json.dependencies) ? pkg.json.dependencies : {}, ...isRecord(pkg.json.devDependencies) ? pkg.json.devDependencies : {} };
12246
+ const deps = { ...isRecord2(pkg.json.dependencies) ? pkg.json.dependencies : {}, ...isRecord2(pkg.json.devDependencies) ? pkg.json.devDependencies : {} };
12153
12247
  if (!("next" in deps))
12154
12248
  continue;
12155
- const scripts = isRecord(pkg.json.scripts) ? pkg.json.scripts : {};
12249
+ const scripts = isRecord2(pkg.json.scripts) ? pkg.json.scripts : {};
12156
12250
  const start = asString(scripts.start) ?? asString(scripts.dev);
12157
12251
  roots.set(pkg.root, { configFiles: [pkg.path], next: true, start: start ? splitCommand(start) : undefined });
12158
12252
  }
@@ -12207,8 +12301,8 @@ function detectVercel(input) {
12207
12301
  }
12208
12302
  if (info.vercelJson) {
12209
12303
  const json = parseJsonLoose(info.vercelJson.text);
12210
- for (const cron of isRecord(json) ? asArray(json.crons) : []) {
12211
- if (isRecord(cron) && typeof cron.path === "string")
12304
+ for (const cron of isRecord2(json) ? asArray(json.crons) : []) {
12305
+ if (isRecord2(cron) && typeof cron.path === "string")
12212
12306
  runtime.entrypoints.push({ name: `cron ${asString(cron.schedule) ?? ""} ${cron.path}`.trim(), handler: cron.path, trigger: "cron" });
12213
12307
  }
12214
12308
  }
@@ -12248,7 +12342,7 @@ function readOptions(cfg, paths2, read, depth = 0) {
12248
12342
  if (depth > 8 || !paths2.has(cfg))
12249
12343
  return null;
12250
12344
  const json = parseJsonLoose(read(cfg) ?? "");
12251
- if (!isRecord(json))
12345
+ if (!isRecord2(json))
12252
12346
  return null;
12253
12347
  const dir = dirname6(cfg);
12254
12348
  const merged = {};
@@ -12261,10 +12355,10 @@ function readOptions(cfg, paths2, read, depth = 0) {
12261
12355
  if (parent?.paths !== undefined)
12262
12356
  merged.paths = parent.paths;
12263
12357
  }
12264
- const opts = isRecord(json.compilerOptions) ? json.compilerOptions : {};
12358
+ const opts = isRecord2(json.compilerOptions) ? json.compilerOptions : {};
12265
12359
  if (typeof opts.baseUrl === "string")
12266
12360
  merged.baseUrl = joinPath(dir, opts.baseUrl);
12267
- if (isRecord(opts.paths)) {
12361
+ if (isRecord2(opts.paths)) {
12268
12362
  merged.paths = {
12269
12363
  base: typeof opts.baseUrl === "string" ? joinPath(dir, opts.baseUrl) : merged.baseUrl ?? dir,
12270
12364
  list: Object.entries(opts.paths).map(([key, value]) => {
@@ -12318,17 +12412,17 @@ function exportTargets(value) {
12318
12412
  return [value];
12319
12413
  if (Array.isArray(value))
12320
12414
  return value.flatMap(exportTargets);
12321
- if (isRecord(value))
12415
+ if (isRecord2(value))
12322
12416
  return Object.values(value).flatMap(exportTargets);
12323
12417
  return [];
12324
12418
  }
12325
12419
  function packageEntry(dir, sub, paths2, read) {
12326
12420
  const json = parseJsonLoose(read(joinPath(dir, "package.json")) ?? "");
12327
12421
  const fields = [];
12328
- if (isRecord(json)) {
12422
+ if (isRecord2(json)) {
12329
12423
  const exp = json.exports;
12330
12424
  const key = sub ? `./${sub}` : ".";
12331
- if (isRecord(exp) && Object.keys(exp).some((k) => k.startsWith("."))) {
12425
+ if (isRecord2(exp) && Object.keys(exp).some((k) => k.startsWith("."))) {
12332
12426
  if (exp[key] !== undefined)
12333
12427
  fields.push(...exportTargets(exp[key]));
12334
12428
  else {
@@ -12367,7 +12461,7 @@ function packageImportTargets(spec, from, paths2, read) {
12367
12461
  const manifest = joinPath(d, "package.json");
12368
12462
  if (paths2.has(manifest)) {
12369
12463
  const json = parseJsonLoose(read(manifest) ?? "");
12370
- const imports = isRecord(json) && isRecord(json.imports) ? json.imports : undefined;
12464
+ const imports = isRecord2(json) && isRecord2(json.imports) ? json.imports : undefined;
12371
12465
  if (imports) {
12372
12466
  const targets = [];
12373
12467
  if (imports[spec] !== undefined)
@@ -12643,14 +12737,14 @@ var ANCESTOR_ORM = [
12643
12737
  var CODE_FILE2 = /\.(?:[cm]?[jt]sx?|py)$/;
12644
12738
  function pyDependencyNames(doc) {
12645
12739
  const out = [];
12646
- const project = isRecord(doc.project) ? doc.project : {};
12740
+ const project = isRecord2(doc.project) ? doc.project : {};
12647
12741
  for (const req of asArray(project.dependencies)) {
12648
12742
  const m = typeof req === "string" ? /^\s*([A-Za-z0-9][\w.-]*)/.exec(req) : null;
12649
12743
  if (m)
12650
12744
  out.push(m[1]);
12651
12745
  }
12652
- const poetry = isRecord(doc.tool) && isRecord(doc.tool.poetry) ? doc.tool.poetry : {};
12653
- if (isRecord(poetry.dependencies))
12746
+ const poetry = isRecord2(doc.tool) && isRecord2(doc.tool.poetry) ? doc.tool.poetry : {};
12747
+ if (isRecord2(poetry.dependencies))
12654
12748
  out.push(...Object.keys(poetry.dependencies));
12655
12749
  return out.map(pyName);
12656
12750
  }
@@ -12661,7 +12755,7 @@ function npmDeps(json) {
12661
12755
  const out = [];
12662
12756
  for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
12663
12757
  const deps = json[field];
12664
- if (isRecord(deps))
12758
+ if (isRecord2(deps))
12665
12759
  out.push(...Object.keys(deps));
12666
12760
  }
12667
12761
  return out;
@@ -12680,7 +12774,7 @@ function directDeps(dir, byPath, npmNames, pyNames, goModules, workspaces) {
12680
12774
  const pkg = byPath.get(joinPath(dir, "package.json"));
12681
12775
  if (pkg) {
12682
12776
  const json = parseJsonLoose(pkg.text);
12683
- if (isRecord(json)) {
12777
+ if (isRecord2(json)) {
12684
12778
  for (const name of npmDeps(json)) {
12685
12779
  const target = npmNames.get(name);
12686
12780
  if (target !== undefined)
@@ -12690,11 +12784,11 @@ function directDeps(dir, byPath, npmNames, pyNames, goModules, workspaces) {
12690
12784
  }
12691
12785
  const pyproject = tomlDoc(byPath.get(joinPath(dir, "pyproject.toml")));
12692
12786
  if (pyproject) {
12693
- const tool = isRecord(pyproject.tool) ? pyproject.tool : {};
12694
- const uv = isRecord(tool.uv) ? tool.uv : {};
12695
- const sources = isRecord(uv.sources) ? uv.sources : {};
12787
+ const tool = isRecord2(pyproject.tool) ? pyproject.tool : {};
12788
+ const uv = isRecord2(tool.uv) ? tool.uv : {};
12789
+ const sources = isRecord2(uv.sources) ? uv.sources : {};
12696
12790
  for (const [name, src] of Object.entries(sources)) {
12697
- if (!isRecord(src))
12791
+ if (!isRecord2(src))
12698
12792
  continue;
12699
12793
  if (src.workspace === true) {
12700
12794
  const target = pyNames.get(pyName(name));
@@ -12714,13 +12808,13 @@ function directDeps(dir, byPath, npmNames, pyNames, goModules, workspaces) {
12714
12808
  out.push(target);
12715
12809
  }
12716
12810
  }
12717
- const poetry = isRecord(tool.poetry) ? tool.poetry : {};
12718
- const groups = [poetry.dependencies, ...isRecord(poetry.group) ? Object.values(poetry.group).map((g) => isRecord(g) ? g.dependencies : undefined) : []];
12811
+ const poetry = isRecord2(tool.poetry) ? tool.poetry : {};
12812
+ const groups = [poetry.dependencies, ...isRecord2(poetry.group) ? Object.values(poetry.group).map((g) => isRecord2(g) ? g.dependencies : undefined) : []];
12719
12813
  for (const deps of groups) {
12720
- if (!isRecord(deps))
12814
+ if (!isRecord2(deps))
12721
12815
  continue;
12722
12816
  for (const spec of Object.values(deps)) {
12723
- const path = isRecord(spec) ? asString(spec.path) : undefined;
12817
+ const path = isRecord2(spec) ? asString(spec.path) : undefined;
12724
12818
  if (path)
12725
12819
  out.push(joinPath(dir, path));
12726
12820
  }
@@ -12760,13 +12854,13 @@ function directDeps(dir, byPath, npmNames, pyNames, goModules, workspaces) {
12760
12854
  return out;
12761
12855
  }
12762
12856
  function composeBuildsUnder(svc, base, root) {
12763
- if (!isRecord(svc) || svc.build === undefined)
12857
+ if (!isRecord2(svc) || svc.build === undefined)
12764
12858
  return false;
12765
12859
  const build = svc.build;
12766
- const context = joinPath(base, typeof build === "string" ? build : isRecord(build) ? asString(build.context) ?? "." : ".");
12860
+ const context = joinPath(base, typeof build === "string" ? build : isRecord2(build) ? asString(build.context) ?? "." : ".");
12767
12861
  if (isUnder2(context, root))
12768
12862
  return true;
12769
- const dockerfile = isRecord(build) ? asString(build.dockerfile) : undefined;
12863
+ const dockerfile = isRecord2(build) ? asString(build.dockerfile) : undefined;
12770
12864
  return dockerfile !== undefined && isUnder2(joinPath(context, dockerfile), root);
12771
12865
  }
12772
12866
  function computeScope(files, root) {
@@ -12780,12 +12874,12 @@ function computeScope(files, root) {
12780
12874
  const name = basename3(f.path);
12781
12875
  if (name === "package.json") {
12782
12876
  const json = parseJsonLoose(f.text);
12783
- if (isRecord(json) && typeof json.name === "string")
12877
+ if (isRecord2(json) && typeof json.name === "string")
12784
12878
  npmNames.set(json.name, dirname6(f.path));
12785
12879
  } else if (name === "pyproject.toml") {
12786
12880
  const doc = tomlDoc(f);
12787
- const project = doc && isRecord(doc.project) ? doc.project : undefined;
12788
- const poetry = doc && isRecord(doc.tool) && isRecord(doc.tool.poetry) ? doc.tool.poetry : undefined;
12881
+ const project = doc && isRecord2(doc.project) ? doc.project : undefined;
12882
+ const poetry = doc && isRecord2(doc.tool) && isRecord2(doc.tool.poetry) ? doc.tool.poetry : undefined;
12789
12883
  const projectName = asString(project?.name) ?? asString(poetry?.name);
12790
12884
  if (projectName)
12791
12885
  pyNames.set(pyName(projectName), dirname6(f.path));
@@ -12800,16 +12894,16 @@ function computeScope(files, root) {
12800
12894
  if (basename3(f.path) !== "pyproject.toml")
12801
12895
  continue;
12802
12896
  const doc = tomlDoc(f);
12803
- const uv = doc && isRecord(doc.tool) && isRecord(doc.tool.uv) ? doc.tool.uv : undefined;
12804
- if (!uv || !isRecord(uv.workspace))
12897
+ const uv = doc && isRecord2(doc.tool) && isRecord2(doc.tool.uv) ? doc.tool.uv : undefined;
12898
+ if (!uv || !isRecord2(uv.workspace))
12805
12899
  continue;
12806
12900
  const base = dirname6(f.path);
12807
12901
  const members = asArray(uv.workspace.members).filter((m) => typeof m === "string").map((m) => globRegex(joinPath(base, m)));
12808
12902
  if (!members.some((re) => re.test(root) || [...pyNames.values()].some((d) => isUnder2(root, d) && re.test(d))))
12809
12903
  continue;
12810
12904
  const sources = new Map;
12811
- for (const [name, src] of Object.entries(isRecord(uv.sources) ? uv.sources : {})) {
12812
- if (!isRecord(src))
12905
+ for (const [name, src] of Object.entries(isRecord2(uv.sources) ? uv.sources : {})) {
12906
+ if (!isRecord2(src))
12813
12907
  continue;
12814
12908
  const target = src.workspace === true ? pyNames.get(pyName(name)) : asString(src.path) ? joinPath(base, asString(src.path)) : undefined;
12815
12909
  if (target !== undefined)
@@ -12875,7 +12969,7 @@ function computeScope(files, root) {
12875
12969
  const rel2 = base === "." ? root : root.slice(base.length + 1);
12876
12970
  if (/compose/.test(name)) {
12877
12971
  const doc = loadYaml(f.text);
12878
- const services = isRecord(doc) && isRecord(doc.services) ? doc.services : {};
12972
+ const services = isRecord2(doc) && isRecord2(doc.services) ? doc.services : {};
12879
12973
  if (Object.values(services).some((svc) => composeBuildsUnder(svc, base, root)))
12880
12974
  configs.add(f.path);
12881
12975
  } else if (new RegExp(`(?:^|[\\s"'=:/])\\.?/?${rel2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:[/"'\\s]|$)`, "m").test(f.text)) {
@@ -12984,8 +13078,8 @@ function scopeComposeImages(ctx, scope) {
12984
13078
  if (base === scope.root)
12985
13079
  continue;
12986
13080
  const doc = loadYaml(f.text);
12987
- const services = isRecord(doc) && isRecord(doc.services) ? Object.values(doc.services) : [];
12988
- const builds = services.some((svc) => isRecord(svc) && svc.build !== undefined);
13081
+ const services = isRecord2(doc) && isRecord2(doc.services) ? Object.values(doc.services) : [];
13082
+ const builds = services.some((svc) => isRecord2(svc) && svc.build !== undefined);
12989
13083
  if (!builds)
12990
13084
  optional.add(f.path);
12991
13085
  }
@@ -12999,14 +13093,14 @@ function scopeComposeImages(ctx, scope) {
12999
13093
  if (!/compose/.test(basename3(path)))
13000
13094
  continue;
13001
13095
  const doc = loadYaml(ctx.byPath.get(path)?.text ?? "");
13002
- const services = isRecord(doc) && isRecord(doc.services) ? doc.services : {};
13096
+ const services = isRecord2(doc) && isRecord2(doc.services) ? doc.services : {};
13003
13097
  const base = path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : ".";
13004
13098
  const deps = new Set;
13005
13099
  let declared = false;
13006
13100
  for (const svc of Object.values(services)) {
13007
- if (!isRecord(svc) || !composeBuildsUnder(svc, base, scope.root))
13101
+ if (!isRecord2(svc) || !composeBuildsUnder(svc, base, scope.root))
13008
13102
  continue;
13009
- const names = [...Array.isArray(svc.depends_on) ? svc.depends_on : isRecord(svc.depends_on) ? Object.keys(svc.depends_on) : [], ...Array.isArray(svc.links) ? svc.links : []];
13103
+ const names = [...Array.isArray(svc.depends_on) ? svc.depends_on : isRecord2(svc.depends_on) ? Object.keys(svc.depends_on) : [], ...Array.isArray(svc.links) ? svc.links : []];
13010
13104
  for (const n of names)
13011
13105
  if (typeof n === "string") {
13012
13106
  declared = true;
@@ -13140,7 +13234,7 @@ function scriptLocalFilter(ctx, runtimes) {
13140
13234
  }
13141
13235
  function lifecycleScripts(text) {
13142
13236
  const json = parseJsonLoose(text);
13143
- const scripts = new Map(Object.entries(isRecord(json) && isRecord(json.scripts) ? json.scripts : {}).filter((e) => typeof e[1] === "string"));
13237
+ const scripts = new Map(Object.entries(isRecord2(json) && isRecord2(json.scripts) ? json.scripts : {}).filter((e) => typeof e[1] === "string"));
13144
13238
  const selected = new Set([...scripts.keys()].filter((name) => /^(?:pre|post)?(?:start|serve|build|install|prepare)(?::[\w:-]+)?$/.test(name)));
13145
13239
  const queue = [...selected];
13146
13240
  while (queue.length > 0) {
@@ -13474,7 +13568,7 @@ function detectDependencies(input) {
13474
13568
  }
13475
13569
 
13476
13570
  // ../../packages/harness-bundle/src/register/harness-digest.ts
13477
- import { createHash as createHash4 } from "node:crypto";
13571
+ import { createHash as createHash5 } from "node:crypto";
13478
13572
  import { readFileSync as readFileSync7 } from "node:fs";
13479
13573
  import { join as join7 } from "node:path";
13480
13574
 
@@ -13550,7 +13644,7 @@ function harnessFiles(manifest, map, read) {
13550
13644
  if (basename3(p2) !== "package.json")
13551
13645
  continue;
13552
13646
  const json = parseJsonLoose(read(p2) ?? "");
13553
- if (isRecord(json) && typeof json.name === "string")
13647
+ if (isRecord2(json) && typeof json.name === "string")
13554
13648
  workspacePackages.set(json.name, dirname6(p2));
13555
13649
  }
13556
13650
  for (const f of importClosure({ entries, paths: paths2, read, workspacePackages }).files)
@@ -13578,7 +13672,7 @@ function harnessDigest(manifest, map, filesDir) {
13578
13672
  };
13579
13673
  const byPath = new Map(manifest.files.map((f) => [f.path, f]));
13580
13674
  const links = new Map(manifest.files.flatMap((f) => f.symlinkTarget !== undefined ? [[f.path, f.symlinkTarget]] : []));
13581
- const hash = createHash4("sha256");
13675
+ const hash = createHash5("sha256");
13582
13676
  hash.update(JSON.stringify({
13583
13677
  v: 1,
13584
13678
  detector: DETECTOR_VERSION,
@@ -13628,10 +13722,10 @@ function wranglerAssetDirs(configPath, text) {
13628
13722
  raw.push(m[1]);
13629
13723
  } else {
13630
13724
  const json = parseJsonLoose(text);
13631
- if (isRecord(json)) {
13632
- if (isRecord(json.assets) && typeof json.assets.directory === "string")
13725
+ if (isRecord2(json)) {
13726
+ if (isRecord2(json.assets) && typeof json.assets.directory === "string")
13633
13727
  raw.push(json.assets.directory);
13634
- if (isRecord(json.site) && typeof json.site.bucket === "string")
13728
+ if (isRecord2(json.site) && typeof json.site.bucket === "string")
13635
13729
  raw.push(json.site.bucket);
13636
13730
  }
13637
13731
  }
@@ -13711,7 +13805,7 @@ function insideCheckout(dir) {
13711
13805
  }
13712
13806
  }
13713
13807
  async function digestFile(path) {
13714
- const hash = createHash5("sha256");
13808
+ const hash = createHash6("sha256");
13715
13809
  await new Promise((resolve7, reject) => {
13716
13810
  createReadStream(path).on("data", (chunk) => hash.update(chunk)).on("error", reject).on("end", () => resolve7());
13717
13811
  });
@@ -14207,7 +14301,7 @@ function formatBytes(bytes) {
14207
14301
  }
14208
14302
 
14209
14303
  // src/harness-prompt-sources.ts
14210
- import { createHash as createHash6 } from "node:crypto";
14304
+ import { createHash as createHash7 } from "node:crypto";
14211
14305
  import { extname as extname5 } from "node:path";
14212
14306
 
14213
14307
  // src/prompt-source-verification/index.ts
@@ -14777,7 +14871,7 @@ function normalizeUsage(reviewed, endpointVerified, reviewedConsumerCited = fals
14777
14871
 
14778
14872
  // src/harness-prompt-sources.ts
14779
14873
  var CODE2 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py"]);
14780
- var shortHash = (text) => createHash6("sha256").update(text).digest("hex").slice(0, 20);
14874
+ var shortHash = (text) => createHash7("sha256").update(text).digest("hex").slice(0, 20);
14781
14875
  var TEST_PATH3 = /(^|\/)(?:test|tests|__tests__|fixtures?|test-fixtures)(?:[_-]|\/|$)|\.(?:test|spec)\.[^.]+$/i;
14782
14876
  var MAX_CODE_PROMPT_PATHS = 64;
14783
14877
  var identity = (source) => JSON.stringify([source.path, source.selector ?? null]);
@@ -15825,23 +15919,6 @@ function unresolvedReports(resolution, sites) {
15825
15919
  function promptArtifactsFromCallSites(callSites, context, promoted, options = {}) {
15826
15920
  return assemblePromptArtifacts(resolvePromptArguments(callSites, context, options), callSites, promoted, options);
15827
15921
  }
15828
-
15829
- // src/harness-sync-limits.ts
15830
- var MAX_HARNESS_SYNC_GRAPH_BYTES = 2000000;
15831
- function assertHarnessGraphSyncSize(graph) {
15832
- if (!graph || typeof graph !== "object" || Array.isArray(graph)) {
15833
- throw new CliInputError("Harness graph must be an object before sync.");
15834
- }
15835
- const graphBytes = Buffer.byteLength(JSON.stringify(graph), "utf8");
15836
- if (graphBytes > MAX_HARNESS_SYNC_GRAPH_BYTES) {
15837
- throw new CliInputError(`Harness graph is too large to sync (${graphBytes.toLocaleString()} bytes; limit ${MAX_HARNESS_SYNC_GRAPH_BYTES.toLocaleString()}).`, [
15838
- "Run `moda harness analyze --path=<agent-dir>` to narrow the harness root.",
15839
- "Reduce captured prompt/tool bodies if the graph grew too large.",
15840
- "Split multiple agent roots into separate harness syncs per tenant."
15841
- ].join(`
15842
- `));
15843
- }
15844
- }
15845
15922
  // src/harness.ts
15846
15923
  var MODA_DIR = ".moda";
15847
15924
  var HARNESS_PATH = join12(MODA_DIR, "harness.json");
@@ -15875,6 +15952,7 @@ var HARNESS_FAMILY_FLAGS = [
15875
15952
  "remote",
15876
15953
  "repair",
15877
15954
  "report",
15955
+ "require-full-bodies",
15878
15956
  "run",
15879
15957
  "run-id",
15880
15958
  "shards",
@@ -16159,7 +16237,7 @@ async function runHarnessCommand(context) {
16159
16237
  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.");
16160
16238
  }
16161
16239
  if (context.flags["github-actions"] === "true") {
16162
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-18v41647.js");
16240
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-9a48sd2r.js");
16163
16241
  const result = await runGithubActionsAnalyze(rootDir, {
16164
16242
  writeReport: (report2) => {
16165
16243
  const normalized = normalizeHarnessReport(report2);
@@ -16310,8 +16388,8 @@ async function runHarnessCommand(context) {
16310
16388
  }
16311
16389
  const { artifacts, unknowns, canonicalAgentIdentities } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
16312
16390
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
16313
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-rdzd700n.js");
16314
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-g3zsqcjg.js");
16391
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-t4fncjwa.js");
16392
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-5q79y09b.js");
16315
16393
  let components = { runtimeAgents: [], artifacts: [], warnings: [] };
16316
16394
  if (promote === "all" || promote === "topology" || promote === "tools") {
16317
16395
  const { result, ctx } = extractHarnessWithContext2(rootDir);
@@ -16377,8 +16455,8 @@ async function runHarnessCommand(context) {
16377
16455
  }
16378
16456
  case "extract": {
16379
16457
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
16380
- const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-rdzd700n.js");
16381
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-g3zsqcjg.js");
16458
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-t4fncjwa.js");
16459
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-5q79y09b.js");
16382
16460
  const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
16383
16461
  const items = deterministicGraphItems(rootDir);
16384
16462
  const artifacts = items.artifacts;
@@ -16873,7 +16951,7 @@ function reportJsonCandidates(output) {
16873
16951
  function parseHarnessReportCandidate(candidate) {
16874
16952
  try {
16875
16953
  const parsed = JSON.parse(candidate.trim());
16876
- if (isRecord2(parsed) && parsed.schemaVersion === "harness_report.v0.1") {
16954
+ if (isRecord3(parsed) && parsed.schemaVersion === "harness_report.v0.1") {
16877
16955
  return parsed;
16878
16956
  }
16879
16957
  } catch {
@@ -17180,7 +17258,7 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
17180
17258
  ];
17181
17259
  if (owners.some((owner) => knownAgents.has(owner)))
17182
17260
  continue;
17183
- const id = `unresolved_tool_owner_${createHash7("sha256").update(artifact2.id).digest("hex").slice(0, 16)}`;
17261
+ const id = `unresolved_tool_owner_${createHash8("sha256").update(artifact2.id).digest("hex").slice(0, 16)}`;
17184
17262
  if (!normalized.graph.unknowns.some((unknown) => unknown.id === id))
17185
17263
  normalized.graph.unknowns.push({
17186
17264
  id,
@@ -17285,8 +17363,8 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
17285
17363
  evals: new Set(["model_config", "eval"])
17286
17364
  };
17287
17365
  async function deterministicFloorGraph(rootDir, options = {}) {
17288
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-rdzd700n.js");
17289
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-g3zsqcjg.js");
17366
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-t4fncjwa.js");
17367
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-5q79y09b.js");
17290
17368
  const { result, ctx } = extractHarnessWithContext2(rootDir);
17291
17369
  const items = deterministicGraphItems(rootDir);
17292
17370
  const components = mergeEnumeratedComponents(items.artifacts, enumerateHarnessComponents(result, ctx));
@@ -17440,7 +17518,7 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
17440
17518
  }
17441
17519
  const extracted = !allowedTypes || allowedTypes.has("model_config") ? extractedModelItems(rootDir) : { artifacts: [], unknowns: [], rewritten: new Set, enabled: false };
17442
17520
  promoted = withExtractedModels(promoted, extracted, rootDir);
17443
- if (extracted.enabled && isRecord2(graph.scan)) {
17521
+ if (extracted.enabled && isRecord3(graph.scan)) {
17444
17522
  try {
17445
17523
  const { literals, truncated } = collectModelLiterals(rootDir);
17446
17524
  const scan = graph.scan;
@@ -17564,7 +17642,7 @@ function remapCanonicalArtifactAgents(graph, artifacts = graph.artifacts, dropUn
17564
17642
  }
17565
17643
  for (const [agentId, artifactIds] of unresolved) {
17566
17644
  const identity2 = canonical.get(agentId);
17567
- const id = `unresolved_agent_links_${createHash7("sha256").update(agentId).digest("hex").slice(0, 16)}`;
17645
+ const id = `unresolved_agent_links_${createHash8("sha256").update(agentId).digest("hex").slice(0, 16)}`;
17568
17646
  if (graph.unknowns.some((unknown) => unknown.id === id))
17569
17647
  continue;
17570
17648
  graph.unknowns.push({
@@ -17853,18 +17931,18 @@ function extractAgentTextFromOutput(output) {
17853
17931
  `);
17854
17932
  }
17855
17933
  function extractTextFromAgentEvent(event) {
17856
- if (!isRecord2(event))
17934
+ if (!isRecord3(event))
17857
17935
  return;
17858
17936
  const directText = stringValue(event.text) ?? stringValue(event.message) ?? stringValue(event.delta) ?? stringValue(event.result);
17859
17937
  if (directText)
17860
17938
  return directText;
17861
- const message = isRecord2(event.message) ? event.message : undefined;
17939
+ const message = isRecord3(event.message) ? event.message : undefined;
17862
17940
  const messageText = message ? stringValue(message.text) ?? stringValue(message.content) : undefined;
17863
17941
  if (messageText)
17864
17942
  return messageText;
17865
17943
  const content = Array.isArray(message?.content) ? message.content : Array.isArray(event.content) ? event.content : [];
17866
17944
  const textParts = content.map((part) => {
17867
- if (!isRecord2(part))
17945
+ if (!isRecord3(part))
17868
17946
  return;
17869
17947
  return stringValue(part.text) ?? stringValue(part.content);
17870
17948
  }).filter((part) => Boolean(part));
@@ -18102,9 +18180,9 @@ function formatExternalAgentDisplayEvent(event, adapter) {
18102
18180
  `;
18103
18181
  }
18104
18182
  function extractAgentEventTelemetry(event) {
18105
- const message = isRecord2(event.message) ? event.message : undefined;
18106
- const usage = isRecord2(event.usage) ? event.usage : isRecord2(message?.usage) ? message.usage : undefined;
18107
- const modelUsage = isRecord2(event.modelUsage) ? event.modelUsage : undefined;
18183
+ const message = isRecord3(event.message) ? event.message : undefined;
18184
+ const usage = isRecord3(event.usage) ? event.usage : isRecord3(message?.usage) ? message.usage : undefined;
18185
+ const modelUsage = isRecord3(event.modelUsage) ? event.modelUsage : undefined;
18108
18186
  const model = stringValue(event.model) ?? stringValue(message?.model) ?? (modelUsage ? Object.keys(modelUsage)[0] : undefined);
18109
18187
  const durationValue = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
18110
18188
  const durationMs = durationValue(event.duration_ms) ?? durationValue(event.durationMs) ?? durationValue(event.duration_api_ms);
@@ -18118,7 +18196,7 @@ function extractAgentEventTelemetry(event) {
18118
18196
  }
18119
18197
  function parseExternalAgentEvent(event) {
18120
18198
  const body = parseExternalAgentEventBody(event);
18121
- if (!isRecord2(event))
18199
+ if (!isRecord3(event))
18122
18200
  return body;
18123
18201
  const telemetry = extractAgentEventTelemetry(event);
18124
18202
  if (!telemetry)
@@ -18130,10 +18208,10 @@ function parseExternalAgentEvent(event) {
18130
18208
  return { kind: "system", message: "usage update", telemetryOnly: true, ...telemetry };
18131
18209
  }
18132
18210
  function parseExternalAgentEventBody(event) {
18133
- if (!isRecord2(event))
18211
+ if (!isRecord3(event))
18134
18212
  return { kind: "agent_text", message: truncateText(String(event), 500) };
18135
- const msg = isRecord2(event.msg) ? event.msg : undefined;
18136
- const call = isRecord2(event.call) ? event.call : undefined;
18213
+ const msg = isRecord3(event.msg) ? event.msg : undefined;
18214
+ const call = isRecord3(event.call) ? event.call : undefined;
18137
18215
  const type = stringValue(event.type) ?? stringValue(event.event) ?? stringValue(msg?.type);
18138
18216
  const subtype = stringValue(event.subtype);
18139
18217
  if (type === "rate_limit_event")
@@ -18147,7 +18225,7 @@ function parseExternalAgentEventBody(event) {
18147
18225
  if (directText && !isLowSignalEventType(type)) {
18148
18226
  return { kind: "agent_text", message: truncateText(firstMeaningfulLine(directText), 500) };
18149
18227
  }
18150
- const message = isRecord2(event.message) ? event.message : undefined;
18228
+ const message = isRecord3(event.message) ? event.message : undefined;
18151
18229
  const messageText = message ? stringValue(message.text) ?? stringValue(message.content) : undefined;
18152
18230
  if (messageText && !isLowSignalEventType(type)) {
18153
18231
  return { kind: "agent_text", message: truncateText(firstMeaningfulLine(messageText), 500) };
@@ -18168,7 +18246,7 @@ function parseExternalAgentEventBody(event) {
18168
18246
  return;
18169
18247
  }
18170
18248
  function parseAgentContentPart(part) {
18171
- if (!isRecord2(part))
18249
+ if (!isRecord3(part))
18172
18250
  return;
18173
18251
  const partType = stringValue(part.type);
18174
18252
  if (partType === "tool_use" || partType === "tool_call") {
@@ -18190,7 +18268,7 @@ function parseAgentContentPart(part) {
18190
18268
  return;
18191
18269
  }
18192
18270
  function toolInputDetail(input) {
18193
- if (!isRecord2(input))
18271
+ if (!isRecord3(input))
18194
18272
  return;
18195
18273
  const value = stringValue(input.file_path) ?? stringValue(input.filePath) ?? stringValue(input.path) ?? stringValue(input.notebook_path) ?? stringValue(input.command) ?? stringValue(input.cmd) ?? stringValue(input.pattern) ?? stringValue(input.query);
18196
18274
  return value ? truncateText(firstMeaningfulLine(value), 300) : undefined;
@@ -18208,7 +18286,7 @@ function analystDisplayName(adapter) {
18208
18286
  return "Cursor";
18209
18287
  return "Codex";
18210
18288
  }
18211
- function isRecord2(value) {
18289
+ function isRecord3(value) {
18212
18290
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
18213
18291
  }
18214
18292
  function stringValue(value) {
@@ -19284,15 +19362,36 @@ function plannedDryRunRemote(plan) {
19284
19362
  };
19285
19363
  }
19286
19364
  async function syncHarnessWithRemote(context, body) {
19287
- assertHarnessGraphSyncSize(body.graph);
19288
19365
  const profileOptions = { profile: context.profile, env: context.env };
19289
19366
  const hasApiKey = Boolean(resolveApiKey(profileOptions));
19367
+ const requireFullBodies = context.flags["require-full-bodies"] === "true";
19368
+ const prepared = await prepareHarnessSyncRequest(body, !context.dryRun && hasApiKey ? controlApiArtifactBodyStore((endpoint, init) => callControlAPI(endpoint, init, profileOptions)) : undefined, undefined, undefined, { requireStorable: requireFullBodies });
19369
+ assertHarnessGraphSyncSize(prepared.request.graph);
19370
+ assertHarnessSyncRequestSize({ ...prepared.request, dryRun: context.dryRun });
19371
+ if (prepared.shortened > 0 && context.dryRun) {
19372
+ writeHarnessNotice(context, "The graph is over the sync limit, so its largest bodies are shortened. A dry run uploads none of their full text; the real sync uploads it.");
19373
+ }
19374
+ const bodiesLabel = (count) => `${count} shortened ${count === 1 ? "body" : "bodies"}`;
19375
+ if (prepared.unstorableBodies > 0) {
19376
+ const count = bodiesLabel(prepared.unstorableBodies);
19377
+ if (requireFullBodies) {
19378
+ throw new CliInputError(`${count} ${prepared.unstorableBodies === 1 ? "is" : "are"} over the ${MAX_STORED_ARTIFACT_BODY_BYTES.toLocaleString()}-byte full-body limit and cannot be stored, so nothing was synced (--require-full-bodies).`, "Split the largest artifacts into smaller files, or drop --require-full-bodies to sync with shortened bodies.");
19379
+ }
19380
+ writeHarnessNotice(context, `${count} ${prepared.unstorableBodies === 1 ? "is" : "are"} over the ${MAX_STORED_ARTIFACT_BODY_BYTES.toLocaleString()}-byte full-body limit; the harness syncs with them shortened and their full text is not stored.`);
19381
+ }
19382
+ if (prepared.storeFailed) {
19383
+ const count = bodiesLabel(prepared.storeFailedBodies);
19384
+ if (requireFullBodies) {
19385
+ throw new CliInputError(`Uploading the full text of ${count} failed, so nothing was synced (--require-full-bodies).`, "Rerun `moda harness sync`, or drop --require-full-bodies to sync with shortened bodies.");
19386
+ }
19387
+ writeHarnessNotice(context, `Uploading the full text of ${count} failed; the harness syncs with shortened bodies and their full text is not retrievable yet. Rerun \`moda harness sync\` to upload it (the version does not change).`);
19388
+ }
19290
19389
  if (context.dryRun && !hasApiKey)
19291
19390
  return;
19292
19391
  return await callControlAPI("/harnesses/sync", {
19293
19392
  method: "POST",
19294
19393
  body: JSON.stringify({
19295
- ...body,
19394
+ ...prepared.request,
19296
19395
  dryRun: context.dryRun
19297
19396
  })
19298
19397
  }, profileOptions);
@@ -21068,7 +21167,7 @@ function normalizePath3(path) {
21068
21167
  return path.split(sep5).join("/");
21069
21168
  }
21070
21169
  function hashText(text) {
21071
- return createHash7("sha256").update(text).digest("hex");
21170
+ return createHash8("sha256").update(text).digest("hex");
21072
21171
  }
21073
21172
 
21074
21173
  // src/harness-candidates.ts
@@ -22984,7 +23083,7 @@ function capPromotedEvidence(artifact2) {
22984
23083
  artifact2.evidence = artifact2.evidence.slice(0, max);
22985
23084
  }
22986
23085
  function distinctStableId(prefix, raw) {
22987
- return `${stableId(prefix, raw.replace(/\./g, "-"))}_${createHash8("sha256").update(raw).digest("hex").slice(0, 8)}`;
23086
+ return `${stableId(prefix, raw.replace(/\./g, "-"))}_${createHash9("sha256").update(raw).digest("hex").slice(0, 8)}`;
22988
23087
  }
22989
23088
  function promoteModelIds(occurrences, context) {
22990
23089
  const out = [];
@@ -23841,7 +23940,7 @@ function modelArtifacts(result) {
23841
23940
  return (result.models ?? []).map((model) => {
23842
23941
  const agentIds = [...new Set(model.calledFrom.flatMap((site) => owners.get(site.callSite) ?? []))].sort();
23843
23942
  return {
23844
- id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
23943
+ id: `model_config_${slug(model.id)}_${createHash10("sha256").update(model.id).digest("hex").slice(0, 8)}`,
23845
23944
  type: "model_config",
23846
23945
  name: model.id,
23847
23946
  scope: agentIds.length === 1 ? "agent" : "shared",