@westbayberry/dg 2.3.2 → 2.3.4

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 (122) hide show
  1. package/README.md +95 -208
  2. package/dist/agents/copilot-cli.js +7 -2
  3. package/dist/agents/persistence.js +83 -8
  4. package/dist/agents/registry.js +5 -2
  5. package/dist/agents/routing.js +31 -14
  6. package/dist/api/analyze.js +138 -41
  7. package/dist/audit/deep.js +2 -1
  8. package/dist/audit/detectors.js +23 -2
  9. package/dist/audit/rules.js +4 -1
  10. package/dist/audit-ui/export.js +5 -4
  11. package/dist/auth/device-login.js +33 -11
  12. package/dist/auth/login-app.js +17 -12
  13. package/dist/auth/store.js +65 -9
  14. package/dist/bin/dg.js +1 -1
  15. package/dist/commands/audit.js +12 -20
  16. package/dist/commands/{guard-commit.js → commit-guard.js} +12 -12
  17. package/dist/commands/cooldown.js +2 -1
  18. package/dist/commands/decisions.js +8 -7
  19. package/dist/commands/help.js +11 -3
  20. package/dist/commands/licenses.js +17 -8
  21. package/dist/commands/login.js +58 -21
  22. package/dist/commands/router.js +12 -2
  23. package/dist/commands/sbom.js +20 -5
  24. package/dist/commands/scan.js +5 -4
  25. package/dist/commands/service.js +1 -1
  26. package/dist/commands/setup.js +12 -12
  27. package/dist/commands/status.js +4 -4
  28. package/dist/commands/uninstall.js +1 -1
  29. package/dist/commands/update.js +20 -0
  30. package/dist/commands/verify.js +4 -4
  31. package/dist/config/settings.js +81 -12
  32. package/dist/export-ui/ExportDialog.js +1 -1
  33. package/dist/gate/cooldown-request.js +22 -0
  34. package/dist/gate/egress-guard.js +185 -0
  35. package/dist/gate/host-match.js +48 -0
  36. package/dist/gate/verdict-core.js +101 -0
  37. package/dist/gate/verdict-fetch.js +214 -0
  38. package/dist/launcher/agent-check.js +1096 -42
  39. package/dist/launcher/agent-hook-exec.js +8 -1
  40. package/dist/launcher/agent-hook-io.js +5 -3
  41. package/dist/launcher/classify.js +110 -26
  42. package/dist/launcher/env.js +84 -18
  43. package/dist/launcher/install-preflight.js +26 -3
  44. package/dist/launcher/live-install.js +4 -2
  45. package/dist/launcher/manifest-screen.js +88 -7
  46. package/dist/launcher/output-redaction.js +153 -15
  47. package/dist/launcher/preflight-prompt.js +1 -1
  48. package/dist/launcher/resolve-real-binary.js +8 -3
  49. package/dist/launcher/run.js +237 -40
  50. package/dist/origin/artifact-cache.js +55 -0
  51. package/dist/origin/cargo-config.js +12 -0
  52. package/dist/origin/gate-mode.js +7 -0
  53. package/dist/origin/platform-paths.js +14 -0
  54. package/dist/origin/precedence.js +345 -0
  55. package/dist/origin/server.js +611 -0
  56. package/dist/origin/spike-worker.js +35 -0
  57. package/dist/origin/worker.js +116 -0
  58. package/dist/presentation/package-page.js +21 -1
  59. package/dist/presentation/safe-version.js +11 -0
  60. package/dist/presentation/sarif.js +109 -0
  61. package/dist/project/dgfile.js +54 -17
  62. package/dist/project/override-trust.js +0 -0
  63. package/dist/proxy/enforcement.js +27 -7
  64. package/dist/proxy/metadata-map.js +33 -7
  65. package/dist/proxy/preverified.js +0 -3
  66. package/dist/proxy/server.js +104 -446
  67. package/dist/proxy/upstream-proxy.js +23 -4
  68. package/dist/proxy/worker.js +3 -2
  69. package/dist/publish-set/collect.js +6 -0
  70. package/dist/runtime/fatal.js +2 -1
  71. package/dist/runtime/first-run.js +5 -1
  72. package/dist/runtime/node-version.js +51 -0
  73. package/dist/runtime/nudges.js +27 -1
  74. package/dist/sbom/cyclonedx.js +120 -33
  75. package/dist/sbom/graph.js +236 -0
  76. package/dist/sbom/spdx.js +53 -0
  77. package/dist/sbom-ui/SbomApp.js +5 -3
  78. package/dist/sbom-ui/inventory.js +8 -10
  79. package/dist/scan/analyze-worker.js +3 -1
  80. package/dist/scan/collect.js +38 -8
  81. package/dist/scan/command.js +77 -27
  82. package/dist/scan/discovery.js +18 -7
  83. package/dist/scan/installed.js +202 -0
  84. package/dist/scan/manifest-coverage.js +128 -0
  85. package/dist/scan/render.js +125 -40
  86. package/dist/scan/scanner-report.js +92 -22
  87. package/dist/scan/staged.js +68 -15
  88. package/dist/scan/types.js +7 -1
  89. package/dist/scan-ui/LegacyApp.js +3 -3
  90. package/dist/scan-ui/components/InteractiveResultsView.js +17 -14
  91. package/dist/scan-ui/hooks/useScan.js +37 -11
  92. package/dist/scan-ui/launch.js +2 -2
  93. package/dist/scan-ui/logo.js +6 -2
  94. package/dist/scan-ui/shims.js +6 -6
  95. package/dist/scripts/gate.js +53 -35
  96. package/dist/security/csv.js +9 -0
  97. package/dist/security/sanitize.js +11 -2
  98. package/dist/service/state.js +120 -37
  99. package/dist/service/trust-refresh.js +12 -1
  100. package/dist/service/trust-store.js +36 -5
  101. package/dist/service/worker.js +5 -7
  102. package/dist/setup/git-hook.js +2 -2
  103. package/dist/setup/install-method.js +36 -0
  104. package/dist/setup/plan.js +119 -57
  105. package/dist/setup/uninstall-standalone.js +7 -2
  106. package/dist/setup-ui/gate.js +1 -8
  107. package/dist/setup-ui/offer.js +14 -7
  108. package/dist/setup-ui/selector.js +1 -1
  109. package/dist/setup-ui/wizard.js +73 -78
  110. package/dist/standalone/uninstall.mjs +1114 -386
  111. package/dist/state/cleanup-registry.js +14 -3
  112. package/dist/state/cooldown-held.js +36 -13
  113. package/dist/state/locks.js +239 -34
  114. package/dist/state/sessions.js +2 -2
  115. package/dist/util/sh-escape.js +6 -0
  116. package/dist/util/tty-prompt.js +13 -4
  117. package/dist/verify/local.js +60 -10
  118. package/dist/verify/package-check.js +35 -49
  119. package/dist/verify/preflight.js +59 -33
  120. package/dist/verify/render.js +11 -12
  121. package/npm-shrinkwrap.json +714 -213
  122. package/package.json +4 -2
@@ -3,6 +3,20 @@ var __esm = (fn, res) => function __init() {
3
3
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
4
  };
5
5
 
6
+ // dist.next/presentation/theme.js
7
+ var init_theme = __esm({
8
+ "dist.next/presentation/theme.js"() {
9
+ "use strict";
10
+ }
11
+ });
12
+
13
+ // dist.next/util/sh-escape.js
14
+ var init_sh_escape = __esm({
15
+ "dist.next/util/sh-escape.js"() {
16
+ "use strict";
17
+ }
18
+ });
19
+
6
20
  // dist.next/state/store.js
7
21
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
8
22
  import { dirname } from "node:path";
@@ -62,8 +76,9 @@ var init_store = __esm({
62
76
  });
63
77
 
64
78
  // dist.next/state/locks.js
