@mnemonik/cli 7.154.2 → 7.155.2

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 (59) hide show
  1. package/dist/auth/credentials.js +35 -22
  2. package/dist/auth/index.js +35 -22
  3. package/dist/auth/installSession.js +21 -10
  4. package/dist/auth/status.js +21 -10
  5. package/dist/authorizationWords.js +21 -10
  6. package/dist/diagnostics.js +35 -22
  7. package/dist/digests.json +57 -53
  8. package/dist/hooksLog.js +3 -1
  9. package/dist/identity/migrate.js +35 -22
  10. package/dist/install/hosts.js +21 -10
  11. package/dist/install/journal.js +35 -22
  12. package/dist/install/journey.d.ts.map +1 -1
  13. package/dist/install/journey.js +42 -22
  14. package/dist/install/journey.js.map +1 -1
  15. package/dist/install/ownership.js +35 -22
  16. package/dist/install/transaction.js +35 -22
  17. package/dist/install/ui.js +35 -22
  18. package/dist/installSession.js +21 -10
  19. package/dist/installation.js +35 -22
  20. package/dist/launcher.js +35 -22
  21. package/dist/preflight.js +23 -10
  22. package/dist/project/eligibility.js +35 -22
  23. package/dist/project/records.js +35 -22
  24. package/dist/project.js +35 -22
  25. package/dist/router.d.ts +2 -0
  26. package/dist/router.d.ts.map +1 -1
  27. package/dist/router.js +66 -43
  28. package/dist/router.js.map +1 -1
  29. package/dist/runtime/releaseSource.js +35 -22
  30. package/dist/runtime/selfUpdate.d.ts +11 -1
  31. package/dist/runtime/selfUpdate.d.ts.map +1 -1
  32. package/dist/runtime/selfUpdate.js +52 -26
  33. package/dist/runtime/selfUpdate.js.map +1 -1
  34. package/dist/runtime/signers.js +177 -22
  35. package/dist/runtime/store.js +81 -22
  36. package/dist/runtime/updateCheck.js +35 -22
  37. package/dist/sbom.json +21 -21
  38. package/dist/scanner/control.js +35 -22
  39. package/dist/scanner/data.js +21 -10
  40. package/dist/scanner/discover.js +23 -10
  41. package/dist/scanner/enable.d.ts +5 -0
  42. package/dist/scanner/enable.d.ts.map +1 -1
  43. package/dist/scanner/enable.js +52 -22
  44. package/dist/scanner/enable.js.map +1 -1
  45. package/dist/scanner/estimate.d.ts +41 -0
  46. package/dist/scanner/estimate.d.ts.map +1 -0
  47. package/dist/scanner/estimate.js +2461 -0
  48. package/dist/scanner/estimate.js.map +1 -0
  49. package/dist/scanner/picker.js +23 -10
  50. package/dist/scanner/service.js +35 -22
  51. package/dist/scanner/update.js +35 -22
  52. package/dist/scanner-release.json +24 -24
  53. package/dist/status.d.ts +6 -0
  54. package/dist/status.d.ts.map +1 -1
  55. package/dist/status.js +39 -23
  56. package/dist/status.js.map +1 -1
  57. package/dist/vendor/local-setup.js +35 -22
  58. package/dist/vendor/shared/runtimeReader.js +110 -21
  59. package/package.json +31 -31