65
- import { closeSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
66
- import { mkdir as mkdir2, open, readFile as readFile2, rename as rename2, rm as rm2, stat } from "node:fs/promises";
79
+ import { randomBytes } from "node:crypto";
80
+ import { closeSync, linkSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
81
+ import { link, mkdir as mkdir2, open, readFile as readFile2, rename as rename2, rm as rm2, stat } from "node:fs/promises";
67
82
  import { join } from "node:path";
68
83
  function isErrno(error, code) {
69
84
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
@@ -75,25 +90,33 @@ async function acquireLock(paths, name, options = {}) {
75
90
  mode: 448
76
91
  });
77
92
  const path = join(paths.locksDir, `${name}.lock`);
78
- await removeStaleLock(path, options);
79
- let handle;
80
- try {
81
- handle = await open(path, "wx", 384);
82
- } catch (error) {
83
- if (isErrno(error, "EEXIST")) {
84
- throw new LockBusyError(path);
85
- }
86
- throw error;
87
- }
88
- const metadata = {
89
- pid: process.pid,
90
- acquiredAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString()
91
- };
93
+ const reclaim = await acquireReclaimLock(path);
92
94
  try {
93
- await handle.writeFile(`${JSON.stringify(metadata)}
95
+ await removeStaleLock(path, options);
96
+ const metadata = {
97
+ pid: process.pid,
98
+ acquiredAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString()
99
+ };
100
+ const tmpPath = `${path}.new-${process.pid}-${++createCounter}`;
101
+ const handle = await open(tmpPath, "wx", 384);
102
+ try {
103
+ await handle.writeFile(`${JSON.stringify(metadata)}
94
104
  `, "utf8");
105
+ } finally {
106
+ await handle.close();
107
+ }
108
+ try {
109
+ await link(tmpPath, path);
110
+ } catch (error) {
111
+ await rm2(tmpPath, { force: true });
112
+ if (isErrno(error, "EEXIST")) {
113
+ throw new LockBusyError(path);
114
+ }
115
+ throw error;
116
+ }
117
+ await rm2(tmpPath, { force: true });
95
118
  } finally {
96
- await handle.close();
119
+ await releaseReclaimLock(path, reclaim);
97
120
  }
98
121
  return {
99
122
  name,
@@ -112,25 +135,33 @@ function acquireLockSync(paths, name, options = {}) {
112
135
  mode: 448
113
136
  });
114
137
  const path = join(paths.locksDir, `${name}.lock`);
115
- removeStaleLockSync(path, options);
116
- let fd;
138
+ const reclaim = acquireReclaimLockSync(path);
117
139
  try {
118
- fd = openSync(path, "wx", 384);
119
- } catch (error) {
120
- if (isErrno(error, "EEXIST")) {
121
- throw new LockBusyError(path);
122
- }
123
- throw error;
124
- }
125
- const metadata = {
126
- pid: process.pid,
127
- acquiredAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString()
128
- };
129
- try {
130
- writeFileSync(fd, `${JSON.stringify(metadata)}
140
+ removeStaleLockSync(path, options);
141
+ const metadata = {
142
+ pid: process.pid,
143
+ acquiredAt: (options.now ?? /* @__PURE__ */ new Date()).toISOString()
144
+ };
145
+ const tmpPath = `${path}.new-${process.pid}-${++createCounter}`;
146
+ const fd = openSync(tmpPath, "wx", 384);
147
+ try {
148
+ writeFileSync(fd, `${JSON.stringify(metadata)}
131
149
  `, "utf8");
150
+ } finally {
151
+ closeSync(fd);
152
+ }
153
+ try {
154
+ linkSync(tmpPath, path);
155
+ } catch (error) {
156
+ rmSync(tmpPath, { force: true });
157
+ if (isErrno(error, "EEXIST")) {
158
+ throw new LockBusyError(path);
159
+ }
160
+ throw error;
161
+ }
162
+ rmSync(tmpPath, { force: true });
132
163
  } finally {
133
- closeSync(fd);
164
+ releaseReclaimLockSync(path, reclaim);
134
165
  }
135
166
  return {
136
167
  name,
@@ -142,6 +173,26 @@ function acquireLockSync(paths, name, options = {}) {
142
173
  }
143
174
  };
144
175
  }
176
+ async function acquireLockWithRetry(paths, name, options = {}) {
177
+ const deadline = Date.now() + (options.timeoutMs ?? 5e3);
178
+ const acquireOptions = {
179
+ ...options.staleMs !== void 0 ? { staleMs: options.staleMs } : {},
180
+ ...options.now !== void 0 ? { now: options.now } : {}
181
+ };
182
+ for (; ; ) {
183
+ try {
184
+ return await acquireLock(paths, name, acquireOptions);
185
+ } catch (error) {
186
+ if (!(error instanceof LockBusyError) || Date.now() + LOCK_RETRY_DELAY_MS > deadline) {
187
+ throw error;
188
+ }
189
+ await new Promise((resolve2) => {
190
+ const timer = setTimeout(resolve2, LOCK_RETRY_DELAY_MS);
191
+ timer.unref?.();
192
+ });
193
+ }
194
+ }
195
+ }
145
196
  function isProcessAlive(pid) {
146
197
  try {
147
198
  process.kill(pid, 0);
@@ -172,6 +223,10 @@ async function removeStaleLock(path, options) {
172
223
  }
173
224
  content = null;
174
225
  }
226
+ if (content !== null && content.trim() === "") {
227
+ await takeoverLock(path);
228
+ return;
229
+ }
175
230
  const holder = content === null ? "unknown" : holderStateFromContent(content);
176
231
  if (holder === "alive") {
177
232
  return;
@@ -208,6 +263,10 @@ function removeStaleLockSync(path, options) {
208
263
  }
209
264
  content = null;
210
265
  }
266
+ if (content !== null && content.trim() === "") {
267
+ takeoverLockSync(path);
268
+ return;
269
+ }
211
270
  const holder = content === null ? "unknown" : holderStateFromContent(content);
212
271
  if (holder === "alive") {
213
272
  return;
@@ -262,17 +321,141 @@ function takeoverLockSync(path) {
262
321
  force: true
263
322
  });
264
323
  }
324
+ function reclaimLockPath(path) {
325
+ return `${path}.takeover`;
326
+ }
327
+ function reclaimToken() {
328
+ return `${process.pid}-${++reclaimCounter}-${randomBytes(8).toString("hex")}`;
329
+ }
330
+ function acquireReclaimLockSync(path) {
331
+ const metaPath = reclaimLockPath(path);
332
+ const token = reclaimToken();
333
+ for (let attempt = 0; attempt < 2; attempt += 1) {
334
+ try {
335
+ const fd = openSync(metaPath, "wx", 384);
336
+ writeFileSync(fd, token, "utf8");
337
+ return { fd, token };
338
+ } catch (error) {
339
+ if (!isErrno(error, "EEXIST")) {
340
+ throw error;
341
+ }
342
+ if (!reclaimStaleMetaLockSync(metaPath)) {
343
+ throw new LockBusyError(path);
344
+ }
345
+ }
346
+ }
347
+ throw new LockBusyError(path);
348
+ }
349
+ function reclaimStaleMetaLockSync(metaPath) {
350
+ let details;
351
+ try {
352
+ details = statSync(metaPath);
353
+ } catch (error) {
354
+ if (isErrno(error, "ENOENT")) {
355
+ return true;
356
+ }
357
+ throw error;
358
+ }
359
+ if (Date.now() - details.mtimeMs < META_LOCK_STALE_MS) {
360
+ return false;
361
+ }
362
+ const stalePath = `${metaPath}.stale-${process.pid}-${++takeoverCounter}`;
363
+ try {
364
+ renameSync(metaPath, stalePath);
365
+ } catch (error) {
366
+ if (isErrno(error, "ENOENT")) {
367
+ return true;
368
+ }
369
+ throw error;
370
+ }
371
+ rmSync(stalePath, { force: true });
372
+ return true;
373
+ }
374
+ function releaseReclaimLockSync(path, reclaim) {
375
+ closeSync(reclaim.fd);
376
+ ownerCheckedRemoveSync(reclaimLockPath(path), reclaim.token);
377
+ }
378
+ function ownerCheckedRemoveSync(metaPath, token) {
379
+ let content;
380
+ try {
381
+ content = readFileSync(metaPath, "utf8");
382
+ } catch {
383
+ return;
384
+ }
385
+ if (content === token) {
386
+ rmSync(metaPath, { force: true });
387
+ }
388
+ }
389
+ async function acquireReclaimLock(path) {
390
+ const metaPath = reclaimLockPath(path);
391
+ const token = reclaimToken();
392
+ for (let attempt = 0; attempt < 2; attempt += 1) {
393
+ try {
394
+ const handle = await open(metaPath, "wx", 384);
395
+ await handle.writeFile(token, "utf8");
396
+ return { handle, token };
397
+ } catch (error) {
398
+ if (!isErrno(error, "EEXIST")) {
399
+ throw error;
400
+ }
401
+ if (!await reclaimStaleMetaLock(metaPath)) {
402
+ throw new LockBusyError(path);
403
+ }
404
+ }
405
+ }
406
+ throw new LockBusyError(path);
407
+ }
408
+ async function reclaimStaleMetaLock(metaPath) {
409
+ let details;
410
+ try {
411
+ details = await stat(metaPath);
412
+ } catch (error) {
413
+ if (isErrno(error, "ENOENT")) {
414
+ return true;
415
+ }
416
+ throw error;
417
+ }
418
+ if (Date.now() - details.mtimeMs < META_LOCK_STALE_MS) {
419
+ return false;
420
+ }
421
+ const stalePath = `${metaPath}.stale-${process.pid}-${++takeoverCounter}`;
422
+ try {
423
+ await rename2(metaPath, stalePath);
424
+ } catch (error) {
425
+ if (isErrno(error, "ENOENT")) {
426
+ return true;
427
+ }
428
+ throw error;
429
+ }
430
+ await rm2(stalePath, { force: true });
431
+ return true;
432
+ }
433
+ async function releaseReclaimLock(path, reclaim) {
434
+ await reclaim.handle.close();
435
+ const metaPath = reclaimLockPath(path);
436
+ let content;
437
+ try {
438
+ content = await readFile2(metaPath, "utf8");
439
+ } catch {
440
+ return;
441
+ }
442
+ if (content === reclaim.token) {
443
+ await rm2(metaPath, { force: true });
444
+ }
445
+ }
265
446
  function assertLockName(name) {
266
447
  if (!/^[a-z][a-z0-9-]{0,63}$/.test(name)) {
267
448
  throw new Error(`Invalid dg lock name: ${name}`);
268
449
  }
269
450
  }
270
- var CLEANUP_REGISTRY_LOCK, takeoverCounter, LockBusyError;
451
+ var CLEANUP_REGISTRY_LOCK, takeoverCounter, createCounter, reclaimCounter, LockBusyError, LOCK_RETRY_DELAY_MS, META_LOCK_STALE_MS;
271
452
  var init_locks = __esm({
272
453
  "dist.next/state/locks.js"() {
273
454
  "use strict";
274
455
  CLEANUP_REGISTRY_LOCK = "cleanup-registry";
275
456
  takeoverCounter = 0;
457
+ createCounter = 0;
458
+ reclaimCounter = 0;
276
459
  LockBusyError = class extends Error {
277
460
  path;
278
461
  constructor(path) {
@@ -281,6 +464,8 @@ var init_locks = __esm({
281
464
  this.name = "LockBusyError";
282
465
  }
283
466
  };
467
+ LOCK_RETRY_DELAY_MS = 25;
468
+ META_LOCK_STALE_MS = 3e3;
284
469
  }
285
470
  });
286
471
 
@@ -321,7 +506,10 @@ async function writeCleanupRegistry(paths, registry) {
321
506
  await writeJsonFileAtomic(paths.cleanupRegistryPath, registry);
322
507
  }
323
508
  async function recordCleanupEntry(paths, entry) {
324
- const lock = await acquireLock(paths, CLEANUP_REGISTRY_LOCK);
509
+ const lock = await acquireLockWithRetry(paths, CLEANUP_REGISTRY_LOCK, {
510
+ staleMs: CLEANUP_REGISTRY_LOCK_STALE_MS,
511
+ timeoutMs: CLEANUP_REGISTRY_LOCK_TIMEOUT_MS
512
+ });
325
513
  try {
326
514
  const { registry } = await loadCleanupRegistry(paths);
327
515
  const nextEntry = {
@@ -341,7 +529,10 @@ async function recordCleanupEntry(paths, entry) {
341
529
  }
342
530
  }
343
531
  async function removeCleanupEntry(paths, target) {
344
- const lock = await acquireLock(paths, CLEANUP_REGISTRY_LOCK);
532
+ const lock = await acquireLockWithRetry(paths, CLEANUP_REGISTRY_LOCK, {
533
+ staleMs: CLEANUP_REGISTRY_LOCK_STALE_MS,
534
+ timeoutMs: CLEANUP_REGISTRY_LOCK_TIMEOUT_MS
535
+ });
345
536
  try {
346
537
  const { registry } = await loadCleanupRegistry(paths);
347
538
  const next = {
@@ -390,11 +581,14 @@ function isEnoent(error) {
390
581
  function sameRegistryTarget(left, right) {
391
582
  return left.kind === right.kind && left.path === right.path && left.sentinel === right.sentinel;
392
583
  }
584
+ var CLEANUP_REGISTRY_LOCK_STALE_MS, CLEANUP_REGISTRY_LOCK_TIMEOUT_MS;
393
585
  var init_cleanup_registry = __esm({
394
586
  "dist.next/state/cleanup-registry.js"() {
395
587
  "use strict";
396
588
  init_store();
397
589
  init_locks();
590
+ CLEANUP_REGISTRY_LOCK_STALE_MS = 30 * 60 * 1e3;
591
+ CLEANUP_REGISTRY_LOCK_TIMEOUT_MS = 5e3;
398
592
  }
399
593
  });
400
594
 
@@ -442,6 +636,7 @@ var init_cooldown_held = __esm({
442
636
  "dist.next/state/cooldown-held.js"() {
443
637
  "use strict";
444
638
  init_json_file();
639
+ init_locks();
445
640
  init_paths();
446
641
  UNKNOWN_ELIGIBILITY_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
447
642
  }
@@ -480,7 +675,7 @@ function findStaleSessionsSync(paths, options) {
480
675
  }
481
676
  throw error;
482
677
  }
483
- if (now - details.mtimeMs >= options.olderThanMs) {
678
+ if (now - details.mtimeMs >= options.olderThanMs && !sessionWorkerAlive(dir)) {
484
679
  stale.push(entry.name);
485
680
  }
486
681
  }
@@ -488,6 +683,16 @@ function findStaleSessionsSync(paths, options) {
488
683
  stale
489
684
  };
490
685
  }
686
+ function sessionWorkerAlive(dir) {
687
+ let raw;
688
+ try {
689
+ raw = readFileSync2(join3(dir, "pid"), "utf8");
690
+ } catch {
691
+ return false;
692
+ }
693
+ const pid = Number.parseInt(raw.trim(), 10);
694
+ return Number.isInteger(pid) && pid > 0 && isProcessAlive(pid);
695
+ }
491
696
  function sweepStaleSessionsSync(paths, options) {
492
697
  const report = findStaleSessionsSync(paths, options);
493
698
  for (const id of report.stale) {
@@ -530,7 +735,7 @@ var init_state = __esm({
530
735
  });
531
736
 
532
737
  // dist.next/config/settings.js
533
- var CONFIG_KEYS, DEFAULT_CONFIG;
738
+ var CONFIG_KEYS, DEFAULT_CONFIG, VENDOR_API_HOST;
534
739
  var init_settings = __esm({
535
740
  "dist.next/config/settings.js"() {
536
741
  "use strict";
@@ -545,8 +750,10 @@ var init_settings = __esm({
545
750
  "policy.scriptHardening",
546
751
  "policy.shimFailClosed",
547
752
  "policy.strictEgress",
753
+ "policy.allowNonVendorApiHost",
754
+ "policy.provenanceDowngrade",
548
755
  "scriptGate.mode",
549
- "scriptGate.observe",
756
+ "scriptGate.persistObservations",
550
757
  "gitHook.onWarn",
551
758
  "gitHook.onIncomplete",
552
759
  "cooldown.age",
@@ -571,11 +778,13 @@ var init_settings = __esm({
571
778
  allowForceOverride: true,
572
779
  scriptHardening: false,
573
780
  shimFailClosed: false,
574
- strictEgress: false
781
+ strictEgress: false,
782
+ allowNonVendorApiHost: false,
783
+ provenanceDowngrade: "off"
575
784
  },
576
785
  scriptGate: {
577
786
  mode: "observe",
578
- observe: false
787
+ persistObservations: false
579
788
  },
580
789
  gitHook: {
581
790
  onWarn: "prompt",
@@ -593,182 +802,401 @@ var init_settings = __esm({
593
802
  upload: false
594
803
  }
595
804
  });
805
+ VENDOR_API_HOST = new URL(DEFAULT_CONFIG.api.baseUrl).hostname;
596
806
  }
597
807
  });
598
808
 
599
- // dist.next/launcher/resolve-real-binary.js
600
- var init_resolve_real_binary = __esm({
601
- "dist.next/launcher/resolve-real-binary.js"() {
809
+ // dist.next/security/sanitize.js
810
+ import { stripVTControlCharacters } from "node:util";
811
+ function sanitizeLine(s) {
812
+ return stripVTControlCharacters(s).replace(/[\r\n]+/g, " ").replace(CTRL_ALL, "").replace(INVISIBLE_GLOBAL, "");
813
+ }
814
+ var CTRL_ALL, INVISIBLE_UNICODE_RE, INVISIBLE_GLOBAL;
815
+ var init_sanitize = __esm({
816
+ "dist.next/security/sanitize.js"() {
602
817
  "use strict";
603
- init_state();
818
+ CTRL_ALL = /[\x00-\x1F\x7F-\x9F]/g;
819
+ INVISIBLE_UNICODE_RE = /[\u200B-\u200F\u2060-\u2064\u202A-\u202E\u2066-\u2069\u061C\uFEFF]/u;
820
+ INVISIBLE_GLOBAL = new RegExp(INVISIBLE_UNICODE_RE.source, "gu");
604
821
  }
605
822
  });
606
823
 
607
- // dist.next/launcher/spawn-invocation.js
608
- var init_spawn_invocation = __esm({
609
- "dist.next/launcher/spawn-invocation.js"() {
824
+ // dist.next/auth/env-token.js
825
+ var init_env_token = __esm({
826
+ "dist.next/auth/env-token.js"() {
610
827
  "use strict";
611
828
  }
612
829
  });
613
830
 
614
- // dist.next/service/trust-store.js
615
- var init_trust_store = __esm({
616
- "dist.next/service/trust-store.js"() {
831
+ // dist.next/auth/store.js
832
+ import { chmodSync, existsSync, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, renameSync as renameSync3, rmSync as rmSync3, statSync as statSync3, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
833
+ import { basename, dirname as dirname2, join as join4 } from "node:path";
834
+ function authPath(paths) {
835
+ return join4(paths.configDir, "auth.json");
836
+ }
837
+ function clearAuthState(env = process.env) {
838
+ const path = authPath(resolveDgPaths(env));
839
+ sweepOrphanAuthTemps(path);
840
+ if (!existsSync(path)) {
841
+ return false;
842
+ }
843
+ unlinkSync(path);
844
+ return true;
845
+ }
846
+ function sweepOrphanAuthTemps(path) {
847
+ const dir = dirname2(path);
848
+ const base = basename(path);
849
+ const pattern = new RegExp(`^${base.replace(/[.]/g, "\\.")}\\.\\d+\\.[0-9a-f-]{36}\\.tmp$`);
850
+ try {
851
+ for (const entry of readdirSync2(dir)) {
852
+ if (pattern.test(entry)) {
853
+ try {
854
+ unlinkSync(join4(dir, entry));
855
+ } catch {
856
+ }
857
+ }
858
+ }
859
+ } catch {
860
+ }
861
+ }
862
+ var init_store2 = __esm({
863
+ "dist.next/auth/store.js"() {
617
864
  "use strict";
618
- init_json_file();
865
+ init_settings();
866
+ init_state();
867
+ init_sanitize();
868
+ init_env_token();
619
869
  }
620
870
  });
621
871
 
622
- // dist.next/service/trust-refresh.js
623
- var init_trust_refresh = __esm({
624
- "dist.next/service/trust-refresh.js"() {
872
+ // dist.next/commands/version.js
873
+ var init_version = __esm({
874
+ "dist.next/commands/version.js"() {
625
875
  "use strict";
626
- init_trust_store();
627
876
  }
628
877
  });
629
878
 
630
- // dist.next/service/state.js
631
- var SERVICE_LOCK_STALE_MS;
632
- var init_state2 = __esm({
633
- "dist.next/service/state.js"() {
879
+ // dist.next/api/analyze.js
880
+ var BATCH_CONCURRENCY, MAX_STREAM_LINE_BYTES;
881
+ var init_analyze = __esm({
882
+ "dist.next/api/analyze.js"() {
634
883
  "use strict";
884
+ init_store2();
885
+ init_env_token();
635
886
  init_settings();
636
- init_trust_store();
637
- init_trust_refresh();
638
- init_state();
639
- SERVICE_LOCK_STALE_MS = 30 * 60 * 1e3;
887
+ init_sanitize();
888
+ init_version();
889
+ BATCH_CONCURRENCY = Math.max(1, Number(process.env.DG_ANALYZE_CONCURRENCY) || 4);
890
+ MAX_STREAM_LINE_BYTES = 32 * 1024 * 1024;
640
891
  }
641
892
  });
642
893
 
643
- // dist.next/setup/uninstall-standalone.js
644
- import { rmSync as rmSync5 } from "node:fs";
645
- import { join as join11 } from "node:path";
646
-
647
- // dist.next/setup/plan.js
648
- import { accessSync, constants, copyFileSync, existsSync as existsSync2, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync4, realpathSync, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
649
- import { basename, delimiter, dirname as dirname3, join as join10, resolve, sep } from "node:path";
650
- import { randomBytes as randomBytes2 } from "node:crypto";
651
-
652
- // dist.next/agents/registry.js
653
- init_state();
654
-
655
- // dist.next/agents/claude-code.js
656
- import { join as join4 } from "node:path";
657
-
658
- // dist.next/auth/store.js
659
- init_settings();
660
- init_state();
661
-
662
- // dist.next/api/analyze.js
663
- init_settings();
664
-
665
- // dist.next/security/sanitize.js
666
- import { stripVTControlCharacters } from "node:util";
667
- var CTRL_ALL = /[\x00-\x1F\x7F-\x9F]/g;
668
- function sanitizeLine(s) {
669
- return stripVTControlCharacters(s).replace(/[\r\n]+/g, " ").replace(CTRL_ALL, "");
670
- }
671
-
672
- // dist.next/api/analyze.js
673
- init_state();
674
- var BATCH_CONCURRENCY = Math.max(1, Number(process.env.DG_ANALYZE_CONCURRENCY) || 4);
675
-
676
894
  // dist.next/setup/optional-support.js
677
- var OPTIONAL_SUPPORT_GATES = Object.freeze([
678
- {
679
- id: "windows",
680
- label: "Windows support",
681
- kind: "platform",
682
- status: "unclaimed",
683
- message: "Windows support is gated in this release; use dg prefix mode from a supported POSIX shell or run 'dg --help' for supported commands"
684
- },
685
- {
686
- id: "python-hook",
687
- label: "Python .pth hook",
688
- kind: "hook",
689
- status: "unclaimed",
690
- message: "Python .pth hook support is gated in this release; use 'dg pip ...', 'dg pipx ...', 'dg uv ...', or 'dg uvx ...' prefix mode instead"
691
- },
692
- {
693
- id: "bun",
694
- label: "Bun and bunx",
695
- kind: "package-manager",
696
- status: "unclaimed",
697
- standaloneCommand: true,
698
- message: "Bun support is gated in this release; use 'dg npm ...', 'dg pnpm ...', or 'dg yarn ...' for supported JavaScript installs"
699
- },
700
- {
701
- id: "yarn-berry",
702
- label: "Yarn Berry",
703
- kind: "package-manager",
704
- status: "unclaimed",
705
- standaloneCommand: false,
706
- message: "Yarn Berry support is gated in this release; use Yarn classic through 'dg yarn ...' or another supported prefix manager"
707
- },
708
- {
709
- id: "conda",
710
- label: "Conda",
711
- kind: "package-manager",
712
- status: "unclaimed",
713
- standaloneCommand: true,
714
- message: "Conda support is gated in this release; use 'dg pip ...' or 'dg uv ...' for supported Python package installs"
715
- },
716
- {
717
- id: "mamba",
718
- label: "Mamba",
719
- kind: "package-manager",
720
- status: "unclaimed",
721
- standaloneCommand: true,
722
- message: "Mamba support is gated in this release; use 'dg pip ...' or 'dg uv ...' for supported Python package installs"
723
- }
724
- ]);
725
895
  function optionalPackageManagerNames() {
726
896
  return OPTIONAL_SUPPORT_GATES.filter((gate) => gate.kind === "package-manager" && gate.standaloneCommand === true).map((gate) => gate.id);
727
897
  }
898
+ var OPTIONAL_SUPPORT_GATES;
899
+ var init_optional_support = __esm({
900
+ "dist.next/setup/optional-support.js"() {
901
+ "use strict";
902
+ OPTIONAL_SUPPORT_GATES = Object.freeze([
903
+ {
904
+ id: "windows",
905
+ label: "Windows support",
906
+ kind: "platform",
907
+ status: "unclaimed",
908
+ message: "Windows support is gated in this release; use dg prefix mode from a supported POSIX shell or run 'dg --help' for supported commands"
909
+ },
910
+ {
911
+ id: "python-hook",
912
+ label: "Python .pth hook",
913
+ kind: "hook",
914
+ status: "unclaimed",
915
+ message: "Python .pth hook support is gated in this release; use 'dg pip ...', 'dg pipx ...', 'dg uv ...', or 'dg uvx ...' prefix mode instead"
916
+ },
917
+ {
918
+ id: "bun",
919
+ label: "Bun and bunx",
920
+ kind: "package-manager",
921
+ status: "unclaimed",
922
+ standaloneCommand: true,
923
+ message: "Bun support is gated in this release; use 'dg npm ...', 'dg pnpm ...', or 'dg yarn ...' for supported JavaScript installs"
924
+ },
925
+ {
926
+ id: "yarn-berry",
927
+ label: "Yarn Berry",
928
+ kind: "package-manager",
929
+ status: "unclaimed",
930
+ standaloneCommand: false,
931
+ message: "Yarn Berry support is gated in this release; use Yarn classic through 'dg yarn ...' or another supported prefix manager"
932
+ },
933
+ {
934
+ id: "conda",
935
+ label: "Conda",
936
+ kind: "package-manager",
937
+ status: "unclaimed",
938
+ standaloneCommand: true,
939
+ message: "Conda support is gated in this release; use 'dg pip ...' or 'dg uv ...' for supported Python package installs"
940
+ },
941
+ {
942
+ id: "mamba",
943
+ label: "Mamba",
944
+ kind: "package-manager",
945
+ status: "unclaimed",
946
+ standaloneCommand: true,
947
+ message: "Mamba support is gated in this release; use 'dg pip ...' or 'dg uv ...' for supported Python package installs"
948
+ }
949
+ ]);
950
+ }
951
+ });
728
952
 
729
953
  // dist.next/launcher/classify.js
730
- var gatedManagers = optionalPackageManagerNames();
954
+ var gatedManagers;
955
+ var init_classify = __esm({
956
+ "dist.next/launcher/classify.js"() {
957
+ "use strict";
958
+ init_optional_support();
959
+ gatedManagers = optionalPackageManagerNames();
960
+ }
961
+ });
731
962
 
732
- // dist.next/verify/preflight.js
733
- init_settings();
963
+ // dist.next/presentation/provenance.js
964
+ var init_provenance = __esm({
965
+ "dist.next/presentation/provenance.js"() {
966
+ "use strict";
967
+ }
968
+ });
969
+
970
+ // dist.next/presentation/safe-version.js
971
+ var init_safe_version = __esm({
972
+ "dist.next/presentation/safe-version.js"() {
973
+ "use strict";
974
+ }
975
+ });
976
+
977
+ // dist.next/presentation/package-page.js
978
+ var init_package_page = __esm({
979
+ "dist.next/presentation/package-page.js"() {
980
+ "use strict";
981
+ }
982
+ });
983
+
984
+ // dist.next/presentation/mode.js
985
+ var init_mode = __esm({
986
+ "dist.next/presentation/mode.js"() {
987
+ "use strict";
988
+ }
989
+ });
734
990
 
735
991
  // dist.next/audit/events.js
736
- init_state();
992
+ var init_events = __esm({
993
+ "dist.next/audit/events.js"() {
994
+ "use strict";
995
+ init_state();
996
+ }
997
+ });
737
998
 
738
999
  // dist.next/policy/evaluate.js
739
- init_settings();
1000
+ var init_evaluate = __esm({
1001
+ "dist.next/policy/evaluate.js"() {
1002
+ "use strict";
1003
+ init_events();
1004
+ init_settings();
1005
+ }
1006
+ });
740
1007
 
741
1008
  // dist.next/verify/preflight.js
742
- var MAX_LOCKFILE_BYTES = 64 * 1024 * 1024;
1009
+ var MAX_LOCKFILE_BYTES;
1010
+ var init_preflight = __esm({
1011
+ "dist.next/verify/preflight.js"() {
1012
+ "use strict";
1013
+ init_settings();
1014
+ init_evaluate();
1015
+ MAX_LOCKFILE_BYTES = 64 * 1024 * 1024;
1016
+ }
1017
+ });
743
1018
 
744
- // dist.next/policy/cooldown.js
745
- init_settings();
1019
+ // dist.next/commands/types.js
1020
+ var init_types = __esm({
1021
+ "dist.next/commands/types.js"() {
1022
+ "use strict";
1023
+ }
1024
+ });
1025
+
1026
+ // dist.next/verify/package-check.js
1027
+ var init_package_check = __esm({
1028
+ "dist.next/verify/package-check.js"() {
1029
+ "use strict";
1030
+ init_analyze();
1031
+ init_theme();
1032
+ init_provenance();
1033
+ init_safe_version();
1034
+ init_package_page();
1035
+ init_mode();
1036
+ init_preflight();
1037
+ init_store2();
1038
+ init_types();
1039
+ }
1040
+ });
1041
+
1042
+ // dist.next/decisions/apply.js
1043
+ var init_apply = __esm({
1044
+ "dist.next/decisions/apply.js"() {
1045
+ "use strict";
1046
+ }
1047
+ });
1048
+
1049
+ // dist.next/launcher/resolve-real-binary.js
1050
+ var init_resolve_real_binary = __esm({
1051
+ "dist.next/launcher/resolve-real-binary.js"() {
1052
+ "use strict";
1053
+ init_state();
1054
+ }
1055
+ });
1056
+
1057
+ // dist.next/launcher/spawn-invocation.js
1058
+ var init_spawn_invocation = __esm({
1059
+ "dist.next/launcher/spawn-invocation.js"() {
1060
+ "use strict";
1061
+ }
1062
+ });
746
1063
 
747
1064
  // dist.next/util/external-tool.js
748
- init_resolve_real_binary();
749
- init_spawn_invocation();
1065
+ var init_external_tool = __esm({
1066
+ "dist.next/util/external-tool.js"() {
1067
+ "use strict";
1068
+ init_resolve_real_binary();
1069
+ init_spawn_invocation();
1070
+ }
1071
+ });
750
1072
 
751
1073
  // dist.next/util/git.js
752
- var DEFAULT_MAX_BUFFER = 256 * 1024 * 1024;
1074
+ var DEFAULT_MAX_BUFFER;
1075
+ var init_git = __esm({
1076
+ "dist.next/util/git.js"() {
1077
+ "use strict";
1078
+ init_external_tool();
1079
+ DEFAULT_MAX_BUFFER = 256 * 1024 * 1024;
1080
+ }
1081
+ });
753
1082
 
754
- // dist.next/project/dgfile.js
755
- init_json_file();
756
- init_state();
1083
+ // dist.next/policy/pypi-name.js
1084
+ var init_pypi_name = __esm({
1085
+ "dist.next/policy/pypi-name.js"() {
1086
+ "use strict";
1087
+ }
1088
+ });
757
1089
 
758
1090
  // dist.next/project/override-trust.js
759
- init_state();
1091
+ var init_override_trust = __esm({
1092
+ "dist.next/project/override-trust.js"() {
1093
+ "use strict";
1094
+ init_state();
1095
+ init_settings();
1096
+ }
1097
+ });
760
1098
 
761
- // dist.next/launcher/install-preflight.js
762
- init_settings();
1099
+ // dist.next/project/dgfile.js
1100
+ var init_dgfile = __esm({
1101
+ "dist.next/project/dgfile.js"() {
1102
+ "use strict";
1103
+ init_git();
1104
+ init_json_file();
1105
+ init_pypi_name();
1106
+ init_state();
1107
+ init_override_trust();
1108
+ init_sanitize();
1109
+ }
1110
+ });
1111
+
1112
+ // dist.next/policy/cooldown.js
1113
+ var init_cooldown = __esm({
1114
+ "dist.next/policy/cooldown.js"() {
1115
+ "use strict";
1116
+ init_settings();
1117
+ init_dgfile();
1118
+ init_pypi_name();
1119
+ }
1120
+ });
1121
+
1122
+ // dist.next/install-ui/prompt.js
1123
+ var init_prompt = __esm({
1124
+ "dist.next/install-ui/prompt.js"() {
1125
+ "use strict";
1126
+ }
1127
+ });
1128
+
1129
+ // dist.next/util/tty-prompt.js
1130
+ var init_tty_prompt = __esm({
1131
+ "dist.next/util/tty-prompt.js"() {
1132
+ "use strict";
1133
+ }
1134
+ });
763
1135
 
764
1136
  // dist.next/decisions/remember-prompt.js
765
- init_settings();
1137
+ var init_remember_prompt = __esm({
1138
+ "dist.next/decisions/remember-prompt.js"() {
1139
+ "use strict";
1140
+ init_events();
1141
+ init_settings();
1142
+ init_prompt();
1143
+ init_dgfile();
1144
+ init_tty_prompt();
1145
+ init_apply();
1146
+ }
1147
+ });
1148
+
1149
+ // dist.next/launcher/pip-report.js
1150
+ var init_pip_report = __esm({
1151
+ "dist.next/launcher/pip-report.js"() {
1152
+ "use strict";
1153
+ }
1154
+ });
1155
+
1156
+ // dist.next/proxy/auth.js
1157
+ var init_auth = __esm({
1158
+ "dist.next/proxy/auth.js"() {
1159
+ "use strict";
1160
+ }
1161
+ });
1162
+
1163
+ // dist.next/launcher/env.js
1164
+ var init_env = __esm({
1165
+ "dist.next/launcher/env.js"() {
1166
+ "use strict";
1167
+ init_auth();
1168
+ }
1169
+ });
766
1170
 
767
1171
  // dist.next/launcher/install-preflight.js
768
- init_spawn_invocation();
1172
+ var MAX_PIP_REPORT_BYTES;
1173
+ var init_install_preflight = __esm({
1174
+ "dist.next/launcher/install-preflight.js"() {
1175
+ "use strict";
1176
+ init_analyze();
1177
+ init_settings();
1178
+ init_override_trust();
1179
+ init_apply();
1180
+ init_remember_prompt();
1181
+ init_provenance();
1182
+ init_prompt();
1183
+ init_cooldown();
1184
+ init_dgfile();
1185
+ init_pip_report();
1186
+ init_spawn_invocation();
1187
+ init_env();
1188
+ MAX_PIP_REPORT_BYTES = 16 * 1024 * 1024;
1189
+ }
1190
+ });
769
1191
 
770
1192
  // dist.next/launcher/manifest-screen.js
771
- var MAX_MANIFEST_BYTES = 4 * 1024 * 1024;
1193
+ var MAX_MANIFEST_BYTES;
1194
+ var init_manifest_screen = __esm({
1195
+ "dist.next/launcher/manifest-screen.js"() {
1196
+ "use strict";
1197
+ MAX_MANIFEST_BYTES = 4 * 1024 * 1024;
1198
+ }
1199
+ });
772
1200
 
773
1201
  // dist.next/launcher/agent-check.js
774
1202
  function formatScreenedNote(screened) {
@@ -779,19 +1207,32 @@ function formatScreenedNote(screened) {
779
1207
  const noun = screened.length === 1 ? "package" : "packages";
780
1208
  return sanitizeLine(`dg pre-screened the requested ${noun}: ${items} \u2014 no known issues (dependencies are screened at install time)`);
781
1209
  }
1210
+ var SHELL_EXEC, HEREDOC_EXEC_HEADS;
1211
+ var init_agent_check = __esm({
1212
+ "dist.next/launcher/agent-check.js"() {
1213
+ "use strict";
1214
+ init_analyze();
1215
+ init_classify();
1216
+ init_package_check();
1217
+ init_apply();
1218
+ init_cooldown();
1219
+ init_install_preflight();
1220
+ init_sanitize();
1221
+ init_manifest_screen();
1222
+ SHELL_EXEC = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "ash", "ksh", "mksh", "fish", "script"]);
1223
+ HEREDOC_EXEC_HEADS = /* @__PURE__ */ new Set([...SHELL_EXEC, "eval", "source", "."]);
1224
+ }
1225
+ });
782
1226
 
783
1227
  // dist.next/agents/persistence.js
784
- init_state();
785
- import { existsSync, lstatSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync2 } from "node:fs";
1228
+ import { existsSync as existsSync2, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync4, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "node:fs";
786
1229
  import { spawnSync } from "node:child_process";
787
- import { dirname as dirname2 } from "node:path";
788
- import { randomBytes } from "node:crypto";
789
- var LEGACY_AGENT_HOOK_SENTINEL = "dg-agent-hook-v1";
1230
+ import { homedir as homedir2 } from "node:os";
1231
+ import { dirname as dirname3, sep } from "node:path";
1232
+ import { randomBytes as randomBytes2 } from "node:crypto";
790
1233
  function agentHookSentinel(agent) {
791
1234
  return `${LEGACY_AGENT_HOOK_SENTINEL}:${agent}`;
792
1235
  }
793
- var AgentHookError = class extends Error {
794
- };
795
1236
  function dirExists(path) {
796
1237
  try {
797
1238
  return lstatSync(path).isDirectory();
@@ -816,17 +1257,38 @@ function assertSafeNode(path, role) {
816
1257
  throw new AgentHookError(`${path} (${role}) is world-writable; refusing to write to it. Tighten its permissions, then retry.`);
817
1258
  }
818
1259
  }
1260
+ function assertNoSymlinkBelowHome(target) {
1261
+ const home = homedir2();
1262
+ if (!home) {
1263
+ return;
1264
+ }
1265
+ let dir = dirname3(target);
1266
+ let prev = "";
1267
+ while (dir !== prev && dir.startsWith(`${home}${sep}`)) {
1268
+ try {
1269
+ if (lstatSync(dir).isSymbolicLink()) {
1270
+ throw new AgentHookError(`${dir} is a symlink; refusing to create or write through it. Replace it with a real directory, then retry.`);
1271
+ }
1272
+ } catch (error) {
1273
+ if (error instanceof AgentHookError) {
1274
+ throw error;
1275
+ }
1276
+ }
1277
+ prev = dir;
1278
+ dir = dirname3(dir);
1279
+ }
1280
+ }
819
1281
  function assertSafeWriteTarget(path) {
820
- assertSafeNode(dirname2(path), "directory");
1282
+ assertSafeNode(dirname3(path), "directory");
821
1283
  assertSafeNode(path, "file");
822
1284
  }
823
1285
  function readSettings(path) {
824
- if (!existsSync(path)) {
1286
+ if (!existsSync2(path)) {
825
1287
  return { settings: {}, existed: false };
826
1288
  }
827
1289
  let parsed;
828
1290
  try {
829
- parsed = JSON.parse(readFileSync3(path, "utf8"));
1291
+ parsed = JSON.parse(readFileSync4(path, "utf8"));
830
1292
  } catch {
831
1293
  throw new AgentHookError(`${path} is not valid JSON; refusing to modify it. Fix or remove it, then retry.`);
832
1294
  }
@@ -835,19 +1297,23 @@ function readSettings(path) {
835
1297
  }
836
1298
  return { settings: parsed, existed: true };
837
1299
  }
838
- function writeSettingsAtomic(path, settings) {
839
- mkdirSync3(dirname2(path), { recursive: true });
1300
+ function writeFileAtomicSafe(path, content) {
1301
+ assertNoSymlinkBelowHome(path);
1302
+ mkdirSync4(dirname3(path), { recursive: true });
840
1303
  assertSafeWriteTarget(path);
841
- const tmp = `${path}.dg-${randomBytes(6).toString("hex")}.tmp`;
842
- writeFileSync2(tmp, `${JSON.stringify(settings, null, 2)}
843
- `, { mode: 384, flag: "wx" });
1304
+ const tmp = `${path}.dg-${randomBytes2(6).toString("hex")}.tmp`;
1305
+ writeFileSync3(tmp, content, { mode: 384, flag: "wx" });
844
1306
  try {
845
- renameSync3(tmp, path);
1307
+ renameSync4(tmp, path);
846
1308
  } catch (error) {
847
- rmSync3(tmp, { force: true });
1309
+ rmSync4(tmp, { force: true });
848
1310
  throw error;
849
1311
  }
850
1312
  }
1313
+ function writeSettingsAtomic(path, settings) {
1314
+ writeFileAtomicSafe(path, `${JSON.stringify(settings, null, 2)}
1315
+ `);
1316
+ }
851
1317
  async function wasCreatedByDg(ctx) {
852
1318
  try {
853
1319
  const reg = await readCleanupRegistry(ctx.paths);
@@ -875,13 +1341,16 @@ async function removeHookEntries(ctx, legacySentinels) {
875
1341
  await removeCleanupEntry(ctx.paths, { kind: "agent-hook", path: ctx.settingsPath, sentinel });
876
1342
  }
877
1343
  }
878
- function findHookCommand(node, signature) {
1344
+ function findHookCommand(node, signature, depth = 0) {
1345
+ if (depth > 512) {
1346
+ return null;
1347
+ }
879
1348
  if (typeof node === "string") {
880
1349
  return node.includes(signature) ? node : null;
881
1350
  }
882
1351
  if (Array.isArray(node)) {
883
1352
  for (const value of node) {
884
- const found = findHookCommand(value, signature);
1353
+ const found = findHookCommand(value, signature, depth + 1);
885
1354
  if (found) {
886
1355
  return found;
887
1356
  }
@@ -890,7 +1359,7 @@ function findHookCommand(node, signature) {
890
1359
  }
891
1360
  if (node && typeof node === "object") {
892
1361
  for (const value of Object.values(node)) {
893
- const found = findHookCommand(value, signature);
1362
+ const found = findHookCommand(value, signature, depth + 1);
894
1363
  if (found) {
895
1364
  return found;
896
1365
  }
@@ -899,13 +1368,45 @@ function findHookCommand(node, signature) {
899
1368
  }
900
1369
  return null;
901
1370
  }
1371
+ function shellHeadTokens(head) {
1372
+ const tokens = [];
1373
+ const s = head.trim();
1374
+ let i = 0;
1375
+ while (i < s.length) {
1376
+ while (i < s.length && /\s/.test(s[i] ?? "")) {
1377
+ i += 1;
1378
+ }
1379
+ if (i >= s.length) {
1380
+ break;
1381
+ }
1382
+ const quote = s[i];
1383
+ if (quote === '"' || quote === "'") {
1384
+ const end = s.indexOf(quote, i + 1);
1385
+ if (end < 0) {
1386
+ tokens.push(s.slice(i + 1));
1387
+ break;
1388
+ }
1389
+ const inner = s.slice(i + 1, end);
1390
+ tokens.push(quote === '"' ? inner.replace(/\\(["\\$`])/g, "$1") : inner);
1391
+ i = end + 1;
1392
+ } else {
1393
+ let j = i;
1394
+ while (j < s.length && !/\s/.test(s[j] ?? "")) {
1395
+ j += 1;
1396
+ }
1397
+ tokens.push(s.slice(i, j));
1398
+ i = j;
1399
+ }
1400
+ }
1401
+ return tokens;
1402
+ }
902
1403
  function hookResolvesCheck(settings, agent) {
903
1404
  const command = findHookCommand(settings, `hook-exec ${agent}`);
904
1405
  if (!command) {
905
1406
  return null;
906
1407
  }
907
1408
  const head = command.split(/\s+hook-exec\s+/)[0] ?? command;
908
- const broken = head.split(/\s+/).filter((token) => token.startsWith("/")).filter((token) => !existsSync(token));
1409
+ const broken = shellHeadTokens(head).filter((token) => token.startsWith("/")).filter((token) => !existsSync2(token));
909
1410
  return {
910
1411
  name: "hook command resolves",
911
1412
  ok: broken.length === 0,
@@ -924,7 +1425,7 @@ function mergedJsonHook(config) {
924
1425
  },
925
1426
  async remove(ctx) {
926
1427
  let removed = false;
927
- if (existsSync(ctx.settingsPath)) {
1428
+ if (existsSync2(ctx.settingsPath)) {
928
1429
  let settings = null;
929
1430
  try {
930
1431
  settings = readSettings(ctx.settingsPath).settings;
@@ -936,7 +1437,7 @@ function mergedJsonHook(config) {
936
1437
  if (result.changed) {
937
1438
  removed = true;
938
1439
  if (result.empty && await wasCreatedByDg(ctx)) {
939
- rmSync3(ctx.settingsPath, { force: true });
1440
+ rmSync4(ctx.settingsPath, { force: true });
940
1441
  } else {
941
1442
  writeSettingsAtomic(ctx.settingsPath, result.settings);
942
1443
  }
@@ -948,7 +1449,7 @@ function mergedJsonHook(config) {
948
1449
  },
949
1450
  verify(ctx) {
950
1451
  const checks = [];
951
- const present = existsSync(ctx.settingsPath);
1452
+ const present = existsSync2(ctx.settingsPath);
952
1453
  checks.push({ name: "settings file", ok: present, detail: present ? ctx.settingsPath : `${ctx.settingsPath} (absent)` });
953
1454
  if (!present) {
954
1455
  return checks;
@@ -971,13 +1472,13 @@ function mergedJsonHook(config) {
971
1472
  return checks;
972
1473
  },
973
1474
  reverseEntry(entry, removed, missing, warnings) {
974
- if (!existsSync(entry.path)) {
1475
+ if (!existsSync2(entry.path)) {
975
1476
  missing.push(entry.path);
976
1477
  return;
977
1478
  }
978
1479
  let settings;
979
1480
  try {
980
- const parsed = JSON.parse(readFileSync3(entry.path, "utf8"));
1481
+ const parsed = JSON.parse(readFileSync4(entry.path, "utf8"));
981
1482
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
982
1483
  warnings.push(`${entry.path}: not a JSON object; left untouched`);
983
1484
  return;
@@ -993,7 +1494,7 @@ function mergedJsonHook(config) {
993
1494
  return;
994
1495
  }
995
1496
  if (result.empty && entry.original === "dg-created") {
996
- rmSync3(entry.path, { force: true });
1497
+ rmSync4(entry.path, { force: true });
997
1498
  } else {
998
1499
  try {
999
1500
  writeSettingsAtomic(entry.path, result.settings);
@@ -1010,7 +1511,7 @@ function ownedJsonHook(config) {
1010
1511
  const sentinel = agentHookSentinel(config.agent);
1011
1512
  const ownsFile = (path) => {
1012
1513
  try {
1013
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
1514
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
1014
1515
  return parsed?.dgSentinel === sentinel;
1015
1516
  } catch {
1016
1517
  return false;
@@ -1019,7 +1520,7 @@ function ownedJsonHook(config) {
1019
1520
  return {
1020
1521
  isInstalledCheckName: config.checkName,
1021
1522
  async apply(ctx) {
1022
- const existed = existsSync(ctx.settingsPath);
1523
+ const existed = existsSync2(ctx.settingsPath);
1023
1524
  if (existed && !ownsFile(ctx.settingsPath)) {
1024
1525
  throw new AgentHookError(`${ctx.settingsPath} already exists and was not written by dg; refusing to overwrite it. Merge the output of 'dg agents --print ${ctx.agent}' yourself, or remove the file and retry.`);
1025
1526
  }
@@ -1029,8 +1530,8 @@ function ownedJsonHook(config) {
1029
1530
  },
1030
1531
  async remove(ctx) {
1031
1532
  let removed = false;
1032
- if (existsSync(ctx.settingsPath) && ownsFile(ctx.settingsPath)) {
1033
- rmSync3(ctx.settingsPath, { force: true });
1533
+ if (existsSync2(ctx.settingsPath) && ownsFile(ctx.settingsPath)) {
1534
+ rmSync4(ctx.settingsPath, { force: true });
1034
1535
  removed = true;
1035
1536
  }
1036
1537
  await removeHookEntries(ctx, []);
@@ -1038,7 +1539,7 @@ function ownedJsonHook(config) {
1038
1539
  },
1039
1540
  verify(ctx) {
1040
1541
  const checks = [];
1041
- const present = existsSync(ctx.settingsPath);
1542
+ const present = existsSync2(ctx.settingsPath);
1042
1543
  checks.push({ name: "hook file", ok: present, detail: present ? ctx.settingsPath : `${ctx.settingsPath} (absent)` });
1043
1544
  if (!present) {
1044
1545
  return checks;
@@ -1047,7 +1548,7 @@ function ownedJsonHook(config) {
1047
1548
  checks.push({ name: config.checkName, ok: installed, detail: installed ? "installed" : "present but not dg-owned" });
1048
1549
  if (installed) {
1049
1550
  try {
1050
- const settings = JSON.parse(readFileSync3(ctx.settingsPath, "utf8"));
1551
+ const settings = JSON.parse(readFileSync4(ctx.settingsPath, "utf8"));
1051
1552
  const resolves = hookResolvesCheck(settings, ctx.agent);
1052
1553
  if (resolves) {
1053
1554
  checks.push(resolves);
@@ -1058,7 +1559,7 @@ function ownedJsonHook(config) {
1058
1559
  return checks;
1059
1560
  },
1060
1561
  reverseEntry(entry, removed, missing, warnings) {
1061
- if (!existsSync(entry.path)) {
1562
+ if (!existsSync2(entry.path)) {
1062
1563
  missing.push(entry.path);
1063
1564
  return;
1064
1565
  }
@@ -1066,7 +1567,7 @@ function ownedJsonHook(config) {
1066
1567
  warnings.push(`${entry.path}: not dg-owned; left untouched`);
1067
1568
  return;
1068
1569
  }
1069
- rmSync3(entry.path, { force: true });
1570
+ rmSync4(entry.path, { force: true });
1070
1571
  removed.push(entry.path);
1071
1572
  }
1072
1573
  };
@@ -1110,11 +1611,21 @@ function probeMinCliVersion(binary, minVersion, label, deps) {
1110
1611
  }
1111
1612
  return { supported: true, detail: `${label} ${found.join(".")}` };
1112
1613
  }
1614
+ var LEGACY_AGENT_HOOK_SENTINEL, AgentHookError;
1615
+ var init_persistence = __esm({
1616
+ "dist.next/agents/persistence.js"() {
1617
+ "use strict";
1618
+ init_state();
1619
+ LEGACY_AGENT_HOOK_SENTINEL = "dg-agent-hook-v1";
1620
+ AgentHookError = class extends Error {
1621
+ };
1622
+ }
1623
+ });
1113
1624
 
1114
1625
  // dist.next/agents/claude-code.js
1115
- var SIGNATURE = "hook-exec claude-code";
1626
+ import { join as join5 } from "node:path";
1116
1627
  function configPath(home) {
1117
- return join4(home, ".claude", "settings.json");
1628
+ return join5(home, ".claude", "settings.json");
1118
1629
  }
1119
1630
  function isDgGroup(group) {
1120
1631
  if (typeof group !== "object" || group === null) {
@@ -1198,33 +1709,42 @@ function emitDecision(verdict) {
1198
1709
  exitCode: 0
1199
1710
  };
1200
1711
  }
1201
- var claudeCodeIntegration = {
1202
- id: "claude-code",
1203
- label: "Claude Code",
1204
- kind: "merged-json",
1205
- maturity: "verified",
1206
- minVersion: null,
1207
- configPath,
1208
- detect: (home) => dirExists(join4(home, ".claude")),
1209
- probeHookSupport: (home) => ({
1210
- supported: true,
1211
- detail: dirExists(join4(home, ".claude")) ? "Claude Code settings directory found" : "settings hooks are supported by every Claude Code version; ~/.claude will be created"
1212
- }),
1213
- parseInput,
1214
- emitDecision,
1215
- ...mergedJsonHook({
1216
- checkName: "dg PreToolUse hook",
1217
- legacySentinels: [LEGACY_AGENT_HOOK_SENTINEL],
1218
- insert: insertDgHook,
1219
- remove: removeDgHook,
1220
- isInstalled: hasDgHook
1221
- })
1222
- };
1712
+ var SIGNATURE, claudeCodeIntegration;
1713
+ var init_claude_code = __esm({
1714
+ "dist.next/agents/claude-code.js"() {
1715
+ "use strict";
1716
+ init_agent_check();
1717
+ init_persistence();
1718
+ SIGNATURE = "hook-exec claude-code";
1719
+ claudeCodeIntegration = {
1720
+ id: "claude-code",
1721
+ label: "Claude Code",
1722
+ kind: "merged-json",
1723
+ maturity: "verified",
1724
+ minVersion: null,
1725
+ configPath,
1726
+ detect: (home) => dirExists(join5(home, ".claude")),
1727
+ probeHookSupport: (home) => ({
1728
+ supported: true,
1729
+ detail: dirExists(join5(home, ".claude")) ? "Claude Code settings directory found" : "settings hooks are supported by every Claude Code version; ~/.claude will be created"
1730
+ }),
1731
+ parseInput,
1732
+ emitDecision,
1733
+ ...mergedJsonHook({
1734
+ checkName: "dg PreToolUse hook",
1735
+ legacySentinels: [LEGACY_AGENT_HOOK_SENTINEL],
1736
+ insert: insertDgHook,
1737
+ remove: removeDgHook,
1738
+ isInstalled: hasDgHook
1739
+ })
1740
+ };
1741
+ }
1742
+ });
1223
1743
 
1224
1744
  // dist.next/agents/codex.js
1225
- import { join as join5 } from "node:path";
1745
+ import { join as join6 } from "node:path";
1226
1746
  function configPath2(home) {
1227
- return join5(home, ".codex", "hooks.json");
1747
+ return join6(home, ".codex", "hooks.json");
1228
1748
  }
1229
1749
  function parseInput2(stdin) {
1230
1750
  try {
@@ -1262,35 +1782,41 @@ function renderHookFile(dgCommand) {
1262
1782
  };
1263
1783
  }
1264
1784
  function probeHookSupport(home, deps) {
1265
- if (!dirExists(join5(home, ".codex"))) {
1785
+ if (!dirExists(join6(home, ".codex"))) {
1266
1786
  return { supported: false, detail: "~/.codex not found (is Codex CLI installed?)" };
1267
1787
  }
1268
1788
  return probeMinCliVersion("codex", "0.124.0", "Codex CLI", deps);
1269
1789
  }
1270
- var codexIntegration = {
1271
- id: "codex",
1272
- label: "Codex CLI",
1273
- kind: "owned-json",
1274
- maturity: "verified",
1275
- minVersion: "0.124.0",
1276
- postInstallNote: "Codex asks to trust new hooks: approve the dg hook when Codex prompts on its next start.",
1277
- configPath: configPath2,
1278
- detect: (home) => dirExists(join5(home, ".codex")),
1279
- probeHookSupport,
1280
- parseInput: parseInput2,
1281
- emitDecision: emitDecision2,
1282
- ...ownedJsonHook({
1283
- agent: "codex",
1284
- checkName: "dg PreToolUse hook",
1285
- render: renderHookFile
1286
- })
1287
- };
1790
+ var codexIntegration;
1791
+ var init_codex = __esm({
1792
+ "dist.next/agents/codex.js"() {
1793
+ "use strict";
1794
+ init_persistence();
1795
+ codexIntegration = {
1796
+ id: "codex",
1797
+ label: "Codex CLI",
1798
+ kind: "owned-json",
1799
+ maturity: "verified",
1800
+ minVersion: "0.124.0",
1801
+ postInstallNote: "Codex asks to trust new hooks: approve the dg hook when Codex prompts on its next start.",
1802
+ configPath: configPath2,
1803
+ detect: (home) => dirExists(join6(home, ".codex")),
1804
+ probeHookSupport,
1805
+ parseInput: parseInput2,
1806
+ emitDecision: emitDecision2,
1807
+ ...ownedJsonHook({
1808
+ agent: "codex",
1809
+ checkName: "dg PreToolUse hook",
1810
+ render: renderHookFile
1811
+ })
1812
+ };
1813
+ }
1814
+ });
1288
1815
 
1289
1816
  // dist.next/agents/copilot-cli.js
1290
- import { join as join6 } from "node:path";
1291
- var SIGNATURE2 = "hook-exec copilot-cli";
1817
+ import { join as join7 } from "node:path";
1292
1818
  function configPath3(home) {
1293
- return join6(home, ".copilot", "settings.json");
1819
+ return join7(home, ".copilot", "settings.json");
1294
1820
  }
1295
1821
  function isDgEntry(entry) {
1296
1822
  return typeof entry === "object" && entry !== null && typeof entry.command === "string" && entry.command.includes(SIGNATURE2);
@@ -1359,44 +1885,53 @@ function emitDecision3(verdict) {
1359
1885
  if (verdict.decision === "allow") {
1360
1886
  return { stdout: "{}", exitCode: 0 };
1361
1887
  }
1888
+ const suffix = verdict.decision === "ask" ? " (dg flagged this for human review \u2014 not auto-approved)" : "";
1889
+ const reason = `${verdict.reason ?? "Dependency Guardian firewall"}${suffix}`;
1362
1890
  return {
1363
1891
  stdout: JSON.stringify({
1364
- permissionDecision: verdict.decision,
1365
- ...verdict.reason ? { permissionDecisionReason: verdict.reason } : {}
1892
+ permissionDecision: "deny",
1893
+ permissionDecisionReason: reason
1366
1894
  }),
1367
1895
  exitCode: 0
1368
1896
  };
1369
1897
  }
1370
1898
  function probeHookSupport2(home, deps) {
1371
- if (!dirExists(join6(home, ".copilot"))) {
1899
+ if (!dirExists(join7(home, ".copilot"))) {
1372
1900
  return { supported: false, detail: "~/.copilot not found (is GitHub Copilot CLI installed?)" };
1373
1901
  }
1374
1902
  return probeMinCliVersion("copilot", "1.0.61", "GitHub Copilot CLI", deps);
1375
1903
  }
1376
- var copilotCliIntegration = {
1377
- id: "copilot-cli",
1378
- label: "GitHub Copilot CLI",
1379
- kind: "merged-json",
1380
- maturity: "verified",
1381
- minVersion: "1.0.61",
1382
- configPath: configPath3,
1383
- detect: (home) => dirExists(join6(home, ".copilot")),
1384
- probeHookSupport: probeHookSupport2,
1385
- parseInput: parseInput3,
1386
- emitDecision: emitDecision3,
1387
- ...mergedJsonHook({
1388
- checkName: "dg preToolUse hook",
1389
- insert: insertDgHook2,
1390
- remove: removeDgHook2,
1391
- isInstalled: hasDgHook2
1392
- })
1393
- };
1904
+ var SIGNATURE2, copilotCliIntegration;
1905
+ var init_copilot_cli = __esm({
1906
+ "dist.next/agents/copilot-cli.js"() {
1907
+ "use strict";
1908
+ init_persistence();
1909
+ SIGNATURE2 = "hook-exec copilot-cli";
1910
+ copilotCliIntegration = {
1911
+ id: "copilot-cli",
1912
+ label: "GitHub Copilot CLI",
1913
+ kind: "merged-json",
1914
+ maturity: "verified",
1915
+ minVersion: "1.0.61",
1916
+ configPath: configPath3,
1917
+ detect: (home) => dirExists(join7(home, ".copilot")),
1918
+ probeHookSupport: probeHookSupport2,
1919
+ parseInput: parseInput3,
1920
+ emitDecision: emitDecision3,
1921
+ ...mergedJsonHook({
1922
+ checkName: "dg preToolUse hook",
1923
+ insert: insertDgHook2,
1924
+ remove: removeDgHook2,
1925
+ isInstalled: hasDgHook2
1926
+ })
1927
+ };
1928
+ }
1929
+ });
1394
1930
 
1395
1931
  // dist.next/agents/cursor.js
1396
- import { join as join7 } from "node:path";
1397
- var SIGNATURE3 = "hook-exec cursor";
1932
+ import { join as join8 } from "node:path";
1398
1933
  function configPath4(home) {
1399
- return join7(home, ".cursor", "hooks.json");
1934
+ return join8(home, ".cursor", "hooks.json");
1400
1935
  }
1401
1936
  function isDgEntry2(entry) {
1402
1937
  return typeof entry === "object" && entry !== null && typeof entry.command === "string" && entry.command.includes(SIGNATURE3);
@@ -1474,7 +2009,7 @@ function emitDecision4(verdict) {
1474
2009
  };
1475
2010
  }
1476
2011
  function probeHookSupport3(home) {
1477
- if (!dirExists(join7(home, ".cursor"))) {
2012
+ if (!dirExists(join8(home, ".cursor"))) {
1478
2013
  return { supported: false, detail: "~/.cursor not found (is Cursor installed?)" };
1479
2014
  }
1480
2015
  try {
@@ -1484,30 +2019,38 @@ function probeHookSupport3(home) {
1484
2019
  }
1485
2020
  return { supported: true, detail: "requires Cursor 1.7+; dg cannot read your Cursor version from disk" };
1486
2021
  }
1487
- var cursorIntegration = {
1488
- id: "cursor",
1489
- label: "Cursor",
1490
- kind: "merged-json",
1491
- maturity: "verified",
1492
- minVersion: "1.7",
1493
- configPath: configPath4,
1494
- detect: (home) => dirExists(join7(home, ".cursor")),
1495
- probeHookSupport: probeHookSupport3,
1496
- parseInput: parseInput4,
1497
- emitDecision: emitDecision4,
1498
- ...mergedJsonHook({
1499
- checkName: "dg beforeShellExecution hook",
1500
- insert: insertHook,
1501
- remove: removeHook,
1502
- isInstalled: hasDgHook3
1503
- })
1504
- };
2022
+ var SIGNATURE3, cursorIntegration;
2023
+ var init_cursor = __esm({
2024
+ "dist.next/agents/cursor.js"() {
2025
+ "use strict";
2026
+ init_agent_check();
2027
+ init_persistence();
2028
+ SIGNATURE3 = "hook-exec cursor";
2029
+ cursorIntegration = {
2030
+ id: "cursor",
2031
+ label: "Cursor",
2032
+ kind: "merged-json",
2033
+ maturity: "verified",
2034
+ minVersion: "1.7",
2035
+ configPath: configPath4,
2036
+ detect: (home) => dirExists(join8(home, ".cursor")),
2037
+ probeHookSupport: probeHookSupport3,
2038
+ parseInput: parseInput4,
2039
+ emitDecision: emitDecision4,
2040
+ ...mergedJsonHook({
2041
+ checkName: "dg beforeShellExecution hook",
2042
+ insert: insertHook,
2043
+ remove: removeHook,
2044
+ isInstalled: hasDgHook3
2045
+ })
2046
+ };
2047
+ }
2048
+ });
1505
2049
 
1506
2050
  // dist.next/agents/gemini.js
1507
- import { join as join8 } from "node:path";
1508
- var SIGNATURE4 = "hook-exec gemini";
2051
+ import { join as join9 } from "node:path";
1509
2052
  function configPath5(home) {
1510
- return join8(home, ".gemini", "settings.json");
2053
+ return join9(home, ".gemini", "settings.json");
1511
2054
  }
1512
2055
  function isDgGroup2(group) {
1513
2056
  if (typeof group !== "object" || group === null) {
@@ -1578,35 +2121,42 @@ function emitDecision5(verdict) {
1578
2121
  };
1579
2122
  }
1580
2123
  function probeHookSupport4(home, deps) {
1581
- if (!dirExists(join8(home, ".gemini"))) {
2124
+ if (!dirExists(join9(home, ".gemini"))) {
1582
2125
  return { supported: false, detail: "~/.gemini not found (is Gemini CLI installed?)" };
1583
2126
  }
1584
2127
  return probeMinCliVersion("gemini", "0.26.0", "Gemini CLI", deps);
1585
2128
  }
1586
- var geminiIntegration = {
1587
- id: "gemini",
1588
- label: "Gemini CLI",
1589
- kind: "merged-json",
1590
- maturity: "verified",
1591
- minVersion: "0.26.0",
1592
- configPath: configPath5,
1593
- detect: (home) => dirExists(join8(home, ".gemini")),
1594
- probeHookSupport: probeHookSupport4,
1595
- parseInput: parseInput5,
1596
- emitDecision: emitDecision5,
1597
- ...mergedJsonHook({
1598
- checkName: "dg BeforeTool hook",
1599
- insert: insertHook2,
1600
- remove: removeHook2,
1601
- isInstalled: hasDgHook4
1602
- })
1603
- };
2129
+ var SIGNATURE4, geminiIntegration;
2130
+ var init_gemini = __esm({
2131
+ "dist.next/agents/gemini.js"() {
2132
+ "use strict";
2133
+ init_persistence();
2134
+ SIGNATURE4 = "hook-exec gemini";
2135
+ geminiIntegration = {
2136
+ id: "gemini",
2137
+ label: "Gemini CLI",
2138
+ kind: "merged-json",
2139
+ maturity: "verified",
2140
+ minVersion: "0.26.0",
2141
+ configPath: configPath5,
2142
+ detect: (home) => dirExists(join9(home, ".gemini")),
2143
+ probeHookSupport: probeHookSupport4,
2144
+ parseInput: parseInput5,
2145
+ emitDecision: emitDecision5,
2146
+ ...mergedJsonHook({
2147
+ checkName: "dg BeforeTool hook",
2148
+ insert: insertHook2,
2149
+ remove: removeHook2,
2150
+ isInstalled: hasDgHook4
2151
+ })
2152
+ };
2153
+ }
2154
+ });
1604
2155
 
1605
2156
  // dist.next/agents/windsurf.js
1606
- import { join as join9 } from "node:path";
1607
- var SIGNATURE5 = "hook-exec windsurf";
2157
+ import { join as join10 } from "node:path";
1608
2158
  function configPath6(home) {
1609
- return join9(home, ".codeium", "windsurf", "hooks.json");
2159
+ return join10(home, ".codeium", "windsurf", "hooks.json");
1610
2160
  }
1611
2161
  function isDgEntry3(entry) {
1612
2162
  return typeof entry === "object" && entry !== null && typeof entry.command === "string" && entry.command.includes(SIGNATURE5);
@@ -1667,43 +2217,48 @@ function emitDecision6(verdict) {
1667
2217
  `, exitCode: 2 };
1668
2218
  }
1669
2219
  function probeHookSupport5(home) {
1670
- if (!dirExists(join9(home, ".codeium", "windsurf"))) {
2220
+ if (!dirExists(join10(home, ".codeium", "windsurf"))) {
1671
2221
  return { supported: false, detail: "~/.codeium/windsurf not found (is Windsurf installed?)" };
1672
2222
  }
1673
2223
  return { supported: true, detail: "Windsurf config directory found; dg cannot read the app version from disk" };
1674
2224
  }
1675
- var windsurfIntegration = {
1676
- id: "windsurf",
1677
- label: "Windsurf",
1678
- kind: "merged-json",
1679
- maturity: "unverified",
1680
- minVersion: null,
1681
- configPath: configPath6,
1682
- detect: (home) => dirExists(join9(home, ".codeium", "windsurf")),
1683
- probeHookSupport: probeHookSupport5,
1684
- parseInput: parseInput6,
1685
- emitDecision: emitDecision6,
1686
- ...mergedJsonHook({
1687
- checkName: "dg pre_run_command hook",
1688
- insert: insertHook3,
1689
- remove: removeHook3,
1690
- isInstalled: hasDgHook5
1691
- })
1692
- };
2225
+ var SIGNATURE5, windsurfIntegration;
2226
+ var init_windsurf = __esm({
2227
+ "dist.next/agents/windsurf.js"() {
2228
+ "use strict";
2229
+ init_persistence();
2230
+ SIGNATURE5 = "hook-exec windsurf";
2231
+ windsurfIntegration = {
2232
+ id: "windsurf",
2233
+ label: "Windsurf",
2234
+ kind: "merged-json",
2235
+ maturity: "unverified",
2236
+ minVersion: null,
2237
+ configPath: configPath6,
2238
+ detect: (home) => dirExists(join10(home, ".codeium", "windsurf")),
2239
+ probeHookSupport: probeHookSupport5,
2240
+ parseInput: parseInput6,
2241
+ emitDecision: emitDecision6,
2242
+ ...mergedJsonHook({
2243
+ checkName: "dg pre_run_command hook",
2244
+ insert: insertHook3,
2245
+ remove: removeHook3,
2246
+ isInstalled: hasDgHook5
2247
+ })
2248
+ };
2249
+ }
2250
+ });
1693
2251
 
1694
2252
  // dist.next/agents/registry.js
1695
- var AGENTS = {
1696
- "claude-code": claudeCodeIntegration,
1697
- codex: codexIntegration,
1698
- cursor: cursorIntegration,
1699
- "copilot-cli": copilotCliIntegration,
1700
- gemini: geminiIntegration,
1701
- windsurf: windsurfIntegration
1702
- };
1703
- var AGENT_IDS = Object.keys(AGENTS);
1704
2253
  function isAgentId(value) {
1705
2254
  return value in AGENTS;
1706
2255
  }
2256
+ function getAgent(id) {
2257
+ return AGENTS[id];
2258
+ }
2259
+ function agentLabel(id) {
2260
+ return isAgentId(id) ? AGENTS[id].label : id;
2261
+ }
1707
2262
  function agentFromSentinel(sentinel) {
1708
2263
  if (!sentinel || sentinel === LEGACY_AGENT_HOOK_SENTINEL) {
1709
2264
  return "claude-code";
@@ -1722,6 +2277,151 @@ function reverseAgentHookEntry(entry, removed, missing, warnings) {
1722
2277
  }
1723
2278
  AGENTS[agent].reverseEntry(entry, removed, missing, warnings);
1724
2279
  }
2280
+ var AGENTS, AGENT_IDS;
2281
+ var init_registry = __esm({
2282
+ "dist.next/agents/registry.js"() {
2283
+ "use strict";
2284
+ init_sh_escape();
2285
+ init_state();
2286
+ init_claude_code();
2287
+ init_codex();
2288
+ init_copilot_cli();
2289
+ init_cursor();
2290
+ init_gemini();
2291
+ init_persistence();
2292
+ init_windsurf();
2293
+ AGENTS = {
2294
+ "claude-code": claudeCodeIntegration,
2295
+ codex: codexIntegration,
2296
+ cursor: cursorIntegration,
2297
+ "copilot-cli": copilotCliIntegration,
2298
+ gemini: geminiIntegration,
2299
+ windsurf: windsurfIntegration
2300
+ };
2301
+ AGENT_IDS = Object.keys(AGENTS);
2302
+ }
2303
+ });
2304
+
2305
+ // dist.next/service/trust-store.js
2306
+ var init_trust_store = __esm({
2307
+ "dist.next/service/trust-store.js"() {
2308
+ "use strict";
2309
+ init_json_file();
2310
+ }
2311
+ });
2312
+
2313
+ // dist.next/service/trust-refresh.js
2314
+ var init_trust_refresh = __esm({
2315
+ "dist.next/service/trust-refresh.js"() {
2316
+ "use strict";
2317
+ init_trust_store();
2318
+ }
2319
+ });
2320
+
2321
+ // dist.next/service/state.js
2322
+ var SERVICE_LOCK_STALE_MS;
2323
+ var init_state2 = __esm({
2324
+ "dist.next/service/state.js"() {
2325
+ "use strict";
2326
+ init_settings();
2327
+ init_trust_store();
2328
+ init_trust_refresh();
2329
+ init_state();
2330
+ SERVICE_LOCK_STALE_MS = 30 * 60 * 1e3;
2331
+ }
2332
+ });
2333
+
2334
+ // dist.next/setup/uninstall-standalone.js
2335
+ import { rmSync as rmSync7 } from "node:fs";
2336
+ import { join as join13 } from "node:path";
2337
+
2338
+ // dist.next/setup/plan.js
2339
+ import { accessSync, constants, copyFileSync, existsSync as existsSync4, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync6, realpathSync, renameSync as renameSync5, rmSync as rmSync6, statSync as statSync4, writeFileSync as writeFileSync5 } from "node:fs";
2340
+ import { basename as basename2, delimiter, dirname as dirname5, join as join12, resolve, sep as sep2 } from "node:path";
2341
+ import { randomBytes as randomBytes3 } from "node:crypto";
2342
+ init_theme();
2343
+ init_registry();
2344
+
2345
+ // dist.next/agents/routing.js
2346
+ init_env();
2347
+ init_state2();
2348
+ init_state();
2349
+ init_persistence();
2350
+ init_registry();
2351
+ import { existsSync as existsSync3, mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "node:fs";
2352
+ import { dirname as dirname4, join as join11 } from "node:path";
2353
+ var CODEX_BEGIN = "# >>> dg routing >>>";
2354
+ var CODEX_END = "# <<< dg routing <<<";
2355
+ function backupPath(agent, env) {
2356
+ return join11(resolveDgPaths(env).stateDir, `routing-${agent}.json`);
2357
+ }
2358
+ function escapeRegex(value) {
2359
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2360
+ }
2361
+ function stripCodexBlock(content) {
2362
+ const block = new RegExp(`\\n?${escapeRegex(CODEX_BEGIN)}[\\s\\S]*?${escapeRegex(CODEX_END)}\\n?`, "g");
2363
+ return content.replace(block, "\n").replace(/\n{3,}/g, "\n\n");
2364
+ }
2365
+ function loadBackupPrior(backup) {
2366
+ if (!existsSync3(backup)) {
2367
+ return {};
2368
+ }
2369
+ try {
2370
+ return JSON.parse(readFileSync5(backup, "utf8")).prior ?? {};
2371
+ } catch {
2372
+ return {};
2373
+ }
2374
+ }
2375
+ function removeClaudeRouting(settingsPath, backup) {
2376
+ if (!existsSync3(backup)) {
2377
+ return;
2378
+ }
2379
+ const prior = loadBackupPrior(backup);
2380
+ if (existsSync3(settingsPath)) {
2381
+ const { settings } = readSettings(settingsPath);
2382
+ const envObj = typeof settings.env === "object" && settings.env !== null ? { ...settings.env } : {};
2383
+ for (const [k, v] of Object.entries(prior)) {
2384
+ if (v === null) {
2385
+ delete envObj[k];
2386
+ } else {
2387
+ envObj[k] = v;
2388
+ }
2389
+ }
2390
+ if (Object.keys(envObj).length === 0) {
2391
+ delete settings.env;
2392
+ } else {
2393
+ settings.env = envObj;
2394
+ }
2395
+ writeSettingsAtomic(settingsPath, settings);
2396
+ }
2397
+ rmSync5(backup, { force: true });
2398
+ }
2399
+ function removeCodexRouting(configPath7) {
2400
+ if (!existsSync3(configPath7)) {
2401
+ return;
2402
+ }
2403
+ writeFileAtomicSafe(configPath7, stripCodexBlock(readFileSync5(configPath7, "utf8")));
2404
+ }
2405
+ function codexConfigPath(home) {
2406
+ return join11(home, ".codex", "config.toml");
2407
+ }
2408
+ function removeAgentRouting(agent, home, env = process.env) {
2409
+ if (agent === "codex") {
2410
+ removeCodexRouting(codexConfigPath(home));
2411
+ return;
2412
+ }
2413
+ removeClaudeRouting(getAgent(agent).configPath(home), backupPath(agent, env));
2414
+ }
2415
+ function routingInstalled(agent, home, env = process.env) {
2416
+ if (agent === "codex") {
2417
+ const p = codexConfigPath(home);
2418
+ return existsSync3(p) && readFileSync5(p, "utf8").includes(CODEX_BEGIN);
2419
+ }
2420
+ return existsSync3(backupPath(agent, env));
2421
+ }
2422
+
2423
+ // dist.next/setup/plan.js
2424
+ init_sh_escape();
1725
2425
 
1726
2426
  // dist.next/agents/gate-posture.js
1727
2427
  init_state2();
@@ -1737,9 +2437,22 @@ var MINIMUM_NODE = Object.freeze({
1737
2437
  });
1738
2438
 
1739
2439
  // dist.next/setup/plan.js
2440
+ init_version();
2441
+
2442
+ // dist.next/commands/update.js
2443
+ init_external_tool();
2444
+ init_state();
2445
+ init_types();
2446
+ init_version();
2447
+
2448
+ // dist.next/setup/plan.js
2449
+ init_store2();
1740
2450
  init_settings();
2451
+ init_cooldown();
1741
2452
  init_resolve_real_binary();
2453
+ init_classify();
1742
2454
  init_state2();
2455
+ init_optional_support();
1743
2456
  var SHIM_COMMANDS = Object.freeze(["npm", "npx", "pnpm", "pnpx", "yarn", "pip", "pip3", "pipx", "uv", "uvx", "cargo"]);
1744
2457
  var SHIM_SENTINEL = "dg-shim-v1";
1745
2458
  var RC_SENTINEL = "dg-shell-rc-v1";
@@ -1750,7 +2463,7 @@ var RC_END = "# <<< dg setup <<<";
1750
2463
  var LEGACY_RC_MARKERS = [
1751
2464
  { begin: "# >>> dg-managed >>>", end: "# <<< dg-managed <<<" }
1752
2465
  ];
1753
- var LEGACY_RC_CANDIDATES = [".zshrc", ".bashrc", ".bash_profile", ".profile", join10(".config", "fish", "config.fish")];
2466
+ var LEGACY_RC_CANDIDATES = [".zshrc", ".bashrc", ".bash_profile", ".profile", join12(".config", "fish", "config.fish")];
1754
2467
  var LEGACY_PYTHON_HOOK_PY = "dg_pip_hook.py";
1755
2468
  var LEGACY_PYTHON_HOOK_PTH = "dg_pip_hook.pth";
1756
2469
  var LEGACY_PYTHON_HOOK_MARKER = "Dependency Guardian pip-install interceptor";
@@ -1760,8 +2473,8 @@ var SETUP_UNINSTALL_LOCK_STALE_MS = 30 * 60 * 1e3;
1760
2473
  var STALE_SESSION_OLDER_THAN_MS = 24 * 60 * 60 * 1e3;
1761
2474
  function uninstallSetup(options) {
1762
2475
  const paths = resolveDgPaths(options.env ?? process.env);
1763
- const hadCacheDirBeforeLock = existsSync2(paths.cacheDir);
1764
- const hadStateDirBeforeLock = existsSync2(paths.stateDir);
2476
+ const hadCacheDirBeforeLock = existsSync4(paths.cacheDir);
2477
+ const hadStateDirBeforeLock = existsSync4(paths.stateDir);
1765
2478
  const lock = acquireLockSync(paths, SETUP_UNINSTALL_LOCK, {
1766
2479
  staleMs: SETUP_UNINSTALL_LOCK_STALE_MS
1767
2480
  });
@@ -1792,6 +2505,17 @@ function uninstallSetup(options) {
1792
2505
  }
1793
2506
  sweepLegacyRcBlocks(paths.homeDir, removed, warnings);
1794
2507
  sweepLegacyPythonHooks(paths.homeDir, removed, warnings);
2508
+ const uninstallEnv = options.env ?? process.env;
2509
+ for (const agent of AGENT_IDS) {
2510
+ try {
2511
+ if (routingInstalled(agent, paths.homeDir, uninstallEnv)) {
2512
+ removeAgentRouting(agent, paths.homeDir, uninstallEnv);
2513
+ removed.push(`agent routing (${agentLabel(agent)})`);
2514
+ }
2515
+ } catch (err) {
2516
+ warnings.push(`could not remove ${agentLabel(agent)} routing: ${err.message}`);
2517
+ }
2518
+ }
1795
2519
  if (!options.all && !registryRead.malformed && options.keepConfig) {
1796
2520
  writeRegistryWithLock(paths, {
1797
2521
  version: 1,
@@ -1804,6 +2528,9 @@ function uninstallSetup(options) {
1804
2528
  if (!options.keepConfig && hadStateDirBeforeLock) {
1805
2529
  removeDirectory(paths.stateDir, removed, missing);
1806
2530
  }
2531
+ if (!options.all && !options.keepConfig && clearAuthState(uninstallEnv)) {
2532
+ removed.push(authPath(paths));
2533
+ }
1807
2534
  if (options.all) {
1808
2535
  removeDirectory(paths.configDir, removed, missing);
1809
2536
  }
@@ -1822,15 +2549,15 @@ function writeRcFileAtomic(rcPath, content) {
1822
2549
  let mode = 420;
1823
2550
  try {
1824
2551
  target = realpathSync(rcPath);
1825
- mode = statSync3(target).mode & 4095;
2552
+ mode = statSync4(target).mode & 4095;
1826
2553
  } catch {
1827
2554
  }
1828
- const tempPath = join10(dirname3(target), `.${basename(target)}.dg-${randomBytes2(6).toString("hex")}.tmp`);
1829
- writeFileSync3(tempPath, content, { encoding: "utf8", mode, flag: "wx" });
2555
+ const tempPath = join12(dirname5(target), `.${basename2(target)}.dg-${randomBytes3(6).toString("hex")}.tmp`);
2556
+ writeFileSync5(tempPath, content, { encoding: "utf8", mode, flag: "wx" });
1830
2557
  try {
1831
- renameSync4(tempPath, target);
2558
+ renameSync5(tempPath, target);
1832
2559
  } catch (error) {
1833
- rmSync4(tempPath, { force: true });
2560
+ rmSync6(tempPath, { force: true });
1834
2561
  throw error;
1835
2562
  }
1836
2563
  }
@@ -1839,7 +2566,7 @@ function stripRcBlockDetailed(existing) {
1839
2566
  const repairedLines = [];
1840
2567
  for (; ; ) {
1841
2568
  const lines = content.split("\n");
1842
- const begin = lines.indexOf(RC_BEGIN);
2569
+ const begin = lines.findIndex((line) => line.replace(/\r$/, "") === RC_BEGIN);
1843
2570
  if (begin === -1) {
1844
2571
  break;
1845
2572
  }
@@ -1854,14 +2581,15 @@ function stripRcBlockDetailed(existing) {
1854
2581
  return { content, repairedLines };
1855
2582
  }
1856
2583
  function rcPairPattern(begin, end) {
1857
- return new RegExp(`${escapeRegex(begin)}\\n(?:(?!${escapeRegex(begin)})[\\s\\S])*?${escapeRegex(end)}\\n?`, "g");
2584
+ return new RegExp(`${escapeRegex2(begin)}\\r?\\n(?:(?!${escapeRegex2(begin)})[\\s\\S])*?${escapeRegex2(end)}\\r?\\n?`, "g");
1858
2585
  }
1859
2586
  function isDgWrittenRcLine(line) {
1860
- return line === RC_END || line.startsWith("# dg-") || line.includes(RC_SHIM_HELPER) || line.includes(`${sep}.dg${sep}shims`);
2587
+ const trimmed = line.replace(/\r$/, "");
2588
+ return trimmed === RC_END || trimmed.startsWith("# dg-") || trimmed.includes(RC_SHIM_HELPER) || trimmed.includes(`${sep2}.dg${sep2}shims`);
1861
2589
  }
1862
2590
  function sweepLegacyRcBlocks(homeDir, removed, warnings) {
1863
2591
  for (const rel of LEGACY_RC_CANDIDATES) {
1864
- const rcPath = join10(homeDir, rel);
2592
+ const rcPath = join12(homeDir, rel);
1865
2593
  const existing = readText(rcPath);
1866
2594
  if (!existing) {
1867
2595
  continue;
@@ -1894,8 +2622,8 @@ function isLegacyPthHook(pthPath) {
1894
2622
  }
1895
2623
  function sweepLegacyPythonHooks(homeDir, removed, warnings) {
1896
2624
  for (const dir of candidateSitePackagesDirs(homeDir)) {
1897
- const pyPath = join10(dir, LEGACY_PYTHON_HOOK_PY);
1898
- const pthPath = join10(dir, LEGACY_PYTHON_HOOK_PTH);
2625
+ const pyPath = join12(dir, LEGACY_PYTHON_HOOK_PY);
2626
+ const pthPath = join12(dir, LEGACY_PYTHON_HOOK_PTH);
1899
2627
  const pyIsHook = readText(pyPath).includes(LEGACY_PYTHON_HOOK_MARKER);
1900
2628
  const pthIsHook = isLegacyPthHook(pthPath);
1901
2629
  if (!pyIsHook && !pthIsHook) {
@@ -1911,7 +2639,7 @@ function sweepLegacyPythonHooks(homeDir, removed, warnings) {
1911
2639
  }
1912
2640
  function removePythonHookFile(path, removed, warnings) {
1913
2641
  try {
1914
- rmSync4(path, { force: true });
2642
+ rmSync6(path, { force: true });
1915
2643
  removed.push(`${path} (legacy dg pip hook)`);
1916
2644
  } catch (error) {
1917
2645
  warnings.push(`could not remove legacy dg pip hook ${path}: ${error instanceof Error ? error.message : "remove error"}`);
@@ -1919,26 +2647,26 @@ function removePythonHookFile(path, removed, warnings) {
1919
2647
  }
1920
2648
  function candidateSitePackagesDirs(homeDir) {
1921
2649
  const dirs = [];
1922
- for (const version of safeReaddir(join10(homeDir, "Library", "Python"))) {
1923
- dirs.push(join10(homeDir, "Library", "Python", version, "lib", "python", "site-packages"));
2650
+ for (const version of safeReaddir(join12(homeDir, "Library", "Python"))) {
2651
+ dirs.push(join12(homeDir, "Library", "Python", version, "lib", "python", "site-packages"));
1924
2652
  }
1925
- for (const entry of safeReaddir(join10(homeDir, ".local", "lib"))) {
2653
+ for (const entry of safeReaddir(join12(homeDir, ".local", "lib"))) {
1926
2654
  if (entry.startsWith("python")) {
1927
- dirs.push(join10(homeDir, ".local", "lib", entry, "site-packages"));
2655
+ dirs.push(join12(homeDir, ".local", "lib", entry, "site-packages"));
1928
2656
  }
1929
2657
  }
1930
2658
  return dirs;
1931
2659
  }
1932
2660
  function safeReaddir(dir) {
1933
2661
  try {
1934
- return readdirSync2(dir);
2662
+ return readdirSync3(dir);
1935
2663
  } catch {
1936
2664
  return [];
1937
2665
  }
1938
2666
  }
1939
2667
  function readRegistry(paths) {
1940
2668
  try {
1941
- if (!existsSync2(paths.cleanupRegistryPath)) {
2669
+ if (!existsSync4(paths.cleanupRegistryPath)) {
1942
2670
  return {
1943
2671
  registry: {
1944
2672
  version: 1,
@@ -1947,7 +2675,7 @@ function readRegistry(paths) {
1947
2675
  malformed: false
1948
2676
  };
1949
2677
  }
1950
- const registry = JSON.parse(readFileSync4(paths.cleanupRegistryPath, "utf8"));
2678
+ const registry = JSON.parse(readFileSync6(paths.cleanupRegistryPath, "utf8"));
1951
2679
  if (registry.version !== 1 || !Array.isArray(registry.entries)) {
1952
2680
  throw new Error("unsupported cleanup registry");
1953
2681
  }
@@ -1968,21 +2696,21 @@ function readRegistry(paths) {
1968
2696
  }
1969
2697
  }
1970
2698
  function writeRegistry(paths, registry) {
1971
- mkdirSync4(dirname3(paths.cleanupRegistryPath), {
2699
+ mkdirSync6(dirname5(paths.cleanupRegistryPath), {
1972
2700
  recursive: true,
1973
2701
  mode: 448
1974
2702
  });
1975
- const tempPath = `${paths.cleanupRegistryPath}.${randomBytes2(6).toString("hex")}.tmp`;
1976
- writeFileSync3(tempPath, `${JSON.stringify(registry, null, 2)}
2703
+ const tempPath = `${paths.cleanupRegistryPath}.${randomBytes3(6).toString("hex")}.tmp`;
2704
+ writeFileSync5(tempPath, `${JSON.stringify(registry, null, 2)}
1977
2705
  `, {
1978
2706
  encoding: "utf8",
1979
2707
  mode: 384,
1980
2708
  flag: "wx"
1981
2709
  });
1982
2710
  try {
1983
- renameSync4(tempPath, paths.cleanupRegistryPath);
2711
+ renameSync5(tempPath, paths.cleanupRegistryPath);
1984
2712
  } catch (error) {
1985
- rmSync4(tempPath, { force: true });
2713
+ rmSync6(tempPath, { force: true });
1986
2714
  throw error;
1987
2715
  }
1988
2716
  }
@@ -2000,15 +2728,15 @@ function writeRegistryWithLock(paths, registry) {
2000
2728
  withRegistryLock(paths, () => writeRegistry(paths, registry));
2001
2729
  }
2002
2730
  function removeShim(entry, removed, missing, warnings) {
2003
- if (!existsSync2(entry.path)) {
2731
+ if (!existsSync4(entry.path)) {
2004
2732
  missing.push(entry.path);
2005
2733
  return;
2006
2734
  }
2007
- if (!validShim(entry.path, basename(entry.path))) {
2735
+ if (!validShim(entry.path, basename2(entry.path))) {
2008
2736
  warnings.push(`refused to remove drifted shim: ${entry.path}`);
2009
2737
  return;
2010
2738
  }
2011
- rmSync4(entry.path, {
2739
+ rmSync6(entry.path, {
2012
2740
  force: true
2013
2741
  });
2014
2742
  removed.push(entry.path);
@@ -2038,11 +2766,11 @@ function removeRcBlock(entry, removed, missing, warnings) {
2038
2766
  function reverseGitHookEntry(entry, removed, missing, warnings) {
2039
2767
  const sentinel = entry.sentinel ?? GUARD_HOOK_SENTINEL;
2040
2768
  let ownsTarget = false;
2041
- if (!existsSync2(entry.path)) {
2769
+ if (!existsSync4(entry.path)) {
2042
2770
  missing.push(entry.path);
2043
2771
  ownsTarget = true;
2044
2772
  } else if (readText(entry.path).split("\n", 2)[1]?.includes(sentinel)) {
2045
- rmSync4(entry.path, { force: true });
2773
+ rmSync6(entry.path, { force: true });
2046
2774
  removed.push(entry.path);
2047
2775
  ownsTarget = true;
2048
2776
  } else {
@@ -2052,9 +2780,9 @@ function reverseGitHookEntry(entry, removed, missing, warnings) {
2052
2780
  return;
2053
2781
  }
2054
2782
  if (entry.original) {
2055
- if (existsSync2(entry.original)) {
2783
+ if (existsSync4(entry.original)) {
2056
2784
  try {
2057
- renameSync4(entry.original, entry.path);
2785
+ renameSync5(entry.original, entry.path);
2058
2786
  removed.push(entry.original);
2059
2787
  } catch (error) {
2060
2788
  warnings.push(`could not restore chained hook ${entry.original}: ${error instanceof Error ? error.message : "unknown error"}`);
@@ -2065,18 +2793,18 @@ function reverseGitHookEntry(entry, removed, missing, warnings) {
2065
2793
  }
2066
2794
  }
2067
2795
  function removeDirectory(path, removed, missing) {
2068
- if (!existsSync2(path)) {
2796
+ if (!existsSync4(path)) {
2069
2797
  missing.push(path);
2070
2798
  return;
2071
2799
  }
2072
- rmSync4(path, {
2800
+ rmSync6(path, {
2073
2801
  force: true,
2074
2802
  recursive: true
2075
2803
  });
2076
2804
  removed.push(path);
2077
2805
  }
2078
2806
  function validShim(path, command) {
2079
- if (!existsSync2(path)) {
2807
+ if (!existsSync4(path)) {
2080
2808
  return false;
2081
2809
  }
2082
2810
  return isValidShimSource(readText(path), command);
@@ -2089,12 +2817,12 @@ function isValidShimSource(content, command) {
2089
2817
  }
2090
2818
  function readText(path) {
2091
2819
  try {
2092
- return readFileSync4(path, "utf8");
2820
+ return readFileSync6(path, "utf8");
2093
2821
  } catch {
2094
2822
  return "";
2095
2823
  }
2096
2824
  }
2097
- function escapeRegex(value) {
2825
+ function escapeRegex2(value) {
2098
2826
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2099
2827
  }
2100
2828
 
@@ -2103,7 +2831,7 @@ init_state();
2103
2831
  function run() {
2104
2832
  const quiet = process.argv.includes("--quiet");
2105
2833
  try {
2106
- const result = uninstallSetup({ keepConfig: false, all: true });
2834
+ const result = uninstallSetup({ keepConfig: true, all: false });
2107
2835
  if (!quiet) {
2108
2836
  process.stderr.write(`Dependency Guardian cleaned up ${result.removed.length} leftover item(s) after the package was removed.
2109
2837
  `);
@@ -2115,7 +2843,7 @@ function run() {
2115
2843
  }
2116
2844
  }
2117
2845
  try {
2118
- rmSync5(join11(resolveDgPaths().homeDir, ".dg"), { recursive: true, force: true });
2846
+ rmSync7(join13(resolveDgPaths().homeDir, ".dg", "shims"), { recursive: true, force: true });
2119
2847
  } catch {
2120
2848
  return;
2121
2849
  }