@@ -1090,6 +1090,7 @@ var init_secretPatterns = __esm({
1090
1090
  import { randomBytes } from "node:crypto";
1091
1091
  import { closeSync, constants, fstatSync, lstatSync as lstatSync2, mkdirSync as mkdirSync2, openSync, renameSync as renameSync2, statSync, unlinkSync as unlinkSync2, writeSync } from "node:fs";
1092
1092
  import { dirname as dirname3, join as join4 } from "node:path";
1093
+ import { open as openAsync, stat as statAsync } from "node:fs/promises";
1093
1094
  function hookTraceEnabled(env = process.env) {
1094
1095
  const value = env[HOOK_TRACE_ENV]?.trim().toLowerCase();
1095
1096
  return !value || !["off", "0", "false", "no", "disabled"].includes(value);
@@ -1279,7 +1280,88 @@ function startHookTrace(options) {
1279
1280
  trace.open();
1280
1281
  return trace;
1281
1282
  }
1282
- var HOOK_TRACE_MAX_BYTES, HOOK_TRACE_ENV, MAX_FIELDS, MAX_CALLS, MAX_ERROR_CHARS, SAFE_ID, SAFE_NAME, SAFE_ENUM, preparedDirectories, STALE_LOCK_MS, isObject, HookTrace, active;
1283
+ async function summarizeRecentHookCalls(host, options = {}) {
1284
+ const empty = { missed: 0, total: 0 };
1285
+ const now = options.now ?? Date.now();
1286
+ const since = now - (options.windowMs ?? HOOK_MISS_WINDOW_MS);
1287
+ let text;
1288
+ try {
1289
+ const file = hookTraceFile(host, options.stateDir);
1290
+ const size = (await statAsync(file)).size;
1291
+ const handle = await openAsync(file, "r");
1292
+ try {
1293
+ const length = Math.min(size, HOOK_MISS_TAIL_BYTES);
1294
+ const buffer = Buffer.alloc(length);
1295
+ await handle.read(buffer, 0, length, size - length);
1296
+ text = buffer.toString("utf8");
1297
+ } finally {
1298
+ await handle.close();
1299
+ }
1300
+ } catch {
1301
+ return empty;
1302
+ }
1303
+ const started = /* @__PURE__ */ new Map();
1304
+ const ended = /* @__PURE__ */ new Set();
1305
+ let missed = 0;
1306
+ let total = 0;
1307
+ for (const line of text.split("\n")) {
1308
+ let record2;
1309
+ try {
1310
+ record2 = JSON.parse(line);
1311
+ } catch {
1312
+ continue;
1313
+ }
1314
+ const at = Date.parse(record2.ts);
1315
+ if (!(at >= since))
1316
+ continue;
1317
+ if (record2.phase === "start")
1318
+ started.set(record2.id, at);
1319
+ else if (record2.phase === "end") {
1320
+ ended.add(record2.id);
1321
+ const answeredByPath = /* @__PURE__ */ new Map();
1322
+ for (const call of record2.calls ?? []) {
1323
+ const status = call.status ?? 0;
1324
+ const answered = call.error === void 0 && call.pending !== true && status > 0 && status < 500 && status !== 408 && status !== 429;
1325
+ answeredByPath.set(call.path, (answeredByPath.get(call.path) ?? false) || answered);
1326
+ }
1327
+ for (const answered of answeredByPath.values()) {
1328
+ total++;
1329
+ if (!answered)
1330
+ missed++;
1331
+ }
1332
+ }
1333
+ }
1334
+ for (const [id, at] of started) {
1335
+ if (ended.has(id) || now - at < 6e4)
1336
+ continue;
1337
+ total++;
1338
+ missed++;
1339
+ }
1340
+ return { missed, total };
1341
+ }
1342
+ function summaryFor(host, options) {
1343
+ const key = `${host}\0${options.stateDir ?? ""}\0${options.now ?? ""}`;
1344
+ const cached = summaries.get(key);
1345
+ if (cached)
1346
+ return cached;
1347
+ const entry = {
1348
+ read: Promise.resolve({})
1349
+ };
1350
+ entry.read = summarizeRecentHookCalls(host, options).then(({ missed, total }) => {
1351
+ const value = total > 0 ? { [HOOK_MISSES_HEADER]: `${missed}/${total}` } : {};
1352
+ entry.value = value;
1353
+ return value;
1354
+ });
1355
+ summaries.set(key, entry);
1356
+ return entry;
1357
+ }
1358
+ function hookMissesHeaders(host, options = {}) {
1359
+ return summaryFor(host, options).read;
1360
+ }
1361
+ function hookMissesHeadersIfReady(host, options = {}) {
1362
+ return summaryFor(host, options).value ?? {};
1363
+ }
1364
+ var HOOK_TRACE_MAX_BYTES, HOOK_TRACE_ENV, MAX_FIELDS, MAX_CALLS, MAX_ERROR_CHARS, SAFE_ID, SAFE_NAME, SAFE_ENUM, preparedDirectories, STALE_LOCK_MS, isObject, HookTrace, active, HOOK_MISS_WINDOW_MS, HOOK_MISS_TAIL_BYTES, HOOK_MISSES_HEADER, summaries;
1283
1365
  var init_hookTrace = __esm({
1284
1366
  "packages/shared/dist/hookTrace.js"() {
1285
1367
  "use strict";
@@ -1482,6 +1564,10 @@ var init_hookTrace = __esm({
1482
1564
  });
1483
1565
  }
1484
1566
  };
1567
+ HOOK_MISS_WINDOW_MS = 30 * 60 * 1e3;
1568
+ HOOK_MISS_TAIL_BYTES = 64 * 1024;
1569
+ HOOK_MISSES_HEADER = "x-mnemonik-hook-misses";
1570
+ summaries = /* @__PURE__ */ new Map();
1485
1571
  }
1486
1572
  });
1487
1573
 
@@ -1495,7 +1581,40 @@ function safePath(path) {
1495
1581
  throw new RuntimeError("permission");
1496
1582
  return path;
1497
1583
  }
1498
- var RuntimeError, hash, missing, versionName, statIdentity, RuntimeReader;
1584
+ function limiter(limit) {
1585
+ let active3 = 0;
1586
+ const waiting = [];
1587
+ return async (work) => {
1588
+ if (active3 >= limit)
1589
+ await new Promise((release) => waiting.push(release));
1590
+ active3 += 1;
1591
+ try {
1592
+ return await work();
1593
+ } finally {
1594
+ active3 -= 1;
1595
+ waiting.shift()?.();
1596
+ }
1597
+ };
1598
+ }
1599
+ async function ownedFileBytes(path, mode) {
1600
+ const fd = await open(path, constants2.O_RDONLY | constants2.O_NOFOLLOW).catch((error) => {
1601
+ throw error.code === "ELOOP" ? new RuntimeError("permission") : error;
1602
+ });
1603
+ try {
1604
+ const stat2 = await fd.stat();
1605
+ if (!stat2.isFile() || stat2.uid !== process.getuid?.() || (stat2.mode & 511) !== mode)
1606
+ throw new RuntimeError("permission");
1607
+ return await fd.readFile();
1608
+ } finally {
1609
+ await fd.close();
1610
+ }
1611
+ }
1612
+ async function settleAll(work) {
1613
+ const failed = (await Promise.allSettled(work)).find((result) => result.status === "rejected");
1614
+ if (failed)
1615
+ throw failed.reason;
1616
+ }
1617
+ var RuntimeError, hash, missing, versionName, VERIFY_CONCURRENCY, statIdentity, RuntimeReader;
1499
1618
  var init_runtimeReader = __esm({
1500
1619
  "packages/shared/dist/runtimeReader.js"() {
1501
1620
  "use strict";
@@ -1516,6 +1635,7 @@ var init_runtimeReader = __esm({
1516
1635
  throw new RuntimeError("permission");
1517
1636
  return v;
1518
1637
  };
1638
+ VERIFY_CONCURRENCY = 16;
1519
1639
  statIdentity = (stat2) => [stat2.dev, stat2.ino, stat2.mode, stat2.uid, stat2.size, stat2.mtimeMs, stat2.ctimeMs].join(":");
1520
1640
  RuntimeReader = class _RuntimeReader {
1521
1641
  run;
@@ -1634,12 +1754,23 @@ var init_runtimeReader = __esm({
1634
1754
  throw new RuntimeError(error instanceof Error && error.message === "acl_permissions" ? "permission" : "acl_unavailable");
1635
1755
  }
1636
1756
  }
1637
- async inspect(path, directory = false, allowMissing = false, replacing = false) {
1757
+ /**
1758
+ * `proven` (one verification's own set, POSIX only) holds directories this
1759
+ * verification has already inspected in full: their components are not
1760
+ * inspected again for every file beneath them, and directories proven here
1761
+ * are added to it.
1762
+ */
1763
+ async inspect(path, directory = false, allowMissing = false, replacing = false, proven) {
1638
1764
  const absolute = this.guardedPath(path);
1639
1765
  const windowsPaths = [];
1640
- let part = parse(absolute).root;
1641
- for (const name of absolute.slice(part.length).split(sep2)) {
1766
+ const remembered = process.platform === "win32" ? void 0 : proven;
1767
+ const checkedDirectories = [];
1768
+ const parent = dirname4(absolute);
1769
+ let part = remembered?.has(parent) ? parent : parse(absolute).root;
1770
+ for (const name of absolute.slice(part.length).split(sep2).filter(Boolean)) {
1642
1771
  part = join5(part, name);
1772
+ if (part !== absolute && remembered?.has(part))
1773
+ continue;
1643
1774
  const stat2 = await lstat3(part).catch((e) => {
1644
1775
  if (allowMissing && missing(e))
1645
1776
  return null;
@@ -1680,7 +1811,12 @@ var init_runtimeReader = __esm({
1680
1811
  windowsPaths.push(part);
1681
1812
  } else if (stat2.uid !== process.getuid?.() || (stat2.mode & 63) !== 0)
1682
1813
  throw new RuntimeError("permission");
1814
+ if (stat2.isDirectory())
1815
+ checkedDirectories.push(part);
1683
1816
  }
1817
+ if (remembered)
1818
+ for (const checked of checkedDirectories)
1819
+ remembered.add(checked);
1684
1820
  await this.audit(windowsPaths);
1685
1821
  for (const part2 of windowsPaths) {
1686
1822
  const verdict = this.windowsAudit.get(part2)?.verdict;
@@ -1701,8 +1837,8 @@ var init_runtimeReader = __esm({
1701
1837
  this.windowsAudit.delete(absolute);
1702
1838
  this.windowsStats.delete(absolute);
1703
1839
  }
1704
- async bytes(path) {
1705
- await this.inspect(path);
1840
+ async bytes(path, proven) {
1841
+ await this.inspect(path, false, false, false, proven);
1706
1842
  const fd = await open(path, constants2.O_RDONLY | (process.platform === "win32" ? 0 : constants2.O_NOFOLLOW));
1707
1843
  try {
1708
1844
  return await fd.readFile();
@@ -1774,36 +1910,43 @@ var init_runtimeReader = __esm({
1774
1910
  if (process.platform === "win32")
1775
1911
  await this.audit(Object.keys(m.files).map((name) => join5(directory, safePath(name))));
1776
1912
  const actual = [];
1913
+ const proven = /* @__PURE__ */ new Set();
1914
+ const limit = limiter(process.platform === "win32" ? 1 : VERIFY_CONCURRENCY);
1777
1915
  const walk = async (dir, prefix = "") => {
1778
- await this.inspect(dir, true);
1779
- for (const name of await readdir(dir)) {
1780
- const key = prefix + name;
1781
- if (!prefix && name === "manifest.json")
1782
- continue;
1783
- const path = join5(dir, name);
1784
- if ((await lstat3(path)).isDirectory())
1916
+ const entries = await limit(async () => {
1917
+ await this.inspect(dir, true, false, false, proven);
1918
+ return readdir(dir, { withFileTypes: true });
1919
+ });
1920
+ await settleAll(entries.map(async (entry) => {
1921
+ const key = prefix + entry.name;
1922
+ if (!prefix && entry.name === "manifest.json")
1923
+ return;
1924
+ const path = join5(dir, entry.name);
1925
+ if (entry.isDirectory())
1785
1926
  await walk(path, key + "/");
1786
1927
  else {
1787
- await this.inspect(path);
1928
+ if (process.platform === "win32")
1929
+ await limit(() => this.inspect(path, false, false, false, proven));
1930
+ else if (!entry.isFile())
1931
+ throw new RuntimeError("permission");
1788
1932
  actual.push(key);
1789
1933
  }
1790
- }
1934
+ }));
1791
1935
  };
1792
1936
  await walk(directory);
1793
1937
  if (actual.sort().join("\n") !== Object.keys(m.files).sort().join("\n"))
1794
1938
  throw new RuntimeError("digest_mismatch");
1795
- let total = 0;
1796
- for (const [name, expected] of Object.entries(m.files)) {
1939
+ for (const expected of Object.values(m.files))
1797
1940
  if (!expected || !/^[a-f0-9]{64}$/.test(expected.sha256) || !Number.isSafeInteger(expected.size) || expected.size < 0 || typeof expected.executable !== "boolean")
1798
1941
  throw new RuntimeError("digest_mismatch");
1942
+ let total = 0;
1943
+ await settleAll(Object.entries(m.files).map(([name, expected]) => limit(async () => {
1799
1944
  const path = join5(directory, safePath(name));
1800
- const contents = await this.bytes(path);
1945
+ const contents = process.platform === "win32" ? await this.bytes(path, proven) : await ownedFileBytes(path, expected.executable ? 448 : 384);
1801
1946
  if (hash(contents) !== expected.sha256 || contents.length !== expected.size)
1802
1947
  throw new RuntimeError("digest_mismatch");
1803
- if (process.platform !== "win32" && ((await lstat3(path)).mode & 511) !== (expected.executable ? 448 : 384))
1804
- throw new RuntimeError("permission");
1805
1948
  total += contents.length;
1806
- }
1949
+ })));
1807
1950
  if (total !== m.totalSize)
1808
1951
  throw new RuntimeError("digest_mismatch");
1809
1952
  if (m.signer) {
@@ -2791,6 +2934,8 @@ __export(hookRuntime_exports, {
2791
2934
  GATE_OUTBOX_MAX_AGE_MS: () => GATE_OUTBOX_MAX_AGE_MS,
2792
2935
  GATE_OUTBOX_MAX_EVENTS: () => GATE_OUTBOX_MAX_EVENTS,
2793
2936
  GATE_OUTBOX_STRAY_MS: () => GATE_OUTBOX_STRAY_MS,
2937
+ HOOK_MISSES_HEADER: () => HOOK_MISSES_HEADER,
2938
+ HOOK_MISS_WINDOW_MS: () => HOOK_MISS_WINDOW_MS,
2794
2939
  HOOK_STDIN_MAX_BYTES: () => HOOK_STDIN_MAX_BYTES,
2795
2940
  HOOK_TRACE_ENV: () => HOOK_TRACE_ENV,
2796
2941
  HOOK_TRACE_MAX_BYTES: () => HOOK_TRACE_MAX_BYTES,
@@ -2802,6 +2947,7 @@ __export(hookRuntime_exports, {
2802
2947
  RELEASE_MINISIGN_PUBLIC_KEY: () => RELEASE_MINISIGN_PUBLIC_KEY,
2803
2948
  RuntimeError: () => RuntimeError,
2804
2949
  RuntimeReader: () => RuntimeReader,
2950
+ VERIFY_CONCURRENCY: () => VERIFY_CONCURRENCY,
2805
2951
  aclRecords: () => aclRecords,
2806
2952
  adoptHookConversation: () => adoptHookConversation,
2807
2953
  appendHookTraceLine: () => appendHookTraceLine,
@@ -2818,6 +2964,8 @@ __export(hookRuntime_exports, {
2818
2964
  findProjectIdentityDetailed: () => findProjectIdentityDetailed,
2819
2965
  handoffProjectSetup: () => handoffProjectSetup,
2820
2966
  hash: () => hash,
2967
+ hookMissesHeaders: () => hookMissesHeaders,
2968
+ hookMissesHeadersIfReady: () => hookMissesHeadersIfReady,
2821
2969
  hookTraceDirectory: () => hookTraceDirectory,
2822
2970
  hookTraceEnabled: () => hookTraceEnabled,
2823
2971
  hookTraceFile: () => hookTraceFile,
@@ -2839,6 +2987,7 @@ __export(hookRuntime_exports, {
2839
2987
  setupResponse: () => setupResponse,
2840
2988
  startHookTrace: () => startHookTrace,
2841
2989
  summarizeHookOutput: () => summarizeHookOutput,
2990
+ summarizeRecentHookCalls: () => summarizeRecentHookCalls,
2842
2991
  takeGateEvents: () => takeGateEvents,
2843
2992
  validHookSessionId: () => validHookSessionId,
2844
2993
  verifyMinisign: () => verifyMinisign,
@@ -3043,6 +3192,8 @@ export {
3043
3192
  GATE_OUTBOX_MAX_AGE_MS,
3044
3193
  GATE_OUTBOX_MAX_EVENTS,
3045
3194
  GATE_OUTBOX_STRAY_MS,
3195
+ HOOK_MISSES_HEADER,
3196
+ HOOK_MISS_WINDOW_MS,
3046
3197
  HOOK_STDIN_MAX_BYTES,
3047
3198
  HOOK_TRACE_ENV,
3048
3199
  HOOK_TRACE_MAX_BYTES,
@@ -3054,6 +3205,7 @@ export {
3054
3205
  RELEASE_MINISIGN_PUBLIC_KEY,
3055
3206
  RuntimeError,
3056
3207
  RuntimeReader,
3208
+ VERIFY_CONCURRENCY,
3057
3209
  aclRecords,
3058
3210
  adoptHookConversation,
3059
3211
  appendHookTraceLine,
@@ -3070,6 +3222,8 @@ export {
3070
3222
  findProjectIdentityDetailed,
3071
3223
  handoffProjectSetup,
3072
3224
  hash,
3225
+ hookMissesHeaders,
3226
+ hookMissesHeadersIfReady,
3073
3227
  hookTraceDirectory,
3074
3228
  hookTraceEnabled,
3075
3229
  hookTraceFile,
@@ -3091,6 +3245,7 @@ export {
3091
3245
  setupResponse,
3092
3246
  startHookTrace,
3093
3247
  summarizeHookOutput,
3248
+ summarizeRecentHookCalls,
3094
3249
  takeGateEvents,
3095
3250
  validHookSessionId,
3096
3251
  verifyMinisign,
@@ -446,7 +446,7 @@ var init_secretPatterns = __esm({
446
446
  });
447
447
 
448
448
  // packages/shared/dist/hookTrace.js
449
- var HOOK_TRACE_MAX_BYTES;
449
+ var HOOK_TRACE_MAX_BYTES, HOOK_MISS_WINDOW_MS, HOOK_MISS_TAIL_BYTES;
450
450
  var init_hookTrace = __esm({
451
451
  "packages/shared/dist/hookTrace.js"() {
452
452
  "use strict";
@@ -454,6 +454,8 @@ var init_hookTrace = __esm({
454
454
  init_runtimeSigners();
455
455
  init_secretPatterns();
456
456
  HOOK_TRACE_MAX_BYTES = 2 * 1024 * 1024;
457
+ HOOK_MISS_WINDOW_MS = 30 * 60 * 1e3;
458
+ HOOK_MISS_TAIL_BYTES = 64 * 1024;
457
459
  }
458
460
  });
459
461
 
@@ -467,7 +469,40 @@ function safePath(path) {
467
469
  throw new RuntimeError("permission");
468
470
  return path;
469
471
  }
470
- var RuntimeError, hash, missing, versionName, statIdentity, RuntimeReader;
472
+ function limiter(limit) {
473
+ let active = 0;
474
+ const waiting = [];
475
+ return async (work) => {
476
+ if (active >= limit)
477
+ await new Promise((release) => waiting.push(release));
478
+ active += 1;
479
+ try {
480
+ return await work();
481
+ } finally {
482
+ active -= 1;
483
+ waiting.shift()?.();
484
+ }
485
+ };
486
+ }
487
+ async function ownedFileBytes(path, mode) {
488
+ const fd = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW).catch((error) => {
489
+ throw error.code === "ELOOP" ? new RuntimeError("permission") : error;
490
+ });
491
+ try {
492
+ const stat = await fd.stat();
493
+ if (!stat.isFile() || stat.uid !== process.getuid?.() || (stat.mode & 511) !== mode)
494
+ throw new RuntimeError("permission");
495
+ return await fd.readFile();
496
+ } finally {
497
+ await fd.close();
498
+ }
499
+ }
500
+ async function settleAll(work) {
501
+ const failed = (await Promise.allSettled(work)).find((result) => result.status === "rejected");
502
+ if (failed)
503
+ throw failed.reason;
504
+ }
505
+ var RuntimeError, hash, missing, versionName, VERIFY_CONCURRENCY, statIdentity, RuntimeReader;
471
506
  var init_runtimeReader = __esm({
472
507
  "packages/shared/dist/runtimeReader.js"() {
473
508
  "use strict";
@@ -488,6 +523,7 @@ var init_runtimeReader = __esm({
488
523
  throw new RuntimeError("permission");
489
524
  return v;
490
525
  };
526
+ VERIFY_CONCURRENCY = 16;
491
527
  statIdentity = (stat) => [stat.dev, stat.ino, stat.mode, stat.uid, stat.size, stat.mtimeMs, stat.ctimeMs].join(":");
492
528
  RuntimeReader = class _RuntimeReader {
493
529
  run;
@@ -606,12 +642,23 @@ var init_runtimeReader = __esm({
606
642
  throw new RuntimeError(error instanceof Error && error.message === "acl_permissions" ? "permission" : "acl_unavailable");
607
643
  }
608
644
  }
609
- async inspect(path, directory = false, allowMissing = false, replacing = false) {
645
+ /**
646
+ * `proven` (one verification's own set, POSIX only) holds directories this
647
+ * verification has already inspected in full: their components are not
648
+ * inspected again for every file beneath them, and directories proven here
649
+ * are added to it.
650
+ */
651
+ async inspect(path, directory = false, allowMissing = false, replacing = false, proven) {
610
652
  const absolute = this.guardedPath(path);
611
653
  const windowsPaths = [];
612
- let part = parse(absolute).root;
613
- for (const name of absolute.slice(part.length).split(sep2)) {
654
+ const remembered = process.platform === "win32" ? void 0 : proven;
655
+ const checkedDirectories = [];
656
+ const parent = dirname2(absolute);
657
+ let part = remembered?.has(parent) ? parent : parse(absolute).root;
658
+ for (const name of absolute.slice(part.length).split(sep2).filter(Boolean)) {
614
659
  part = join2(part, name);
660
+ if (part !== absolute && remembered?.has(part))
661
+ continue;
615
662
  const stat = await lstat(part).catch((e) => {
616
663
  if (allowMissing && missing(e))
617
664
  return null;
@@ -652,7 +699,12 @@ var init_runtimeReader = __esm({
652
699
  windowsPaths.push(part);
653
700
  } else if (stat.uid !== process.getuid?.() || (stat.mode & 63) !== 0)
654
701
  throw new RuntimeError("permission");
702
+ if (stat.isDirectory())
703
+ checkedDirectories.push(part);
655
704
  }
705
+ if (remembered)
706
+ for (const checked of checkedDirectories)
707
+ remembered.add(checked);
656
708
  await this.audit(windowsPaths);
657
709
  for (const part2 of windowsPaths) {
658
710
  const verdict = this.windowsAudit.get(part2)?.verdict;
@@ -673,8 +725,8 @@ var init_runtimeReader = __esm({
673
725
  this.windowsAudit.delete(absolute);
674
726
  this.windowsStats.delete(absolute);
675
727
  }
676
- async bytes(path) {
677
- await this.inspect(path);
728
+ async bytes(path, proven) {
729
+ await this.inspect(path, false, false, false, proven);
678
730
  const fd = await open(path, constants.O_RDONLY | (process.platform === "win32" ? 0 : constants.O_NOFOLLOW));
679
731
  try {
680
732
  return await fd.readFile();
@@ -746,36 +798,43 @@ var init_runtimeReader = __esm({
746
798
  if (process.platform === "win32")
747
799
  await this.audit(Object.keys(m.files).map((name) => join2(directory, safePath(name))));
748
800
  const actual = [];
801
+ const proven = /* @__PURE__ */ new Set();
802
+ const limit = limiter(process.platform === "win32" ? 1 : VERIFY_CONCURRENCY);
749
803
  const walk = async (dir, prefix = "") => {
750
- await this.inspect(dir, true);
751
- for (const name of await readdir(dir)) {
752
- const key = prefix + name;
753
- if (!prefix && name === "manifest.json")
754
- continue;
755
- const path = join2(dir, name);
756
- if ((await lstat(path)).isDirectory())
804
+ const entries = await limit(async () => {
805
+ await this.inspect(dir, true, false, false, proven);
806
+ return readdir(dir, { withFileTypes: true });
807
+ });
808
+ await settleAll(entries.map(async (entry) => {
809
+ const key = prefix + entry.name;
810
+ if (!prefix && entry.name === "manifest.json")
811
+ return;
812
+ const path = join2(dir, entry.name);
813
+ if (entry.isDirectory())
757
814
  await walk(path, key + "/");
758
815
  else {
759
- await this.inspect(path);
816
+ if (process.platform === "win32")
817
+ await limit(() => this.inspect(path, false, false, false, proven));
818
+ else if (!entry.isFile())
819
+ throw new RuntimeError("permission");
760
820
  actual.push(key);
761
821
  }
762
- }
822
+ }));
763
823
  };
764
824
  await walk(directory);
765
825
  if (actual.sort().join("\n") !== Object.keys(m.files).sort().join("\n"))
766
826
  throw new RuntimeError("digest_mismatch");
767
- let total = 0;
768
- for (const [name, expected] of Object.entries(m.files)) {
827
+ for (const expected of Object.values(m.files))
769
828
  if (!expected || !/^[a-f0-9]{64}$/.test(expected.sha256) || !Number.isSafeInteger(expected.size) || expected.size < 0 || typeof expected.executable !== "boolean")
770
829
  throw new RuntimeError("digest_mismatch");
830
+ let total = 0;
831
+ await settleAll(Object.entries(m.files).map(([name, expected]) => limit(async () => {
771
832
  const path = join2(directory, safePath(name));
772
- const contents = await this.bytes(path);
833
+ const contents = process.platform === "win32" ? await this.bytes(path, proven) : await ownedFileBytes(path, expected.executable ? 448 : 384);
773
834
  if (hash(contents) !== expected.sha256 || contents.length !== expected.size)
774
835
  throw new RuntimeError("digest_mismatch");
775
- if (process.platform !== "win32" && ((await lstat(path)).mode & 511) !== (expected.executable ? 448 : 384))
776
- throw new RuntimeError("permission");
777
836
  total += contents.length;
778
- }
837
+ })));
779
838
  if (total !== m.totalSize)
780
839
  throw new RuntimeError("digest_mismatch");
781
840
  if (m.signer) {
@@ -43,6 +43,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
43
43
  mod
44
44
  ));
45
45
 
46
+ // packages/shared/dist/secretPatterns.js
47
+ var SECRET_LABEL, SECRET_LABEL_RE, LABELED_VALUE_RE;
48
+ var init_secretPatterns = __esm({
49
+ "packages/shared/dist/secretPatterns.js"() {
50
+ "use strict";
51
+ SECRET_LABEL = String.raw`[\w$-]*(?:api[_-]?key|secret|token|password|credential|auth)|aws_secret_access_key`;
52
+ SECRET_LABEL_RE = new RegExp(`^(?:${SECRET_LABEL}|MYSQL_PWD|SSHPASS)$`, "i");
53
+ LABELED_VALUE_RE = new RegExp(String.raw`(?<![\w$-])((["']?)(?:${SECRET_LABEL})\2\s*[:=]\s*)(?=\S)`, "gi");
54
+ }
55
+ });
56
+
46
57
  // node_modules/ignore/index.js
47
58
  var require_ignore = __commonJS({
48
59
  "node_modules/ignore/index.js"(exports, module2) {
@@ -885,17 +896,6 @@ var require_ignore = __commonJS({
885
896
  }
886
897
  });
887
898
 
888
- // packages/shared/dist/secretPatterns.js
889
- var SECRET_LABEL, SECRET_LABEL_RE, LABELED_VALUE_RE;
890
- var init_secretPatterns = __esm({
891
- "packages/shared/dist/secretPatterns.js"() {
892
- "use strict";
893
- SECRET_LABEL = String.raw`[\w$-]*(?:api[_-]?key|secret|token|password|credential|auth)|aws_secret_access_key`;
894
- SECRET_LABEL_RE = new RegExp(`^(?:${SECRET_LABEL}|MYSQL_PWD|SSHPASS)$`, "i");
895
- LABELED_VALUE_RE = new RegExp(String.raw`(?<![\w$-])((["']?)(?:${SECRET_LABEL})\2\s*[:=]\s*)(?=\S)`, "gi");
896
- }
897
- });
898
-
899
899
  // packages/shared/dist/protectedPaths.js
900
900
  var init_protectedPaths = __esm({
901
901
  "packages/shared/dist/protectedPaths.js"() {
@@ -1016,7 +1016,7 @@ var init_repositoryRoot = __esm({
1016
1016
  });
1017
1017
 
1018
1018
  // packages/shared/dist/hookTrace.js
1019
- var HOOK_TRACE_MAX_BYTES;
1019
+ var HOOK_TRACE_MAX_BYTES, HOOK_MISS_WINDOW_MS, HOOK_MISS_TAIL_BYTES;
1020
1020
  var init_hookTrace = __esm({
1021
1021
  "packages/shared/dist/hookTrace.js"() {
1022
1022
  "use strict";
@@ -1024,6 +1024,8 @@ var init_hookTrace = __esm({
1024
1024
  init_runtimeSigners();
1025
1025
  init_secretPatterns();
1026
1026
  HOOK_TRACE_MAX_BYTES = 2 * 1024 * 1024;
1027
+ HOOK_MISS_WINDOW_MS = 30 * 60 * 1e3;
1028
+ HOOK_MISS_TAIL_BYTES = 64 * 1024;
1027
1029
  }
1028
1030
  });
1029
1031
 
@@ -2736,9 +2738,6 @@ function getMcpInstructions() {
2736
2738
  }
2737
2739
  var MCP_INSTRUCTIONS = getMcpInstructions();
2738
2740
 
2739
- // packages/shared/dist/codeScanner.js
2740
- var import_ignore = __toESM(require_ignore(), 1);
2741
-
2742
2741
  // node_modules/web-tree-sitter/web-tree-sitter.js
2743
2742
  var __defProp2 = Object.defineProperty;
2744
2743
  var __name = (target, value) => __defProp2(target, "name", { value, configurable: true });
@@ -6787,9 +6786,6 @@ import { dirname, extname, join } from "node:path";
6787
6786
  import { fileURLToPath } from "node:url";
6788
6787
  var WASM_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "wasm");
6789
6788
 
6790
- // packages/shared/dist/ast/astChunker.js
6791
- var MAX_AST_PARSE_BYTES = 2 * 1024 * 1024;
6792
-
6793
6789
  // packages/shared/dist/redactCredentials.js
6794
6790
  var REDACTED = "<redacted credential>";
6795
6791
  var MAX_PEM_BODY_LENGTH = 8 * 1024;
@@ -7049,11 +7045,15 @@ var PATTERNS = [
7049
7045
 
7050
7046
  // packages/shared/dist/sourceRedaction.js
7051
7047
  init_secretPatterns();
7048
+ var MAX_SOURCE_REDACTION_BYTES = 10 * 1024 * 1024;
7052
7049
 
7053
- // packages/shared/dist/codeScanner.js
7050
+ // packages/shared/dist/ast/astChunker.js
7051
+ var MAX_AST_PARSE_BYTES = 2 * 1024 * 1024;
7052
+
7053
+ // packages/shared/dist/fileSelection.js
7054
+ var import_ignore = __toESM(require_ignore(), 1);
7054
7055
  init_protectedPaths();
7055
7056
  init_projectIdentityFile();
7056
- var MAX_SCANNED_FILE_BYTES = 10 * 1024 * 1024;
7057
7057
  var BUILT_IN_IGNORE_DIRS = [
7058
7058
  // JS / web
7059
7059
  "node_modules",
@@ -7210,22 +7210,35 @@ var DEFAULT_INCLUDE_EXTENSIONS = [
7210
7210
  ".nix",
7211
7211
  ".bzl"
7212
7212
  ];
7213
+ var BUILT_IN_IGNORE_DIR_SET = new Set(BUILT_IN_IGNORE_DIRS);
7214
+ var DEFAULT_IGNORE_PATTERNS = [
7215
+ ...BUILT_IN_IGNORE_DIRS,
7216
+ ...BUILT_IN_IGNORE_FILE_PATTERNS
7217
+ ];
7218
+
7219
+ // packages/shared/dist/codeScanner.js
7220
+ var MAX_SCANNED_FILE_BYTES = 10 * 1024 * 1024;
7213
7221
  var DEFAULT_OPTIONS = {
7214
7222
  maxChunkSize: 8e3,
7215
7223
  // ~2000 tokens
7216
7224
  minChunkSize: 100,
7217
- ignorePatterns: [...BUILT_IN_IGNORE_DIRS, ...BUILT_IN_IGNORE_FILE_PATTERNS],
7225
+ ignorePatterns: [...DEFAULT_IGNORE_PATTERNS],
7218
7226
  includeExtensions: [...DEFAULT_INCLUDE_EXTENSIONS],
7219
7227
  maxAstParseBytes: MAX_AST_PARSE_BYTES,
7220
7228
  protectedPaths: []
7221
7229
  };
7222
- var BUILT_IN_IGNORE_DIR_SET = new Set(BUILT_IN_IGNORE_DIRS);
7223
7230
 
7224
7231
  // packages/shared/dist/indexJudge.js
7225
7232
  var import_ignore2 = __toESM(require_ignore(), 1);
7226
7233
 
7227
7234
  // packages/shared/dist/index.js
7228
7235
  init_secretPatterns();
7236
+
7237
+ // packages/shared/dist/sourceRedactionPool.js
7238
+ var MB = 1024 * 1024;
7239
+ var LARGE_FILE_BYTES = 1 * MB;
7240
+
7241
+ // packages/shared/dist/index.js
7229
7242
  init_hookTimeouts();
7230
7243
 
7231
7244
  // packages/shared/dist/jitDeliveryAck.js